Version: dev

SurfaceLayerUpdate

Top-layer ice and liquid water mass-rate updates from surface dew, frost, and sublimation, following Oleson et al. (2010, CLM Tech Note Ch. 5) Eqs. 5.150-5.152. Migrated from UrbanCanopy.jl@9200edd4 src/hydrology.jl:860 (`SurfaceLayerUpdate` @component). Parameterized as observed-only: q_sdew, q_frost, q_subl are inputs (parameters); dw_liq_1, dw_ice_1_frost, dw_ice_1_subl are algebraic outputs that pass each input through (with a sign flip on sublimation). Applies to the top layer of all surfaces (roof, pervious road, impervious road).

Domain
urban_canopy
Subdomain
hydro
Type
model
.esm schema
1.0.0
Source
components/urban_canopy/hydro/surface_layer_update.esm
Tags
#urban_canopy #hydro #model #hydrology #surface_layer #observed-only #clmu

Description

Top-layer ice and liquid water mass-rate updates from surface dew, frost, and sublimation, following Oleson et al. (2010, CLM Tech Note Ch. 5) Eqs. 5.150-5.152. Migrated from UrbanCanopy.jl@9200edd4 src/hydrology.jl:860 (SurfaceLayerUpdate @component). Parameterized as observed-only: q_sdew, q_frost, q_subl are inputs (parameters); dw_liq_1, dw_ice_1_frost, dw_ice_1_subl are algebraic outputs that pass each input through (with a sign flip on sublimation). Applies to the top layer of all surfaces (roof, pervious road, impervious road).

Reference

_source_ref: UrbanCanopy.jl@9200edd4f15609f20339d3a7d104de8064544310:src/hydrology.jl:860 Upstream SurfaceLayerUpdate is an MTK @component whose three inputs (q_sdew, q_frost, q_subl) are @parameters and whose three outputs (dw_liq_1, dw_ice_1_frost, dw_ice_1_subl) are time-indexed @variables with algebraic-only equations (no derivatives). The three equations are: • dw_liq_1 ~ q_sdew (Eq. 5.150 — rate form) • dw_ice_1_frost ~ q_frost (Eq. 5.151 — rate form) • dw_ice_1_subl ~ -q_subl (Eq. 5.152 — rate form, sublimation removes ice) Identical structure preserved here. The negation in Eq. 5.152 is encoded as multiplication by -1 — the same pattern used by snow_compaction.esm for C_R1 = -c_3 * ....

