Skip to content

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

Open
bdestombe wants to merge 3 commits into
gwmod:devfrom
bdestombe:lake-from-gdf-aggregate-pieces
Open

bdestombe wants to merge 3 commits into
gwmod:devfrom
bdestombe:lake-from-gdf-aggregate-pieces

Conversation

@bdestombe

@bdestombe bdestombe commented Jul 22, 2026 •

Copy link
Copy Markdown
Collaborator

lake_from_gdf can now take the output of nlmod.grid.gdf_to_grid directly, even when one lake has several pieces in the same cell.

Problem

  • Each row became its own lake connection. MODFLOW 6 applies every connection over the full cell area, so a cell with two pieces of one lake got about twice the exchange with the groundwater.
  • Stages that differ only by floating-point noise (around 1e-12) raised "A single lake should have a single strt".

Change

  • Pieces of one lake in the same cell are combined into one connection. The bed resistance is area-weighted, so the exchange equals the sum of the pieces. surface_water.aggregate already does the same for RIV and DRN.
  • Numeric per-lake values are compared with a small tolerance instead of exact equality.

Input with one row per cell per lake gives the same result as before. At lake edges, where a cell is only partly covered, the exchange is now scaled to the covered area, so existing models may change there.

Tests: two new tests in test_013_surface_water.py, both failing on dev before this change.

… 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.

@OnnoEbbens OnnoEbbens left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Bas, hadn't realised this was happening for lakes. I have just some small textual comments.

Another thing is that I had a bit of a hard time understanding the PR text. It only clicked after I looked into the code. It looks as if it is AI generated. Not necessarily something I oppose but maybe the AI can make it more concise next time :)

Comment thread nlmod/gwf/lake.py
the first piece per cell.
"""
if "geometry" not in lake_gdf.columns or lake_gdf.geometry.isna().any():
raise ValueError(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a bit of trouble reading the error message. Is this a good alternative:

"found multiple elements of one lake in a single cell; provide polygon "
"geometries of the lake to aggregate these elements"

Comment thread nlmod/gwf/lake.py Outdated
lakeno : with the number of the lake
strt : with the starting head of the lake
clake : with the bed resistance of the lake
A lake may have multiple rows (polygon pieces) per cellid, e.g. straight

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A lake may have multiple rows (polygon pieces) per cellid, e.g. straight
A single lake may have multiple elements (polygon pieces) in one cell, e.g. straight

@OnnoEbbens OnnoEbbens left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Bas, hadn't realised this was happening for lakes. I have just some small textual comments.

Another thing is that I had a bit of a hard time understanding the PR text. It only clicked after I looked into the code. It looks as if it is AI generated. Not necessarily something I oppose but maybe the AI can make it more concise next time :)

@rubencalje rubencalje left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good improvement. Existing models will change, as the bedleak (conductance) at the edge of lakes is now scaled by the part of the cell that is covered by the lake. This is a good thing though, and will maybe help with model convergence as well.

When Onno's comments are addressed, we can merge this.

@dbrakenhoff dbrakenhoff mentioned this pull request Sep 11, 2026
6 tasks
@bdestombe

Copy link
Copy Markdown
Collaborator Author

Thanks both! I applied Onno's suggestions, merged the latest dev (CI should pass again) and shortened the description.

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.

3 participants