Context
v1 lake support (see DESIGN_lakes.md, "Committed design" section) is being implemented as a special SubCatchment kind (kind='lake'): a single threshold-power-law reservoir fed by direct P − E, coupled to a land sub-catchment's deepest reservoir by a bidirectional groundwater flux Q_gw, and area-weighted into basin discharge.
This reuses the substantial per-sub-catchment plumbing — the update() loop, BMI area-weighting, calibration state capture/restore, decadal chaining, store_depths, and JIT flattening (sc_start_idx/sc_end_idx) — which is the reason we chose it for v1.
The problem
A lake is not really a "sub-catchment" (a parallel land zone with a vertical reservoir cascade). It is "another thing in the basin that behaves differently and is not part of the same cascade." Overloading SubCatchment works for v1 but conflates two distinct concepts, and SubCatchment becomes a misnomer for non-land elements.
Proposal (to decide later — not blocking v1 lakes)
Introduce a more general basin-element abstraction: a common interface for compartments that
- carry an area fraction,
- hold per-element state,
- advance per timestep and contribute an area-weighted flux to the gauge,
- may couple to other elements by explicit edges (e.g.
Q_gw),
of which SubCatchment (cascade land zone) and Lake (open water + stage-discharge outlet + GW exchange) are two kinds. This would cleanly support future elements (wetlands / depression storage, glaciers, explicit routed channel/reservoir elements) without further overloading SubCatchment.
Scope of the decision
- Refactor
SubCatchment into a base class / protocol with LandSubCatchment and Lake subclasses, vs. keeping a kind discriminator.
- How element-to-element coupling edges (currently just lake ↔ subsurface
Q_gw) are represented in general.
- How the JIT flattening generalizes across element kinds.
- Naming.
Relates to DESIGN_lakes.md open-question #3. Best revisited once the lake lands and we can see where the bookkeeping strains.
🤖 Generated with Claude Code
Context
v1 lake support (see
DESIGN_lakes.md, "Committed design" section) is being implemented as a specialSubCatchmentkind (kind='lake'): a single threshold-power-law reservoir fed by directP − E, coupled to a land sub-catchment's deepest reservoir by a bidirectional groundwater fluxQ_gw, and area-weighted into basin discharge.This reuses the substantial per-sub-catchment plumbing — the
update()loop, BMI area-weighting, calibration state capture/restore, decadal chaining,store_depths, and JIT flattening (sc_start_idx/sc_end_idx) — which is the reason we chose it for v1.The problem
A lake is not really a "sub-catchment" (a parallel land zone with a vertical reservoir cascade). It is "another thing in the basin that behaves differently and is not part of the same cascade." Overloading
SubCatchmentworks for v1 but conflates two distinct concepts, andSubCatchmentbecomes a misnomer for non-land elements.Proposal (to decide later — not blocking v1 lakes)
Introduce a more general basin-element abstraction: a common interface for compartments that
Q_gw),of which
SubCatchment(cascade land zone) andLake(open water + stage-discharge outlet + GW exchange) are two kinds. This would cleanly support future elements (wetlands / depression storage, glaciers, explicit routed channel/reservoir elements) without further overloadingSubCatchment.Scope of the decision
SubCatchmentinto a base class / protocol withLandSubCatchmentandLakesubclasses, vs. keeping akinddiscriminator.Q_gw) are represented in general.Relates to
DESIGN_lakes.mdopen-question #3. Best revisited once the lake lands and we can see where the bookkeeping strains.🤖 Generated with Claude Code