Groundwater Flow Problem Definition#

Purpose#

This page defines the common groundwater problem carried by the [flow] layer, before one backend translates it into MODFLOW-NWT, MODFLOW 6, or the in-house Boussinesq solver.

The goal is not to pretend that all backends solve the exact same discrete equations. The goal is to state the shared scientific contract:

  • the primary unknown is hydraulic head,

  • the problem is driven by storage, transmissive flow, boundary exchanges, recharge, and wells,

  • and the runtime Flow object is the canonical place where those meanings are expressed before backend-specific assembly.

What The [flow] Layer Represents#

The Flow process is the canonical project-level description of a groundwater simulation problem.

It groups:

  • hydraulic properties,

  • initial conditions,

  • boundary conditions,

  • sinks and sources,

  • regime information such as steady or transient execution.

In code, the main runtime object is hydromodpy.physics.flow.flow.Flow. Scientifically, it should be read as the project-level statement:

Given one aquifer geometry, one parameterization, one initial state, and one set of forcings and exchanges, solve for groundwater head over space and time.

Generic Solver-Agnostic Statement#

At the most generic level, HydroModPy represents a head problem driven by:

  • storage or accumulation,

  • internal transmissive exchanges inside the aquifer,

  • imposed-head boundaries,

  • head-dependent exchanges such as drainage,

  • diffuse areal forcing such as recharge or evapotranspiration,

  • localized sources and sinks such as wells.

One convenient schematic balance is:

\[\mathcal{R}(h) = \mathcal{A}(h) + \mathcal{F}_{\mathrm{int}}(h) + \mathcal{F}_{\mathrm{bc}}(h) + \mathcal{Q}_{\mathrm{out}}(h) - \mathcal{Q}_{\mathrm{in}} = 0\]

where:

  • \(\mathcal{A}\) is the storage term in transient settings,

  • \(\mathcal{F}_{\mathrm{int}}\) is the internal groundwater-flow operator,

  • \(\mathcal{F}_{\mathrm{bc}}\) collects boundary exchanges driven by imposed heads or conductances,

  • \(\mathcal{Q}_{\mathrm{out}}\) collects sink terms,

  • \(\mathcal{Q}_{\mathrm{in}}\) collects source terms.

For readers who prefer PDE language, the same contract can be read schematically as:

\[S(h)\,\frac{\partial h}{\partial t} - \nabla \cdot \left(T(h)\nabla h\right) = q_{\mathrm{recharge}} + q_{\mathrm{inj}} - q_{\mathrm{pump}} - q_{\mathrm{drain}} - q_{\mathrm{evt}}\]

This PDE-style reading is intentionally schematic. HydroModPy does not force every backend into one identical continuous formulation:

  • MODFLOW-family backends express the problem through NPF, STO, CHD, DRN, RCHA, EVT, and WEL packages,

  • the Boussinesq backend makes thickness dependence and surface-interaction operators explicit in its finite-volume residual.

What This Looks Like In Results#

The shared problem definition is abstract, but the persisted outputs are not. On a basin run, the first two result families to inspect are usually the state field and the water budget.

Canonical Unknown And Parameters#

Across the current repository, the main project-level unknown is hydraulic head.

The most recurrent physical parameters are:

  • hydraulic conductivity K,

  • specific yield Sy,

  • specific storage Ss,

  • geometry-related fields such as topography and substratum.

The runtime layer normalizes them into solver-independent scientific families.

Quantity

Typical units

Meaning at [flow] level

Typical backend interpretation

Hydraulic head h

m

Primary state variable

IC / BAS initial heads, cell-centered unknown, diagnostics

Hydraulic conductivity K

m/s

Lateral transmissive capacity

NPF conductivity arrays, transmissivity in Boussinesq

Specific yield Sy

-

Unconfined storage

STO or effective storage term

Specific storage Ss

1/m

Compressible storage

STO or effective storage term

Topography / substratum

m

Aquifer support and thickness envelope

Layer geometry, top and bottom elevations, wetted thickness

Initial Conditions#

Initial conditions are declared in the flat [flow.ic] section. They define the initial hydraulic head h for the flow process before any backend translation takes place.

They are scientific choices about the starting state, not solver options. The same [flow.ic] contract is consumed by MODFLOW 6, MODFLOW-NWT, and the Boussinesq backend.

The supported type values are:

type

Meaning

Required / related keys

top

Initialize head from the aquifer top surface. This is close to a full aquifer initial state.

No value, unit, or units.

top_offset

Initialize head from top surface minus a vertical offset.

value is required and is a length.

bottom

Initialize head from the aquifer bottom surface. This is close to an empty aquifer initial state.

No value, unit, or units.

custom

Initialize all cells from one explicit scalar head.

value is required and is a length.

steady_state

Initialize a transient run from an auxiliary permanent solve performed by the same solver backend.

Strategy keys only: source, recharge_statistic, boundary_condition_policy. No value, unit, or units.

Examples:

[flow.ic]
type = "top"
[flow.ic]
type = "top_offset"
value = "2 m"
[flow.ic]
type = "custom"
value = "125 m"
[flow.ic]
type = "steady_state"
source = "mean_recharge"
recharge_statistic = "time_mean"
boundary_condition_policy = "first_period"

For steady_state, HydroModPy first builds a one-period permanent problem from the transient setup. Recharge is represented by its time mean over the transient simulation window. Time-varying boundary-condition values are reduced with the documented first_period policy. The resulting permanent head field is then injected as the initial head of the transient run.

This initialization is same-solver by construction: MODFLOW 6 initializes MODFLOW 6, MODFLOW-NWT initializes MODFLOW-NWT, and Boussinesq initializes Boussinesq. HydroModPy does not mix head fields across solver backends.

All length values are normalized to meters before backend translation. A non-empty [flow.ic] section must declare type explicitly. The [flow.ic] section is intentionally flat; nested forms such as [flow.ic.h], scalar shorthand forms such as flow.ic = 125.0, and value-only payloads such as [flow.ic] value = "125 m" are not part of the public contract.

Canonical Families Of Inputs#

The [flow] block currently exposes a stable set of scientific input families.

Initial conditions:

  • head initialized from top,

  • head initialized from top minus an offset,

  • head initialized from bottom,

  • custom scalar head,

  • same-solver steady-state initialization for transient runs.

Boundary conditions:

  • lateral Dirichlet conditions on side boundaries,

  • stream and ocean imposed-head style conditions,

  • drainage-type head-dependent exchange.

Sinks and sources:

  • diffuse recharge,

  • wells,

  • evapotranspiration-related terms where supported by the backend.

It is important to distinguish those families:

  • imposed-head boundaries prescribe a head value and let the exchanged flux emerge from the solve,

  • drainage is a head-dependent exchange law,

  • recharge and evapotranspiration are areal forcings,

  • wells are localized volumetric forcings.

Sign Conventions And Units#

The repository already uses a mostly coherent set of physical conventions at the Flow level.

Quantity

Units

Positive meaning

Current note

Hydraulic head

m

Higher piezometric level

Imposed-head boundaries store values in meters

Recharge

m/s

Water added to the aquifer

Normalized from data-manager conventions such as mm/day

Dedicated ETP

m/s

Water removed from the aquifer

Diffuse sink, mainly used through EVT-style assembly

Well flux

m3/s

Injection into the aquifer

Negative values mean pumping

Drainage conductance

m2/s

Stronger exchange capacity

Produces outflow only when the head exceeds the drainage level

Imposed-head stage

m

Not a signed flux

The sign of the resulting exchange depends on the solved head difference

One subtle but important distinction is this:

  • the physical sign convention above is the one to use when discussing project inputs,

  • each backend is still free to assemble its residual with its own internal algebraic sign convention.

For example, the Boussinesq residual uses positive residual contributions for water leaving the cell, while keeping the physical interpretation above.

Boundary-Condition Families#

HydroModPy currently exposes two main scientific boundary families.

Imposed-head family#

The following identifiers carry imposed-head semantics in the common layer:

  • west_side

  • east_side

  • north_side

  • south_side

  • stream

  • ocean

At this level, the scientific meaning is only:

  • one target support is selected,

  • one stage or head value is prescribed on that support,

  • the exchanged flux is not prescribed directly.

How that support is represented later depends on the backend:

  • structured rows and columns,

  • DISV support cells,

  • or boundary edges in the Boussinesq mesh.

Head-dependent exchange family#

drainage is the main current head-dependent exchange family. It should be read as:

  • a conductance-controlled release mechanism,

  • activated only when the groundwater state reaches the drainage threshold,

  • physically distinct from diffuse recharge,

  • physically distinct from direct runoff observations.

This distinction matters for interpretation:

  • recharge describes water entering the aquifer,

  • drainage describes water leaving the aquifer because the piezometric state meets one release condition,

  • runoff is not the same object and does not currently live in flow.sinks_sources.

What Is Solver-Agnostic And What Is Backend-Specific#

Solver-agnostic at [flow] level:

  • head as the primary unknown,

  • normalized units and sign conventions,

  • semantic boundary identifiers such as ocean or drainage,

  • semantic forcing families such as recharge, ETP, and wells.

Backend-specific:

  • exact spatial discretization,

  • the detailed transmissive law,

  • the exact package set or operator split,

  • the representation of stream and ocean exchange,

  • the surface-interaction closure used by the Boussinesq solver,

  • optional numerical features such as XT3D or rewetting.

Current Backend Interpretations#

Backend family

What remains the same

What becomes backend-specific

MODFLOW-NWT / MODFLOW 6

Head-based groundwater problem with recharge, wells, imposed heads, drainage, and storage

Package assembly, structured versus DISV support, XT3D, rewetting, detailed treatment of RCHA / EVT / DRN / CHD

Boussinesq

Head-based groundwater problem with the same physical families of forcing and exchange

Explicit finite-volume residual, thickness-dependent transmissivity, top drainage operator, and optional surface-interaction closure

Representative Validation Anchors#

The generic contract described on this page is not only conceptual. Several gallery pages already exercise its main families of forcing and exchange.

Why This Page Matters#

Without this page, readers have to infer the scientific contract by combining:

  • hydromodpy.physics.flow.flow.py,

  • backend adapter code,

  • validation-case names,

  • and scattered developer notes.

That is workable for maintainers, but it is too indirect for new contributors, for scientific review, and for explaining why several numerical backends can still belong to one modelling framework.

Current Source Anchors#

The most relevant anchors for the current version are: