Skip to content

Canonical boundary-condition pipeline: load -> grid -> per-feature agg -> per-cell agg -> SPD #72

Description

@bdestombe

Execution plan for a consistent PWN boundary-condition structure. Self-contained: independent of nlmod — no upstream issues or PRs are part of this work. Every new function carries a docstring section Path forward to nlmod describing where it would eventually live upstream; that note is the future upstreaming spec and the deletion criterion once nlmod ships it.

Target pipeline (per stage-boundary BC)

modelscript: load geojson/shapefile via nhflodata paths, map columns to the canonical schema
  boundname | stage | rbot/elev | c OR cond_per_m OR cond_per_m2 | concentration
① nlmod.grid.gdf_to_grid(gdf, ds)                      # gridding (exists)
② aggregate_per_feature_per_cell(gdf_grid, methods)    # pieces of one feature merge per cell
③ aggregate_per_cell(per_feature, methods)             # OPTIONAL cross-feature merge
④ nlmod.gwf.build_spd(celldata, kind, ds, layer_method)  # exists
⑤ bc_package(...)                                      # flopy ctor + boundnames + aux + ssm_sources
side product of ①: open_water_fraction(gdf_grid, ds)   # feeds RCH/EVT/DRN land-share scaling

New functions in nhflotools/boundaries.py

  • aggregate_per_feature_per_cell(gdf_grid, fields_methods, boundname='boundname') — groupby [cellid, boundname]; replaces the per-feature groupby loop in lakes._aggregate_lake_cells. Path forward to nlmod: a by= parameter on nlmod.grid.aggregate_vector_per_cell (filed as aggregate_vector_per_cell: support grouping per feature (by=['cellid', boundname]) gwmod/nlmod#589).
  • cond_from_measure(gdf_grid) — conductance from clipped geometry: area/c, length*cond_per_m, area*cond_per_m2, plain cond for points; recomputes clipped measures from .geometry (carried area can be stale; the gdf_to_grid line-length branch is dead code); handles mixed geometry types in one call. Path forward to nlmod: helper in nlmod.grid + the line-length fix.
  • open_water_fraction(gdf_grid, ds) — clipped piece areas summed per cell / cell area, clipped at 1. Deduplicates lake_coverage (carve_lake_cells) and panden_coverage (riv_from_oppervlakte_pwn). Path forward to nlmod: nlmod.grid helper or part of gdf_to_grid output.
  • bc_package(celldata, kind, ds, gwf, *, pname, layer_method='lay_of_rbot')build_spd + flopy constructor with boundnames, aux CONCENTRATION, save_flows, ssm_sources registration. Path forward to nlmod: uniform package wrapper; WEL self-registration is wel_from_df / maw_from_df do not register aux concentration in ssm_sources gwmod/nlmod#578.
  • Loaders split from BC builders (permanent nhflotools code, never upstreamed): get_oppervlakte_pwn_shapes (exists), a waterboard level-areas loader out of drn_from_waterboard_data, an RWS loader out of major_surface_waters. Hardcoded knowledge (ICAS 2.8 / IKIEF 5.8 m NAP, 'None' sanitizing, HHNK quirks) lives here.

Migration order (one tools PR each + lockstep models commit — models installs nhflotools@main)

  • a. Local drains (currently inline in 09pwnmodel2/01_pwnmodel2.py): purest canonical case (lines + polygons, per-measure metadata). Proves the pipeline.
  • b. Panden: riv_from_oppervlakte_pwn(ds, gwf, data_path) -> (ds, gwf, gdf); per-feature step fixes the Naam: 'first' boundname loss on shared cells.
  • c. Lakes: re-express _aggregate_lake_cells on the per-feature aggregator; carve/threshold/LAK prep stay lake-specific. Step ③ deliberately skipped (per-lake budgets, boundnames, future MVR/outlets).
  • d. Polder DRN: signature -> (ds, gwf, gdf, ...); the vlakdekkend full-cell conductance ([polder] Waterboard DRN conductance uses full cell area instead of intersected peilgebied area (contradicts its docstring) #51) becomes an explicit override of cond_from_measure; maaiveld fallback stays a documented domain-wide step.
  • e. Major surface waters: decide last — raster-style discretize_surface_water is a different paradigm; join the pipeline or document as the exception. Wells/HFB stay outside (point/face family).

Guardrails

  • Per PR: equivalence test old-vs-new stress-period data on the existing synthetic fixtures; deliberate deltas (e.g. the panden boundname fix) asserted explicitly.
  • Sequencing: start only after NHFLO/models#135 lands (tools#71 must merge first for its notebook CI).

Context: consistency review on NHFLO/models#135; fractional-coverage groundwork in #71.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions