WaterTableDepth
Water table depth z_v as a function of unconfined-aquifer water storage W_a and the depth of the bottom soil interface z_h_bottom. Implements Oleson et al. (2010) CLM Tech Note Eq. 5.146 (p. 143) with hard clamps at z_v_min = 0.05 m and z_v_max = 80 m. Migrated from UrbanCanopy.jl@9200edd4 src/hydrology.jl:743 (`WaterTableDepth` @component). Observed-only: z_h_bottom and W_a are parameters and z_v is given by a single algebraic equation.
Description
Water table depth z_v as a function of unconfined-aquifer water storage W_a and the depth of the bottom soil interface z_h_bottom. Implements Oleson et al. (2010) CLM Tech Note Eq. 5.146 (p. 143) with hard clamps at z_v_min = 0.05 m and z_v_max = 80 m. Migrated from UrbanCanopy.jl@9200edd4 src/hydrology.jl:743 (WaterTableDepth @component). Observed-only: z_h_bottom and W_a are parameters and z_v is given by a single algebraic equation.
Reference
_source_ref: UrbanCanopy.jl@9200edd4f15609f20339d3a7d104de8064544310:src/hydrology.jl:743
Upstream WaterTableDepth is an MTK @component whose two inputs (z_h_bottom, W_a) are @parameters, whose five @constants (S_y, z_v_min, z_v_max, z_offset, ρ_liq) are physical constants, and whose single output (z_v) is a time-indexed @variable with one algebraic equation. Identical structure preserved here.
Upstream @constants are encoded as parameters with the upstream default values, mirroring the convention established by the sibling files in this directory (snow_compaction.esm, soil_water_content_calc.esm, interface_hydraulic_conductivity.esm). They are physical constants not intended to be tuned.
Unicode ρ_liq is preserved from upstream — sibling files in this directory (soil_water_content_calc.esm, interface_hydraulic_conductivity.esm) already established that unicode identifiers are the rig convention for new urban_canopy migrations and the canonical Python runner accepts them.
The equation is the verbatim Eq. 5.146 form: z_v = clamp(z_h_bottom + z_offset - W_a / (ρ_liq * S_y), z_v_min, z_v_max), expressed as max(z_v_min, min(z_v_max, ...)) to match the upstream Julia source ordering of the clamps. With W_a in kg/m² and ρ_liq in kg/m³, W_a/ρ_liq gives meters of equivalent water column; dividing by S_y (specific yield, dimensionless) converts to water-table depth contribution in m.
Observability classification: this component is functionally observed-only — z_v is given by a single algebraic equation in the parameters. The (t) time index has no role since there is no derivative. Test scenarios use time_span: [0, 1] and sample at t=0 to mirror the convention used by the other observed-only ESM files in this directory (soil_water_content_calc.esm, interface_hydraulic_conductivity.esm).
Default parameter values: z_h_bottom = 3.5 m and W_a = 4800 kg/m² are taken from the upstream WaterTableDepth - Equation Verification test fixture (UrbanCanopy.jl test/hydrology_test.jl:486). They yield the canonical mid-range value z_v = 3.5 + 25 - 4800/(1000*0.2) = 4.5 m, well within both clamp bounds — so the no-override default scenario evaluates the unclamped branch of Eq. 5.146 directly.
Tolerance rationale (model-level rel=1e-9): observed-only algebraic system (no ODE integration); the equation involves five IEEE-754 float64 operations (add, subtract, multiply, divide, two compare-selects), so worst-case roundoff is ~5*ULP ≈ 1e-15. 1e-9 leaves comfortable headroom and is well below any plausible physical-discrimination scale on water table depth (which spans ~3 orders of magnitude across the 0.05 m to 80 m clamp range and is typically known to ~1 cm in observations). Clamp tests assert tight equality (abs: 1e-12) since the clamp produces an exact algebraic value once active._
Parameters
| Name | Units | Default | Description |
|---|---|---|---|
S_y | 1 | 0.2 | Specific yield (Oleson Eq. 5.146, dimensionless) |
z_v_min | m | 0.05 | Minimum water table depth (lower clamp of Eq. 5.146) |
z_v_max | m | 80.0 | Maximum water table depth (upper clamp of Eq. 5.146) |
z_offset | m | 25.0 | Offset for water table calculation (Eq. 5.146) |
ρ_liq | kg/m^3 | 1000.0 | Density of liquid water (Oleson Table 1.4) |
z_h_bottom | m | 3.5 | Depth of bottom soil interface |
W_a | kg/m^2 | 4800.0 | Water stored in unconfined aquifer (kg/m^2; equivalent to mm of water column) |
Observed
| Name | Units | Default | Description |
|---|---|---|---|
z_v | m | Water table depth (Oleson Eq. 5.146) |
Observed expressions
$$ z_{v} = \mathrm{max}\left(z_{v\,min}, \mathrm{min}\left(z_{v\,max}, z_{h\,bottom} + z_{offset} - \frac{W_{a}}{ρ_{liq} \cdot S_{y}}\right)\right) $$Water table depth (Oleson Eq. 5.146)
Analyses
z_v_vs_W_a
Water table depth vs. aquifer water storage at fixed z_h_bottom = 3.5 m. Reproduces the upstream qualitative-behavior plot (UrbanCanopy.jl test/hydrology_test.jl:917): sweeping W_a from 0 to 6000 kg/m² traces the linear branch of Eq. 5.146 from the upper region of the soil column through the lower-clamp activation at W_a ≈ 5690 kg/m².
Time span: 0.0 → 1.0
Swept over: W_a

z_v_vs_W_a_and_z_h_bottom
Joint sweep over W_a and z_h_bottom — surfaces the iso-z_v contours of Eq. 5.146 across the (aquifer storage, soil-column depth) plane. The unclamped branch is a plane in this space (z_v = z_h_bottom + 25 - W_a/200); the lower- and upper-clamp regions appear as flat plateaux at z_v = 0.05 m and z_v = 80 m respectively.
Time span: 0.0 → 1.0
Swept over: W_a, z_h_bottom

Raw .esm
Raw .esm JSON (this component)
{
"reference": {
"notes": "source_ref: UrbanCanopy.jl@9200edd4f15609f20339d3a7d104de8064544310:src/hydrology.jl:743\nUpstream `WaterTableDepth` is an MTK `@component` whose two inputs (z_h_bottom, W_a) are `@parameters`, whose five `@constants` (S_y, z_v_min, z_v_max, z_offset, ρ_liq) are physical constants, and whose single output (z_v) is a time-indexed `@variable` with one algebraic equation. Identical structure preserved here.\n\nUpstream `@constants` are encoded as parameters with the upstream default values, mirroring the convention established by the sibling files in this directory (snow_compaction.esm, soil_water_content_calc.esm, interface_hydraulic_conductivity.esm). They are physical constants not intended to be tuned.\n\nUnicode `ρ_liq` is preserved from upstream — sibling files in this directory (soil_water_content_calc.esm, interface_hydraulic_conductivity.esm) already established that unicode identifiers are the rig convention for new urban_canopy migrations and the canonical Python runner accepts them.\n\nThe equation is the verbatim Eq. 5.146 form: z_v = clamp(z_h_bottom + z_offset - W_a / (ρ_liq * S_y), z_v_min, z_v_max), expressed as `max(z_v_min, min(z_v_max, ...))` to match the upstream Julia source ordering of the clamps. With W_a in kg/m² and ρ_liq in kg/m³, W_a/ρ_liq gives meters of equivalent water column; dividing by S_y (specific yield, dimensionless) converts to water-table depth contribution in m.\n\nObservability classification: this component is functionally observed-only — z_v is given by a single algebraic equation in the parameters. The `(t)` time index has no role since there is no derivative. Test scenarios use `time_span: [0, 1]` and sample at t=0 to mirror the convention used by the other observed-only ESM files in this directory (soil_water_content_calc.esm, interface_hydraulic_conductivity.esm).\n\nDefault parameter values: z_h_bottom = 3.5 m and W_a = 4800 kg/m² are taken from the upstream `WaterTableDepth - Equation Verification` test fixture (UrbanCanopy.jl test/hydrology_test.jl:486). They yield the canonical mid-range value z_v = 3.5 + 25 - 4800/(1000*0.2) = 4.5 m, well within both clamp bounds — so the no-override default scenario evaluates the unclamped branch of Eq. 5.146 directly.\n\nTolerance rationale (model-level rel=1e-9): observed-only algebraic system (no ODE integration); the equation involves five IEEE-754 float64 operations (add, subtract, multiply, divide, two compare-selects), so worst-case roundoff is ~5*ULP ≈ 1e-15. 1e-9 leaves comfortable headroom and is well below any plausible physical-discrimination scale on water table depth (which spans ~3 orders of magnitude across the 0.05 m to 80 m clamp range and is typically known to ~1 cm in observations). Clamp tests assert tight equality (`abs: 1e-12`) since the clamp produces an exact algebraic value once active."
},
"tolerance": {
"rel": 1e-09
},
"variables": {
"S_y": {
"type": "parameter",
"units": "1",
"default": 0.2,
"description": "Specific yield (Oleson Eq. 5.146, dimensionless)"
},
"z_v_min": {
"type": "parameter",
"units": "m",
"default": 0.05,
"description": "Minimum water table depth (lower clamp of Eq. 5.146)"
},
"z_v_max": {
"type": "parameter",
"units": "m",
"default": 80.0,
"description": "Maximum water table depth (upper clamp of Eq. 5.146)"
},
"z_offset": {
"type": "parameter",
"units": "m",
"default": 25.0,
"description": "Offset for water table calculation (Eq. 5.146)"
},
"ρ_liq": {
"type": "parameter",
"units": "kg/m^3",
"default": 1000.0,
"description": "Density of liquid water (Oleson Table 1.4)"
},
"z_h_bottom": {
"type": "parameter",
"units": "m",
"default": 3.5,
"description": "Depth of bottom soil interface"
},
"W_a": {
"type": "parameter",
"units": "kg/m^2",
"default": 4800.0,
"description": "Water stored in unconfined aquifer (kg/m^2; equivalent to mm of water column)"
},
"z_v": {
"type": "unknown",
"units": "m",
"description": "Water table depth (Oleson Eq. 5.146)"
}
},
"equations": [
{
"lhs": "z_v",
"rhs": {
"op": "max",
"args": [
"z_v_min",
{
"op": "min",
"args": [
"z_v_max",
{
"op": "-",
"args": [
{
"op": "+",
"args": [
"z_h_bottom",
"z_offset"
]
},
{
"op": "/",
"args": [
"W_a",
{
"op": "*",
"args": [
"ρ_liq",
"S_y"
]
}
]
}
]
}
]
}
]
}
}
],
"tests": [
{
"id": "canonical_unclamped",
"description": "Canonical unclamped case from the upstream Equation Verification test (UrbanCanopy.jl test/hydrology_test.jl:486): z_h_bottom = 3.5 m, W_a = 4800 kg/m², S_y = 0.2, ρ_liq = 1000 kg/m³. z_v = 3.5 + 25 - 4800/(1000*0.2) = 28.5 - 24.0 = 4.5 m, well within the [0.05, 80] m clamp. Verifies the canonical Eq. 5.146 evaluation in the interior of the clamp.",
"parameter_overrides": {
"z_h_bottom": 3.5,
"W_a": 4800.0
},
"time_span": {
"start": 0.0,
"end": 1.0
},
"assertions": [
{
"variable": "z_v",
"time": 0.0,
"expected": 4.5
}
]
},
{
"id": "min_clamp_active",
"description": "Lower-clamp activation from upstream Equation Verification (UrbanCanopy.jl test/hydrology_test.jl:502): z_h_bottom = 3.5 m, W_a = 6000 kg/m². Unclamped value is 28.5 - 30.0 = -1.5 m which is below z_v_min = 0.05 m, so the max(z_v_min, ...) clamp pins z_v = 0.05 m. Verifies the lower-clamp branch of Eq. 5.146 (asserted at abs=1e-12 since the clamp is an exact value).",
"parameter_overrides": {
"z_h_bottom": 3.5,
"W_a": 6000.0
},
"time_span": {
"start": 0.0,
"end": 1.0
},
"assertions": [
{
"variable": "z_v",
"time": 0.0,
"expected": 0.05,
"tolerance": {
"abs": 1e-12
}
}
]
},
{
"id": "no_aquifer_water",
"description": "Empty-aquifer limit from upstream Equation Verification (UrbanCanopy.jl test/hydrology_test.jl:509): z_h_bottom = 3.5 m, W_a = 0 kg/m². z_v = 3.5 + 25 - 0 = 28.5 m, which is within the [0.05, 80] m clamp. Verifies that the unclamped formula handles the W_a = 0 boundary cleanly (the upper clamp test is exercised by the dedicated max_clamp_active scenario below).",
"parameter_overrides": {
"z_h_bottom": 3.5,
"W_a": 0.0
},
"time_span": {
"start": 0.0,
"end": 1.0
},
"assertions": [
{
"variable": "z_v",
"time": 0.0,
"expected": 28.5
}
]
},
{
"id": "max_clamp_active",
"description": "Upper-clamp activation: z_h_bottom = 60 m and a strongly negative W_a contribution would drive z_v above z_v_max = 80 m, but in the canonical formulation W_a ≥ 0, so we exercise the upper clamp by setting z_h_bottom = 100 m with W_a = 0 → unclamped value = 125 m, which the min(z_v_max, ...) clamp pins to z_v = 80 m. Verifies the upper-clamp branch of Eq. 5.146 (asserted at abs=1e-12 since the clamp is an exact value).",
"parameter_overrides": {
"z_h_bottom": 100.0,
"W_a": 0.0
},
"time_span": {
"start": 0.0,
"end": 1.0
},
"assertions": [
{
"variable": "z_v",
"time": 0.0,
"expected": 80.0,
"tolerance": {
"abs": 1e-12
}
}
]
},
{
"id": "shallow_column_partial_aquifer",
"description": "Shallow soil column with partially-charged aquifer: z_h_bottom = 1.0 m, W_a = 2000 kg/m². z_v = 1.0 + 25 - 2000/(1000*0.2) = 26.0 - 10.0 = 16.0 m, well within bounds. Exercises a different operating point (small z_h_bottom relative to z_offset) — the water table sits 16 m below the surface despite a shallow soil column, with the aquifer providing the dominant control.",
"parameter_overrides": {
"z_h_bottom": 1.0,
"W_a": 2000.0
},
"time_span": {
"start": 0.0,
"end": 1.0
},
"assertions": [
{
"variable": "z_v",
"time": 0.0,
"expected": 16.0
}
]
},
{
"id": "monotone_W_a_decreases_z_v",
"description": "Monotonicity check from upstream Qualitative Behavior (UrbanCanopy.jl test/hydrology_test.jl:917): increasing W_a should decrease z_v (more aquifer water → shallower water table). At W_a = 3000 kg/m², z_h_bottom = 3.5 m: z_v = 3.5 + 25 - 3000/(1000*0.2) = 28.5 - 15.0 = 13.5 m. Paired with the canonical_unclamped scenario (W_a = 4800 → z_v = 4.5 m) this confirms z_v monotonically decreases as W_a grows.",
"parameter_overrides": {
"z_h_bottom": 3.5,
"W_a": 3000.0
},
"time_span": {
"start": 0.0,
"end": 1.0
},
"assertions": [
{
"variable": "z_v",
"time": 0.0,
"expected": 13.5
}
]
},
{
"id": "exact_min_clamp_boundary",
"description": "Boundary case where the unclamped value lands exactly at z_v_min: z_h_bottom = 3.5 m, W_a = 5690 kg/m² → unclamped = 3.5 + 25 - 5690/200 = 28.5 - 28.45 = 0.05 m. Exercises the algebraic equality at the lower clamp boundary (max(z_v_min, 0.05) = 0.05) without needing the clamp to actively pin.",
"parameter_overrides": {
"z_h_bottom": 3.5,
"W_a": 5690.0
},
"time_span": {
"start": 0.0,
"end": 1.0
},
"assertions": [
{
"variable": "z_v",
"time": 0.0,
"expected": 0.05,
"tolerance": {
"abs": 1e-12
}
}
]
}
],
"analyses": [
{
"id": "z_v_vs_W_a",
"description": "Water table depth vs. aquifer water storage at fixed z_h_bottom = 3.5 m. Reproduces the upstream qualitative-behavior plot (UrbanCanopy.jl test/hydrology_test.jl:917): sweeping W_a from 0 to 6000 kg/m² traces the linear branch of Eq. 5.146 from the upper region of the soil column through the lower-clamp activation at W_a ≈ 5690 kg/m².",
"initial_state": {},
"parameters": {
"z_h_bottom": 3.5
},
"time_span": {
"start": 0.0,
"end": 1.0
},
"parameter_sweep": {
"type": "cartesian",
"dimensions": [
{
"parameter": "W_a",
"range": {
"start": 0.0,
"stop": 6000.0,
"count": 25,
"scale": "linear"
}
}
]
},
"plots": [
{
"id": "z_v_vs_W_a_line",
"type": "line",
"description": "z_v vs W_a — linear decrease through the unclamped branch, then a flat segment once W_a exceeds ~5690 kg/m² and the lower clamp activates.",
"x": {
"variable": "W_a",
"label": "W_a (kg/m^2)"
},
"y": {
"variable": "z_v",
"label": "z_v (m)"
}
}
]
},
{
"id": "z_v_vs_W_a_and_z_h_bottom",
"description": "Joint sweep over W_a and z_h_bottom — surfaces the iso-z_v contours of Eq. 5.146 across the (aquifer storage, soil-column depth) plane. The unclamped branch is a plane in this space (z_v = z_h_bottom + 25 - W_a/200); the lower- and upper-clamp regions appear as flat plateaux at z_v = 0.05 m and z_v = 80 m respectively.",
"initial_state": {},
"parameters": {},
"time_span": {
"start": 0.0,
"end": 1.0
},
"parameter_sweep": {
"type": "cartesian",
"dimensions": [
{
"parameter": "W_a",
"range": {
"start": 0.0,
"stop": 6000.0,
"count": 13,
"scale": "linear"
}
},
{
"parameter": "z_h_bottom",
"range": {
"start": 0.5,
"stop": 5.0,
"count": 10,
"scale": "linear"
}
}
]
},
"plots": [
{
"id": "z_v_heatmap",
"type": "heatmap",
"description": "z_v as a function of aquifer storage and soil-column depth — diagonal iso-z_v contours in the unclamped region with horizontal plateaux where the lower clamp activates.",
"x": {
"variable": "W_a",
"label": "W_a (kg/m^2)"
},
"y": {
"variable": "z_h_bottom",
"label": "z_h_bottom (m)"
},
"value": {
"variable": "z_v",
"reduce": "final"
}
}
]
}
]
}