Skip to content

Subcatchment masking - #885

Merged
JoostBuitink merged 35 commits into
masterfrom
subcatchment_masking
Jun 10, 2026
Merged

Subcatchment masking#885
JoostBuitink merged 35 commits into
masterfrom
subcatchment_masking

Conversation

@JoostBuitink

@JoostBuitink JoostBuitink commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Issue addressed

  • Fixes ENH: run a subset of a wflow model #270.
  • Adds a logging message on which profile type is being used
  • Fixes an issue where the field capacity variable was not yet included in the standard_names dict
  • Fixes the maximum subsurface flow not being adjusted for subdaily timesteps
    (only when using layered or layered_exponential profiles)

Explanation

Explain how you addressed the bug/feature request, what choices you made and why.

Checklist

  • Updated tests or added new tests
  • Branch is up to date with master
  • Tests & pre-commit hooks pass
  • Updated documentation if needed
  • Updated changelog.qmd if needed

Additional Notes (optional)

Note that for the testing, I decided to use the landuse map, as no subcatchment map was present in the example models.

@JoostBuitink
JoostBuitink marked this pull request as ready for review April 23, 2026 06:25

@SouthEndMusic SouthEndMusic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Some general comments. I don't understand everything well enough to approve the PR

Comment thread docs/user_guide/faq.qmd Outdated
represents your entire catchment, and all cells that have a value are interpreted as active
cells. You can update this to another layer which contains a subset of the original data.

Alternatively, you can also point this to a layer with subcatchment information (e.g. based

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
Alternatively, you can also point this to a layer with subcatchment information (e.g. based
Alternatively, you can point this to a layer with subcatchment information (e.g. based

Comment thread docs/user_guide/faq.qmd Outdated
When using this functionality, please take the following points into account:

- Ensure that all upstream regions are included (unless you make use of external inflows)
- When using water demand and allocation: ensure that there are no allocations area's with

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
- When using water demand and allocation: ensure that there are no allocations area's with
- When using water demand and allocation: ensure that there are no allocation areas with

Comment thread docs/user_guide/faq.qmd Outdated

- Ensure that all upstream regions are included (unless you make use of external inflows)
- When using water demand and allocation: ensure that there are no allocations area's with
the same IDs outside your active domain (a warning is shown in the logging)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
the same IDs outside your active domain (a warning is shown in the logging)
the same ID outside your active domain (a warning is shown in the logging)

Comment thread docs/user_guide/faq.qmd Outdated
- When using local_inertial for routing: a ghost node will be added at the end of each river
section (with a set distance and water level). This might cause some difference in the
results, as it no longer contains the "real" downstream boundary condition. If this is
important, ensure that the gauges for evaluation have sufficient downstream pixels in your

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does pixel here refer to a cell? I feel that's a better word to refer to the concept

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks, yes cell is indeed a better word!

config,
"land_water_allocation_area__count",
LandHydrologySBM;
metadata = ParameterMetadata(; type = Int, allow_missing = true),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why not add this to a standard name map?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It is already part of the standard names, but I needed to overwrite the metadata in order to get the full array (so not only for the active cells, as is done in the lines above this change).

@vers-w vers-w 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.

LGTM and good to have this functionality!
See my comments below.

Comment thread docs/user_guide/faq.qmd Outdated
represents your entire catchment, and all cells that have a value are interpreted as active
cells. You can update this to another layer which contains a subset of the original data.

Alternatively, you can point this to a layer with subcatchment information (e.g. based on

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
Alternatively, you can point this to a layer with subcatchment information (e.g. based on
Alternatively, you can point `subbasin_location__count` to a layer with subcatchment information (e.g. based on

Comment thread docs/user_guide/faq.qmd Outdated
```toml
[input]
subbasin_location__count = "subcatchment_gauges_obs"
subbasin_active_area__count = [1016, 1013, 1011, 206, 203, 503]

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 more in line with the already used subbasin_location__count entry:

Suggested change
subbasin_active_area__count = [1016, 1013, 1011, 206, 203, 503]
subbasin_active_location__count = [1016, 1013, 1011, 206, 203, 503]

Comment thread docs/user_guide/faq.qmd Outdated
Comment on lines +147 to +148
- When writing output at specific cells (`index`) and/or x-y positions (`coordinate`): this
can cause unreliable results and/or give errors. If you need output at specific locations,

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 guess this means a check is not performed for index and coordinate (removing entries that are not part of active indices)? If that's the case maybe add this at the start. I think the "this can cause unreliable results" is a bit unclear.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This was indeed not checked. I adjusted the code to show a warning rather than an error, which means that this message is no longer relevant, and users are a bit more flexible with using the same toml file

Comment thread docs/changelog.qmd
Comment on lines +36 to +37
- Fixed a bug where the maximum subsurface flow was not adjusted for subdaily timesteps
(only when using `layered` or `layered_exponential` profiles)

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.

Nice catch!
Note that this also needs fixing in the release v1 branch and these lines need then to be moved below v1.0.3 in the changelog.

Comment thread Wflow/src/routing/utils.jl Outdated
# find the node id of the downstream cell
to_node = searchsortedfirst(indices, to_index)
if to_node > length(indices) || indices[to_node] != to_index
@warn "Invalid drainage direction value at node `$from_node` (LDD=`$ldd_val`), assuming pit"

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
@warn "Invalid drainage direction value at node `$from_node` (LDD=`$ldd_val`), assuming pit"
@warn "Invalid drainage direction value at node `$from_node` (LDD=`$ldd_val`), assign pit value at node"

Comment thread Wflow/src/io.jl Outdated
Comment on lines +793 to +794
config;
indices = indices,

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
config;
indices = indices,
config,
indices,

Comment thread Wflow/src/io.jl Outdated
Comment on lines +1036 to +1037
# update 2d map to only include active cells, and convert to missing for inactive cells
map_2d = mask_to_indices(map_2d, indices; fill_value = missing)

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.

Suggest to remove this part and add indices as argument to ncread function.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done!

Comment thread Wflow/src/utils.jl Outdated
end

"Mask a 2D array, keeping only values at the given `indices` and setting the rest to `fill_value`."
function mask_to_indices(

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.

As suggested for the io.jl part to remove this function (and use indices directly in ncread), I think this is now only used for the river location. It is not clear to me why a Union type is required? I would suggest to either not make fill_value optional and use the correct type in the function call (based on array_2d), so you only need eltype(array_2d) or to make use of the metadata of the parameter that has the required type and fill information.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

the function is removed and incorporated with ncread

Comment thread Wflow/src/domain.jl
sel=network.indices,
)
replace!(x -> ismissing(x) ? 0 : x, reservoirs)
# check if any reservoirs are found in the active model domain, if not disable reservoir model component

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.

Nice to have this check! For consistency would be good if reservoir network info is also adapted if reservoirs are not found in the active model domain.

And probably good to have a similar check for drains?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I have added a similar check for drains!

Comment thread docs/user_guide/faq.qmd
```

::: {.callout-important}
When using this functionality, please take the following points into account:

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.

Just wondering: any considerations needed when running with multiple threads/this works fine with this functionality?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not in particular; since the new outlets are assumed pits, the multithreading recognizes them as individual basins

Comment thread docs/user_guide/faq.qmd Outdated
Comment on lines +144 to +146
results, as it no longer contains the "real" downstream boundary condition. If this is
important, ensure that the gauges for evaluation have sufficient downstream cells in your
selected model domain.

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.

Is it not better (easier) to recommend to add boundary conditions at these points?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes true, added that as well!

Comment thread docs/user_guide/faq.qmd
can cause unreliable results and/or give errors. If you need output at specific locations,
use the `map` functionality instead, as this will still write output at the targeted
locations when running only a subsection of your model.
:::

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.

Probably good to add what a user needs to take into account for the Darcy based groundwater flow concept?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added!

also made the output writing when using coordinates or index values a bit more relaxed, to throw a warning rather than an error when invalid cells are selected
@JoostBuitink
JoostBuitink requested a review from vers-w June 1, 2026 12:59

@vers-w vers-w 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.

LGTM, except for the failing tests ;-)!

@JoostBuitink
JoostBuitink merged commit aa99309 into master Jun 10, 2026
11 of 14 checks passed
@JoostBuitink
JoostBuitink deleted the subcatchment_masking branch June 10, 2026 13:46
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.

ENH: run a subset of a wflow model

3 participants