Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c3558b7
Add mask_packages method
JoerivanEngelen Sep 22, 2026
1c8ffb0
Add mask_topsystem_packages utility function
JoerivanEngelen Sep 22, 2026
be94e0f
Provide proper mask and fix mypy issues
JoerivanEngelen Sep 23, 2026
69bd29c
Add test
JoerivanEngelen Sep 23, 2026
d0970c3
Fix docstring
JoerivanEngelen Sep 23, 2026
c8cbc5f
Move mask topsystem function to separate utility and add ITopSystemBo…
JoerivanEngelen Sep 23, 2026
29204bd
Remove method
JoerivanEngelen Sep 23, 2026
a4ba60d
Also clip topsystems for clip_box when states_for_boundary are provided
JoerivanEngelen Sep 23, 2026
433cd10
Add test for masking the topsystem
JoerivanEngelen Sep 23, 2026
32e6772
Return None in type annotation
JoerivanEngelen Sep 23, 2026
b3a59fc
Use mask_packages method
JoerivanEngelen Sep 23, 2026
698f36e
Regrid iMOD5 IBOUND data when regridding cap data and also mask where…
JoerivanEngelen Sep 23, 2026
03aabc0
Also drop bnd layer
JoerivanEngelen Sep 23, 2026
3171d54
Call correct var an improve varname
JoerivanEngelen Sep 23, 2026
ac10b19
Add docstring
JoerivanEngelen Sep 23, 2026
65cd181
Add ibound to test fixture and expand tests to test for cell inactivity
JoerivanEngelen Sep 23, 2026
9441fd4
Update changelog
JoerivanEngelen Sep 23, 2026
e6e7a03
Rename to avoid duplicate test module names
JoerivanEngelen Sep 23, 2026
fb1b855
Also rename msw mask util test module
JoerivanEngelen Sep 23, 2026
52b6ea4
Fix and expand mf6 mask tests
JoerivanEngelen Sep 23, 2026
fc7d39d
Update mock setup
JoerivanEngelen Sep 23, 2026
4e06044
format
JoerivanEngelen Sep 23, 2026
cb51c40
Add ibound to regrid schemes where it was missing and slightly improv…
JoerivanEngelen Sep 24, 2026
4776d41
Include bnd ibound data in test fixtures where missing.
JoerivanEngelen Sep 24, 2026
65ec47d
Include ignore_time_purge_empty in mask_topsystem calls. Fix creation…
JoerivanEngelen Sep 24, 2026
50f71e5
Refactor: Move boundary condition creator utiltity functions from mod…
JoerivanEngelen Sep 24, 2026
d8b191a
Update mocking framework
JoerivanEngelen Sep 24, 2026
0f41608
Update missing args
JoerivanEngelen Sep 24, 2026
497f94a
Drop time coord and add docstring
JoerivanEngelen Sep 24, 2026
0bede89
Rename to "regrid_imod5_cap_and_bnd_data"
JoerivanEngelen Sep 28, 2026
9fbc7b6
Rename to drop_layer_dim_cap_and_bnd_data
JoerivanEngelen Sep 28, 2026
6aff0f3
Add missing docstrings to functions
JoerivanEngelen Sep 28, 2026
fc1d283
Rename cls to pkg_type here and add missing docstrings
JoerivanEngelen Sep 28, 2026
8061c3f
Move mask_topsyste_where_bc logic to utilities module
JoerivanEngelen Sep 28, 2026
a213c46
Add BoundaryCondition interface
JoerivanEngelen Sep 28, 2026
1ea8cad
update forgotten mock patch
JoerivanEngelen Sep 28, 2026
af386ae
Clearer varnames in fixture
JoerivanEngelen Sep 28, 2026
dccb8b3
Update imod/mf6/utilities/clipped_bc_creator.py
JoerivanEngelen Sep 28, 2026
1e2a9cd
Merge branch 'issue_#1787_mask_topsystem_packages' of github.com:Delt…
JoerivanEngelen Sep 28, 2026
ab7212f
Add unittests
JoerivanEngelen Sep 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions docs/api/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,35 @@ Added
:meth:`imod.msw.SprinklingPoints.from_imod5_data`.
- :class:`imod.mf6.LayeredWell.from_imod5_cap_data` now also supports loading
wells from IPF files in an iMOD5 CAP dataset.
- Added :meth:`imod.mf6.GroundwaterFlowModel.mask_packages` and
:meth:`imod.mf6.GroundwaterTransportModel.mask_packages` to mask specific
packages of a groundwater flow model and a groundwater transport model
respectively.

Fixed
~~~~~

- Fixed resampling in :meth:`imod.mf6.Well.from_imod5_data` and
:meth:`imod.mf6.LayeredWell.from_imod5_data` when simulation timesteps precede
the first well timestep.
- :meth:`imod.mf6.GroundwaterFlowModel.from_imod5_data` now masks cells in
topsystem packages (:class:`imod.mf6.River`,
:class:`imod.mf6.GeneralHeadBoundary`, :class:`imod.mf6.Drainage`,
:class:`imod.mf6.Recharge`) where IBOUND is less than 0.
- :meth:`imod.msw.MetaSwapModel.from_imod5_data` now masks cells where IBOUND is
less than 0.

Changed
~~~~~~~

- Deprecated :class:`imod.msw.Sprinkling` in favor of
:class:`imod.msw.SprinklingGrid`. Call :class:`imod.msw.SprinklingGrid` to get
the same behavior as you were used to.
- If ``states_for_boundary`` is provided to
:meth:`imod.mf6.GroundwaterFlowModel.clip_box`, topsystem packages
(:class:`imod.mf6.River`, :class:`imod.mf6.GeneralHeadBoundary`,
:class:`imod.mf6.Drainage`, :class:`imod.mf6.Recharge`) will also be masked
where constant head cells are placed.

[1.1.0] - 2026-08-03
--------------------
Expand Down
2 changes: 2 additions & 0 deletions docs/api/mf6.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Model objects & methods
Modflow6Simulation.set_validation_settings
GroundwaterFlowModel
GroundwaterFlowModel.mask_all_packages
GroundwaterFlowModel.mask_packages
GroundwaterFlowModel.prepare_wel_for_mf6
GroundwaterFlowModel.regrid_like
GroundwaterFlowModel.dump
Expand All @@ -60,6 +61,7 @@ Model objects & methods
GroundwaterFlowModel.get_diskey
GroundwaterTransportModel
GroundwaterTransportModel.mask_all_packages
GroundwaterTransportModel.mask_packages
GroundwaterTransportModel.dump
GroundwaterTransportModel.clip_box
GroundwaterTransportModel.regrid_like
Expand Down
12 changes: 12 additions & 0 deletions imod/common/interfaces/iboundarycondition.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from abc import ABC
from typing import ClassVar

from imod.common.interfaces.ipackage import IPackage


class IBoundaryCondition(IPackage, ABC):
"""
Interface for boundary condition packages with stress-period variables.
"""

_period_data: ClassVar[tuple[str, ...]]
20 changes: 19 additions & 1 deletion imod/common/interfaces/imodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Any, Optional, Tuple

from imod.common.interfaces.idict import IDict
from imod.common.interfaces.ipackage import IPackage
from imod.common.statusinfo import StatusInfoBase
from imod.mf6.validation_settings import ValidationSettings
from imod.typing import GridDataArray
Expand All @@ -16,9 +17,21 @@ class IModel(IDict):
def mask_all_packages(self, mask: GridDataArray):
raise NotImplementedError

@abstractmethod
def mask_packages(
self,
package_names: list[str],
mask: GridDataArray,
ignore_time_purge_empty: bool = False,
):
raise NotImplementedError

@abstractmethod
def purge_empty_packages(
self, model_name: Optional[str] = "", ignore_time: bool = False
self,
model_name: Optional[str] = "",
ignore_time: bool = False,
package_names: list[str] | None = None,
) -> None:
raise NotImplementedError

Expand Down Expand Up @@ -56,3 +69,8 @@ def _is_splitting_supported(self) -> Tuple[bool, str]:
@abstractmethod
def _is_clipping_supported(self) -> Tuple[bool, str]:
raise NotImplementedError

@property
@abstractmethod
def _boundary_state_pkg_type(self) -> type[IPackage]:
raise NotImplementedError
15 changes: 15 additions & 0 deletions imod/common/interfaces/itopsystembc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from abc import abstractmethod

from imod.common.interfaces.ipackage import IPackage
from imod.typing import GridDataDict, GridDataset


class ITopSystemBoundaryCondition(IPackage):
"""
Interface for top system boundary condition packages in MODFLOW 6.
"""

@classmethod
@abstractmethod
def aggregate_layers(cls, dataset: GridDataset) -> GridDataDict:
raise NotImplementedError
13 changes: 8 additions & 5 deletions imod/common/utilities/mask.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,18 @@ def mask_all_models(
)


def mask_all_packages(
def mask_packages(
model: IModel,
package_names: list[str],
mask: GridDataArray,
ignore_time_purge_empty: bool = False,
):
) -> None:
_validate_coords_mask(mask)
for pkgname, pkg in model.items():
model[pkgname] = pkg.mask(mask)
model.purge_empty_packages(ignore_time=ignore_time_purge_empty)
for pkgname in package_names:
model[pkgname] = model[pkgname].mask(mask)
model.purge_empty_packages(
ignore_time=ignore_time_purge_empty, package_names=package_names
)


def mask_package(package: IPackage, mask: GridDataArray) -> IPackage:
Expand Down
12 changes: 8 additions & 4 deletions imod/common/utilities/regrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
is_unstructured,
ones_like,
)
from imod.util.dims import drop_layer_dim_cap_data, enforced_dim_order
from imod.util.dims import drop_layer_dim_cap_and_bnd_data, enforced_dim_order
from imod.util.regrid import (
RegridderType,
RegridderWeightsCache,
Expand Down Expand Up @@ -471,7 +471,7 @@ def _get_regridding_domain(
return new_idomain


def regrid_imod5_cap_data(
def regrid_imod5_cap_and_bnd_data(
imod5_data: Imod5DataDict,
target_dis: IRegridPackage,
regridder_types: DataclassType,
Expand All @@ -486,15 +486,19 @@ def regrid_imod5_cap_data(
and ``imod.mf6.Recharge.from_imod5_cap_data``.
"""
# Drop layer coords
imod5_cap_no_layer = drop_layer_dim_cap_data(imod5_data)
imod5_no_layer = drop_layer_dim_cap_and_bnd_data(imod5_data)
target_grid = target_dis.dataset["idomain"].isel(layer=0, drop=True)
# Regrid the input data
cap_data_regridded = _regrid_package_data(
Comment thread
JoerivanEngelen marked this conversation as resolved.
imod5_cap_no_layer["cap"], target_grid, regridder_types, regrid_cache
imod5_no_layer["cap"], target_grid, regridder_types, regrid_cache
)
bnd_data_regridded = _regrid_package_data(
imod5_no_layer["bnd"], target_grid, regridder_types, regrid_cache
Comment thread
JoerivanEngelen marked this conversation as resolved.
)
extra_paths = imod5_data["extra"]["paths"]
imod5_regridded: Imod5DataDict = {
"cap": cap_data_regridded,
"bnd": bnd_data_regridded,
"extra": {"paths": extra_paths},
}
return imod5_regridded
5 changes: 3 additions & 2 deletions imod/mf6/boundary_condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import xarray as xr
import xugrid as xu

from imod.common.interfaces.iboundarycondition import IBoundaryCondition
from imod.common.utilities.value_filters import enforce_scalar
from imod.mf6.auxiliary_variables import (
expand_transient_auxiliary_variables,
Expand Down Expand Up @@ -57,7 +58,7 @@ def _disv_recarr(arrdict, layer, notnull):
return recarr


class BoundaryCondition(Package, abc.ABC):
class BoundaryCondition(Package, IBoundaryCondition, abc.ABC):
"""
BoundaryCondition is used to share methods for specific stress packages
with a time component.
Expand Down Expand Up @@ -324,7 +325,7 @@ def _get_period_varnames(self) -> list[str]:
>>> river._get_period_varnames()
>>> # prints: ['stage', 'conductance', 'bottom_elevation', 'species1', 'species2']
"""
result = []
result: list[str] = []
if hasattr(self, "_period_data"):
result.extend(self._period_data)
if hasattr(self, "_optional_data"):
Expand Down
Loading
Loading