Skip to content

eCLM-ParFlow: Couple urban landunits - #133

Open
s-poll wants to merge 1 commit into
masterfrom
dev-eclm-parflow-urblu
Open

eCLM-ParFlow: Couple urban landunits#133
s-poll wants to merge 1 commit into
masterfrom
dev-eclm-parflow-urblu

Conversation

@s-poll

@s-poll s-poll commented Sep 1, 2026

Copy link
Copy Markdown
Member

Fixes #61.

Summary

Urban landunits were only partly connected to ParFlow. Two issues:

  1. urban pervious road used ParFlow state that was never distributed to it, leaving h2osoi_liq at spval (1e36) on every column and level
  2. impervious urban runoff left the domain as river runoff without ever entering ParFlow's budget.

Both are fixed here, so every hydrologically active column receives ParFlow's soil water and the impervious fraction contributes its runoff to the subsurface instead of losing it.

Note on #61: The consequence is more severe than the column being ignored: icol_road_perv is in the used filters (e.g. filter_hydrologyc), so rather than being skipped it reads state that was never written.

1. Distribute ParFlow state on the hydrology filter

The ParFlow state is written on one column filter and read on another, and the two are not the same set.

clm_drv_init wrote pfl_psi / pfl_h2osoi_liq on filter_soilc (istsoil and istcrop landunits only). Every routine that reads them loops over filter_hydrologyc, which builds from col%hydrologically_active: soil + crop + icol_road_perv (column_varcon.F90:69-76).

The read set is therefore a strict superset of the written set, and the extra members, the pervious-road columns, read array slots nothing ever filled: spval on cold start (WaterStateType.F90:862-863), NaN on restart. soilwater_parflow wrote that straight into h2osoi_liq.

The physical statement, and the answer to the question raised in #61: ParFlow resolves one soil column per gridcell, and all hydrologically active eCLM tiles share it — pervious road draws from the same water table as the surrounding vegetation.

EUR-12 domain

Before, all 20 levels of all 22,110 active pervious-road columns held spval:

icol_road_perv (ityp=75)  22110 cols  H2OSOI_LIQ mean=1.0000e+36  >1e30: 442200/442200
icol_road_imperv          22110 cols  H2OSOI_LIQ mean=3.4762e-02  >1e30: 0
soil                     102979 cols  H2OSOI_LIQ mean=1.4321e+02  >1e30: 0

TWS was previously undefined on 21.5 % of land cells. The match is three-way exact: 22,110 undefined land cells = 22,110 active icol_road_perv columns = 22,110 gridcells containing them.

2. Route impervious urban runoff into ParFlow

Roof, wall and impervious-road runoff was zeroed for drainage and left via qflx_runoff, never reaching ParFlow. It is now routed into ParFlow layer 1, with both runoff terms zeroed where they are read so the water is not counted twice, and the exchange booked to qflx_drain = -sum(qflx_parflow). It follows the convention of every other coupled column (SoilHydrologyMod.F90:2396). qflx_drain is taken while the flux is still in mm/s, before the 1/dz conversion, matching the hydrologically active loop above it.

Impact: This routes 100 % of impervious runoff locally, the opposite from the previous behavior; real cities probably lie in between. Could be fixed in future by introducing a partial fraction and/or by modifying hydraulic parameter in ParFlow.

Known gaps

  • QOVER does not include urban surface runoff. Even in a build where impervious urban columns demonstrably generate runoff, their ponding storage sits at the pondmx_urban limit, which is only set on the branch that also sets qflx_surf, QOVER reads exactly zero on every land cell. For now: QOVER should not be used as an urban diagnostic instead QRUNOFF/QDRAI should be used.
  • The qflx_drain = -sum(qflx_parflow) convention is passed down, not verified. It passes the entire ParFlow exchange as drainage. Whether this closes eCLM's column water balance could not be determined, and would be needed to check in future. Change 2 applies the same rule to impervious columns as to all other coupled columns.

- bugfix: pfl_psi/pfl_h2osoi_liq were distributed over filter_soilc, but eCLM run over filter_hydrologyc, leading to soilwater_parflow wrote nan into h2osoi_liq for pervious road
- distribute over filter_nolakec testing col%hydrologically_active, the predicate filterMod uses for filter_hydrologyc, originally leading to undefined TWS
- impervious urban runoff left the domain as river runoff, route it into ParFlow layer 1, zeroed qflx_surf/qflx_qrgwl and write it to qflx_drain as for every other coupled column
@s-poll s-poll added the coupled-parflow Issues related to eCLM-ParFlow coupling label Sep 1, 2026
@s-poll
s-poll marked this pull request as ready for review September 2, 2026 07:26
@s-poll
s-poll requested a review from kvrigor September 2, 2026 07:26
Comment thread src/clm5/biogeophys/SoilHydrologyMod.F90
qflx_parflow(c,1:nlevsoi) = 0._r8
qflx_parflow(c,1) = qflx_surf(c) + qflx_qrgwl(c)
qflx_surf(c) = 0._r8
qflx_qrgwl(c) = 0._r8

@kvrigor kvrigor Sep 2, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Zero-ing qflx_surf and qflx_qrgwl wouldn't be a good idea. Processes relying on these fluxes will be affected, e.g. qflx_runoff:

do fc = 1,num_nolakec
c = filter_nolakec(fc)
l = col%landunit(c)
qflx_runoff(c) = qflx_drain(c) + qflx_surf(c) + qflx_h2osfc_surf(c) + qflx_qrgwl(c) + qflx_drain_perched(c)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

coupled-parflow Issues related to eCLM-ParFlow coupling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

eCLM-ParFlow: Urban pervious road (icol_road_perv) land units are ignored

2 participants