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
Flowobject 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:
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:
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, andWELpackages,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 |
Typical backend interpretation |
|---|---|---|---|
Hydraulic head |
|
Primary state variable |
|
Hydraulic conductivity |
|
Lateral transmissive capacity |
|
Specific yield |
|
Unconfined storage |
|
Specific storage |
|
Compressible storage |
|
Topography / substratum |
|
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:
|
Meaning |
Required / related keys |
|---|---|---|
|
Initialize head from the aquifer top surface. This is close to a full aquifer initial state. |
No |
|
Initialize head from top surface minus a vertical offset. |
|
|
Initialize head from the aquifer bottom surface. This is close to an empty aquifer initial state. |
No |
|
Initialize all cells from one explicit scalar head. |
|
|
Initialize a transient run from an auxiliary permanent solve performed by the same solver backend. |
Strategy keys only: |
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 |
|
Higher piezometric level |
Imposed-head boundaries store values in meters |
Recharge |
|
Water added to the aquifer |
Normalized from data-manager conventions such as |
Dedicated ETP |
|
Water removed from the aquifer |
Diffuse sink, mainly used through |
Well flux |
|
Injection into the aquifer |
Negative values mean pumping |
Drainage conductance |
|
Stronger exchange capacity |
Produces outflow only when the head exceeds the drainage level |
Imposed-head stage |
|
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_sideeast_sidenorth_sidesouth_sidestreamocean
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
oceanordrainage,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 |
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.
Side imposed heads plus steady recharge: Dupuit Uniform Recharge 1D
Divide plus downstream river-stage interpretation: Dupuit Divide-River 1D
Transient recharge propagation: Linearized Unconfined 1D Recharge Step
Drainage as head-dependent release: Linearized Unconfined Drainage 1D
Ocean boundary in 2D: Dupuit Circular-Island Ocean 2D
Thickness-dependent Boussinesq and ocean support behaviour: Boussinesq Circular-Island Piecewise-K 2D
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:
hydromodpy.physics.flow.flowhydromodpy.physics.flow.flow_confighydromodpy.physics.flow.boundary_conditionshydromodpy.physics.flow.boundary_condition_registryhydromodpy.physics.flow.sinks_sourceshydromodpy.physics.flow.initial_conditions