Observability classification: this component is functionally observed-only — every output is given by a single algebraic equation in terms of the parameters (and 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 rig (e.g. soil_water_content_calc.esm, snow_melt_no_layers.esm).

Tolerance rationale (model-level rel=1e-9): observed-only algebraic system (no ODE integration); two of the three equations are pass-through (zero floating-point ops), and the third is a single negation (one IEEE-754 sign flip — exact). Round-off is ~1e-16. 1e-9 leaves comfortable headroom and is well below any plausible physical-discrimination scale on surface mass fluxes (which are typically 1e-7 to 1e-3 kg/(m^2*s) for dew/frost/sublimation in CLMU). Branches where the expected value is exactly zero by construction add abs: 1e-15 to guard against silent stuck-at-large regressions._

Parameters

NameUnitsDefaultDescription
q_sdewkg/(m^2*s)0.0Surface dew rate (liquid condensation onto the surface)
q_frostkg/(m^2*s)0.0Frost rate (vapor deposition as ice)
q_sublkg/(m^2*s)0.0Sublimation rate (ice → vapor; sign-flipped on the ice-mass tendency)

Observed

NameUnitsDefaultDescription
dw_liq_1kg/(m^2*s)Rate of change of top-layer liquid water from dew (Oleson Eq. 5.150): dw_liq_1 = q_sdew
dw_ice_1_frostkg/(m^2*s)Rate of change of top-layer ice from frost (Oleson Eq. 5.151): dw_ice_1_frost = q_frost
dw_ice_1_sublkg/(m^2*s)Rate of change of top-layer ice from sublimation (Oleson Eq. 5.152): dw_ice_1_subl = -q_subl

Observed expressions

$$ dw_{liq\,1} = q_{sdew} $$

Rate of change of top-layer liquid water from dew (Oleson Eq. 5.150): dw_liq_1 = q_sdew

$$ dw_{ice\,1\,frost} = q_{frost} $$

Rate of change of top-layer ice from frost (Oleson Eq. 5.151): dw_ice_1_frost = q_frost

$$ dw_{ice\,1\,subl} = \left(-1\right) \cdot q_{subl} $$

Rate of change of top-layer ice from sublimation (Oleson Eq. 5.152): dw_ice_1_subl = -q_subl

Analyses

sublimation_response_curve

Sweep the sublimation rate q_subl across the typical CLMU range (0 to 1e-5 kg/(m^2*s)). dw_ice_1_subl traces a straight line from 0 to -1e-5 — visualizing the sign-flip of Eq. 5.152. The other two tendencies stay pinned at zero across the sweep.

Time span: 0.0 → 1.0

Swept over: q_subl

dw_ice_1_subl vs q_subl — straight line through the origin with slope -1, exhibiting Eq. 5.152.

dew_frost_phase_partition

Joint sweep of dew (q_sdew) and frost (q_frost) rates at fixed zero sublimation. Surfaces the independence of the liquid- and ice-tendency channels: dw_liq_1 depends only on q_sdew, dw_ice_1_frost only on q_frost. Useful as a regression baseline confirming that no cross-coupling has been silently introduced.

Time span: 0.0 → 1.0

Swept over: q_sdew, q_frost

dw_liq_1 vs (q_sdew, q_frost) — must vary only along the q_sdew axis.

dw_ice_1_frost vs (q_sdew, q_frost) — must vary only along the q_frost axis.

Raw .esm

Raw .esm JSON (this component)
{
  "reference": {
    "notes": "source_ref: UrbanCanopy.jl@9200edd4f15609f20339d3a7d104de8064544310:src/hydrology.jl:860\nUpstream `SurfaceLayerUpdate` is an MTK `@component` whose three inputs (q_sdew, q_frost, q_subl) are `@parameters` and whose three outputs (dw_liq_1, dw_ice_1_frost, dw_ice_1_subl) are time-indexed `@variables` with algebraic-only equations (no derivatives). The three equations are:\n  • dw_liq_1        ~  q_sdew    (Eq. 5.150 — rate form)\n  • dw_ice_1_frost  ~  q_frost   (Eq. 5.151 — rate form)\n  • dw_ice_1_subl   ~ -q_subl    (Eq. 5.152 — rate form, sublimation removes ice)\nIdentical structure preserved here. The negation in Eq. 5.152 is encoded as multiplication by -1 — the same pattern used by snow_compaction.esm for `C_R1 = -c_3 * ...`.\n\nObservability classification: this component is functionally observed-only — every output is given by a single algebraic equation in terms of the parameters (and 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 rig (e.g. soil_water_content_calc.esm, snow_melt_no_layers.esm).\n\nTolerance rationale (model-level rel=1e-9): observed-only algebraic system (no ODE integration); two of the three equations are pass-through (zero floating-point ops), and the third is a single negation (one IEEE-754 sign flip — exact). Round-off is ~1e-16. 1e-9 leaves comfortable headroom and is well below any plausible physical-discrimination scale on surface mass fluxes (which are typically 1e-7 to 1e-3 kg/(m^2*s) for dew/frost/sublimation in CLMU). Branches where the expected value is exactly zero by construction add `abs: 1e-15` to guard against silent stuck-at-large regressions."
  },
  "tolerance": {
    "rel": 1e-09
  },
  "variables": {
    "q_sdew": {
      "type": "parameter",
      "units": "kg/(m^2*s)",
      "default": 0.0,
      "description": "Surface dew rate (liquid condensation onto the surface)"
    },
    "q_frost": {
      "type": "parameter",
      "units": "kg/(m^2*s)",
      "default": 0.0,
      "description": "Frost rate (vapor deposition as ice)"
    },
    "q_subl": {
      "type": "parameter",
      "units": "kg/(m^2*s)",
      "default": 0.0,
      "description": "Sublimation rate (ice → vapor; sign-flipped on the ice-mass tendency)"
    },
    "dw_liq_1": {
      "type": "unknown",
      "units": "kg/(m^2*s)",
      "description": "Rate of change of top-layer liquid water from dew (Oleson Eq. 5.150): dw_liq_1 = q_sdew"
    },
    "dw_ice_1_frost": {
      "type": "unknown",
      "units": "kg/(m^2*s)",
      "description": "Rate of change of top-layer ice from frost (Oleson Eq. 5.151): dw_ice_1_frost = q_frost"
    },
    "dw_ice_1_subl": {
      "type": "unknown",
      "units": "kg/(m^2*s)",
      "description": "Rate of change of top-layer ice from sublimation (Oleson Eq. 5.152): dw_ice_1_subl = -q_subl"
    }
  },
  "equations": [
    {
      "lhs": "dw_liq_1",
      "rhs": "q_sdew"
    },
    {
      "lhs": "dw_ice_1_frost",
      "rhs": "q_frost"
    },
    {
      "lhs": "dw_ice_1_subl",
      "rhs": {
        "op": "*",
        "args": [
          -1,
          "q_subl"
        ]
      }
    }
  ],
  "tests": [
    {
      "id": "all_zero",
      "description": "No surface fluxes (all three rates zero). Each tendency must be exactly zero — the trivial baseline that confirms the equations and the runner do not introduce spurious offsets.",
      "parameter_overrides": {
        "q_sdew": 0.0,
        "q_frost": 0.0,
        "q_subl": 0.0
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "dw_liq_1",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        },
        {
          "variable": "dw_ice_1_frost",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        },
        {
          "variable": "dw_ice_1_subl",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        }
      ]
    },
    {
      "id": "dew_only",
      "description": "Surface dew at 1e-5 kg/(m^2*s) (a typical CLMU early-morning condensation rate, ~36 mm/hr peak), no frost, no sublimation. Eq. 5.150 routes the dew rate straight to dw_liq_1; the ice-tendency equations remain at zero.",
      "parameter_overrides": {
        "q_sdew": 1e-05,
        "q_frost": 0.0,
        "q_subl": 0.0
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "dw_liq_1",
          "time": 0.0,
          "expected": 1e-05
        },
        {
          "variable": "dw_ice_1_frost",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        },
        {
          "variable": "dw_ice_1_subl",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        }
      ]
    },
    {
      "id": "frost_only",
      "description": "Vapor deposition as frost (q_frost = 5e-6 kg/(m^2*s)) on a sub-freezing surface, no dew, no sublimation. Eq. 5.151 routes the frost rate to dw_ice_1_frost; dw_liq_1 and dw_ice_1_subl stay at zero. Verifies the frost branch is decoupled from the liquid-water branch.",
      "parameter_overrides": {
        "q_sdew": 0.0,
        "q_frost": 5e-06,
        "q_subl": 0.0
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "dw_liq_1",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        },
        {
          "variable": "dw_ice_1_frost",
          "time": 0.0,
          "expected": 5e-06
        },
        {
          "variable": "dw_ice_1_subl",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        }
      ]
    },
    {
      "id": "sublimation_only",
      "description": "Sublimation removes ice from the surface (q_subl = 2e-6 kg/(m^2*s)) with no dew or frost. Eq. 5.152 sign-flips the input: dw_ice_1_subl = -q_subl = -2e-6. The other two tendencies stay at zero. Crucial test of the only non-pass-through equation in the component.",
      "parameter_overrides": {
        "q_sdew": 0.0,
        "q_frost": 0.0,
        "q_subl": 2e-06
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "dw_liq_1",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        },
        {
          "variable": "dw_ice_1_frost",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        },
        {
          "variable": "dw_ice_1_subl",
          "time": 0.0,
          "expected": -2e-06
        }
      ]
    },
    {
      "id": "dew_plus_frost_morning",
      "description": "Pre-dawn near-freezing surface: liquid dew co-deposits with frost (q_sdew = 8e-6, q_frost = 3e-6 kg/(m^2*s)), no sublimation. Both ice and liquid tendencies are positive; the sublimation channel stays at zero. Captures the diurnal-transition morning condition where the two condensation branches are simultaneously active.",
      "parameter_overrides": {
        "q_sdew": 8e-06,
        "q_frost": 3e-06,
        "q_subl": 0.0
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "dw_liq_1",
          "time": 0.0,
          "expected": 8e-06
        },
        {
          "variable": "dw_ice_1_frost",
          "time": 0.0,
          "expected": 3e-06
        },
        {
          "variable": "dw_ice_1_subl",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        }
      ]
    },
    {
      "id": "dew_plus_sublimation",
      "description": "Sun-warmed surface where existing snow/frost sublimates while new dew condenses (q_sdew = 4e-6, q_subl = 6e-6 kg/(m^2*s)), no fresh frost. dw_liq_1 = 4e-6 (positive — liquid accumulating); dw_ice_1_subl = -6e-6 (negative — ice mass leaving as vapor). The two phase tendencies have opposite signs, exercising the regime where the surface is gaining liquid but losing ice.",
      "parameter_overrides": {
        "q_sdew": 4e-06,
        "q_frost": 0.0,
        "q_subl": 6e-06
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "dw_liq_1",
          "time": 0.0,
          "expected": 4e-06
        },
        {
          "variable": "dw_ice_1_frost",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        },
        {
          "variable": "dw_ice_1_subl",
          "time": 0.0,
          "expected": -6e-06
        }
      ]
    },
    {
      "id": "all_three_active",
      "description": "All three vapor-exchange channels simultaneously active (q_sdew = 1.5e-5, q_frost = 7e-6, q_subl = 4e-6 kg/(m^2*s)) — a transition-period state where the surface is partly above and partly below freezing within a single tile. Verifies that the three equations are independent: each tendency depends only on its own input, regardless of the others' magnitudes.",
      "parameter_overrides": {
        "q_sdew": 1.5e-05,
        "q_frost": 7e-06,
        "q_subl": 4e-06
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "dw_liq_1",
          "time": 0.0,
          "expected": 1.5e-05
        },
        {
          "variable": "dw_ice_1_frost",
          "time": 0.0,
          "expected": 7e-06
        },
        {
          "variable": "dw_ice_1_subl",
          "time": 0.0,
          "expected": -4e-06
        }
      ]
    },
    {
      "id": "negative_q_sdew_evaporation",
      "description": "Negative q_sdew (= -3e-6 kg/(m^2*s)) — physically a net surface evaporation rather than dew. Eq. 5.150 is sign-preserving, so dw_liq_1 = q_sdew = -3e-6 (negative tendency, liquid is leaving). The upstream MTK component does not clamp the sign of q_sdew; this test pins down that this ESM file inherits the same sign-preserving behavior.",
      "parameter_overrides": {
        "q_sdew": -3e-06,
        "q_frost": 0.0,
        "q_subl": 0.0
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "dw_liq_1",
          "time": 0.0,
          "expected": -3e-06
        },
        {
          "variable": "dw_ice_1_frost",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        },
        {
          "variable": "dw_ice_1_subl",
          "time": 0.0,
          "expected": 0.0,
          "tolerance": {
            "abs": 1e-15
          }
        }
      ]
    },
    {
      "id": "high_magnitude_storm",
      "description": "Stress-test of the linear pass-through with high-magnitude inputs (1e-3 kg/(m^2*s) on each — an extreme rime-icing event in the upper bound of physical realism). The exact pass-through and sign-flip behavior must hold at three orders of magnitude above the typical scale, confirming the equations have no hidden non-linearity or saturation.",
      "parameter_overrides": {
        "q_sdew": 0.001,
        "q_frost": 0.001,
        "q_subl": 0.001
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "dw_liq_1",
          "time": 0.0,
          "expected": 0.001
        },
        {
          "variable": "dw_ice_1_frost",
          "time": 0.0,
          "expected": 0.001
        },
        {
          "variable": "dw_ice_1_subl",
          "time": 0.0,
          "expected": -0.001
        }
      ]
    }
  ],
  "analyses": [
    {
      "id": "sublimation_response_curve",
      "description": "Sweep the sublimation rate q_subl across the typical CLMU range (0 to 1e-5 kg/(m^2*s)). dw_ice_1_subl traces a straight line from 0 to -1e-5 — visualizing the sign-flip of Eq. 5.152. The other two tendencies stay pinned at zero across the sweep.",
      "initial_state": {},
      "parameters": {
        "q_sdew": 0.0,
        "q_frost": 0.0
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "parameter_sweep": {
        "type": "cartesian",
        "dimensions": [
          {
            "parameter": "q_subl",
            "range": {
              "start": 0.0,
              "stop": 1e-05,
              "count": 21,
              "scale": "linear"
            }
          }
        ]
      },
      "plots": [
        {
          "id": "dw_ice_subl_vs_q_subl",
          "type": "line",
          "description": "dw_ice_1_subl vs q_subl — straight line through the origin with slope -1, exhibiting Eq. 5.152.",
          "x": {
            "variable": "q_subl",
            "label": "q_subl (kg/(m^2*s))"
          },
          "y": {
            "variable": "dw_ice_1_subl",
            "label": "dw_ice_1_subl (kg/(m^2*s))"
          }
        }
      ]
    },
    {
      "id": "dew_frost_phase_partition",
      "description": "Joint sweep of dew (q_sdew) and frost (q_frost) rates at fixed zero sublimation. Surfaces the independence of the liquid- and ice-tendency channels: dw_liq_1 depends only on q_sdew, dw_ice_1_frost only on q_frost. Useful as a regression baseline confirming that no cross-coupling has been silently introduced.",
      "initial_state": {},
      "parameters": {
        "q_subl": 0.0
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "parameter_sweep": {
        "type": "cartesian",
        "dimensions": [
          {
            "parameter": "q_sdew",
            "range": {
              "start": 0.0,
              "stop": 1e-05,
              "count": 11,
              "scale": "linear"
            }
          },
          {
            "parameter": "q_frost",
            "range": {
              "start": 0.0,
              "stop": 1e-05,
              "count": 11,
              "scale": "linear"
            }
          }
        ]
      },
      "plots": [
        {
          "id": "dw_liq_heatmap",
          "type": "heatmap",
          "description": "dw_liq_1 vs (q_sdew, q_frost) — must vary only along the q_sdew axis.",
          "x": {
            "variable": "q_sdew",
            "label": "q_sdew (kg/(m^2*s))"
          },
          "y": {
            "variable": "q_frost",
            "label": "q_frost (kg/(m^2*s))"
          },
          "value": {
            "variable": "dw_liq_1",
            "reduce": "final"
          }
        },
        {
          "id": "dw_ice_frost_heatmap",
          "type": "heatmap",
          "description": "dw_ice_1_frost vs (q_sdew, q_frost) — must vary only along the q_frost axis.",
          "x": {
            "variable": "q_sdew",
            "label": "q_sdew (kg/(m^2*s))"
          },
          "y": {
            "variable": "q_frost",
            "label": "q_frost (kg/(m^2*s))"
          },
          "value": {
            "variable": "dw_ice_1_frost",
            "reduce": "final"
          }
        }
      ]
    }
  ]
}