Skip to content

Aggregate lake pieces per cell in lake_from_gdf, like RIV/DRN celldata aggregation - #582

Open
bdestombe wants to merge 1 commit into
gwmod:devfrom
bdestombe:lake-from-gdf-aggregate-pieces
Open

Aggregate lake pieces per cell in lake_from_gdf, like RIV/DRN celldata aggregation#582
bdestombe wants to merge 1 commit into
gwmod:devfrom
bdestombe:lake-from-gdf-aggregate-pieces

Conversation

@bdestombe

Copy link
Copy Markdown
Collaborator

What

lake_from_gdf now accepts per-piece input — multiple rows per cellid for one lake, as produced directly by nlmod.grid.gdf_to_grid — and combines the pieces into one lake-GWF connection per cell with an area-weighted bed resistance. It also tolerates float-level noise in numeric per-lake settings.

Why

Two defects when the input is not pre-aggregated by the caller:

  1. Per-piece rows multiply-count the lake-aquifer exchange. MODFLOW 6 applies each VERTICAL lake-GWF connection over the full cell area, and lake_from_gdf turns every row into its own connection with bedleak = 1/clake. A cell holding two pieces of one lake (6000 m² at clake=10 and 2000 m² at clake=20 in a 10000 m² cell) gets two full-cell-area connections totalling 0.15 * cell_area of conductance, where the pieces physically justify (6000/10 + 2000/20) / 10000 = 0.07 * cell_area.
  2. Exact-equality single-value check rejects aggregated inputs. _get_and_check_single_value compares strt (and outlet settings) with ==. Area-weighted per-cell stages carry float-level noise (a 1e-12 difference), which raised AssertionError: A single lake should have a single strt for no physical reason.

RIV and DRN already have exactly this aggregation step in nlmod: nlmod.gwf.surface_water.aggregate collapses per-piece celldata to one reach per cell with area-weighted parameters before build_spd. The LAK path lacked the equivalent, forcing every caller to hand-roll it. (Encountered wiring the NHFLO Bergen ponds — NHFLO/models#127, NHFLO/tools#58 — where the workaround currently lives downstream.)

How

  • New _aggregate_connections_per_cell(lake_gdf, ds), invoked per lake when the cellid index has duplicates: combined clake = cell_area / sum(piece_area / clake), so the VERTICAL connection conductance cell_area / clake equals the summed piece conductance; other columns take the first piece's value (they are per-lake settings, still validated by _get_and_check_single_value). Raises a clear ValueError when pieces come without geometry, since the areas are then unknown.
  • _get_and_check_single_value uses np.allclose(rtol=1e-8, atol=0) for numeric columns; exact comparison is kept for strings (boundnames, timeseries names, lakeout).
  • nlakeconn consequently counts cells, not pieces.

Behaviour for already-aggregated input (one row per cell per lake) is unchanged.

Tests

Two regression tests in test_013_surface_water.py, both shown to fail on unchanged dev before the fix:

  • test_lake_from_gdf_aggregates_pieces_per_cell — fails on dev with 3 connections at bedleak=0.1/0.05 instead of 2 connections at the area-weighted 0.07/0.1; also pins nlakeconn == 2.
  • test_lake_from_gdf_accepts_floating_point_strt_noise — fails on dev with the AssertionError on a 1e-12 strt difference.

test_gdf_lake (existing) still passes; ruff check/ruff format add no findings relative to dev.

… strt

A lake commonly intersects a grid cell in multiple polygon pieces (e.g.
straight from nlmod.grid.gdf_to_grid). lake_from_gdf turned each row
into its own VERTICAL connection over the full cell area with
bedleak = 1/clake, multiply-counting the lake-aquifer exchange. Pieces
of one lake within a cell now collapse to a single connection with
clake = cell_area / sum(piece_area / clake), the same area-weighted
aggregation nlmod.gwf.surface_water.aggregate applies to RIV and DRN
celldata. Numeric per-lake settings are now compared with
np.allclose(rtol=1e-8) so aggregated inputs carrying float-level noise
(e.g. area-weighted stages) are not rejected by the single-value check.

Both regression tests fail on unchanged dev: three connections with
bedleak 0.1 instead of two with area-weighted bedleak, and an
AssertionError on a 1e-12 strt difference.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant