Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b537f7f

Browse files
Issue #1437 fix recharge from imod5 cap data 2d (#1448)
Fixes #1437 # Description ``primod`` expects a 2D rate array or single layer array for the dummy MODFLOW6 package, as otherwise the ``squeeze("layer")`` it does returns an error. I think the safest for iMOD Python is to return a 2D array with extra layer coordinate. I added some extra tests to test if this RCH package could be clipped and regridded, as in most/all fixtures for clipping/regridding I added packages with layer dimension. Luckily these two extra tests turned out to be mostly for my own peace of mind, as they ran without problems. # Checklist - [x] Links to correct issue - [x] Update changelog, if changes affect users - [x] PR title starts with ``Issue #nr``, e.g. ``Issue #737`` - [x] Unit tests were added - [ ] **If feature added**: Added/extended example
1 parent c34343a commit b537f7f

File tree

3 files changed

+67
-12
lines changed

3 files changed

+67
-12
lines changed

docs/api/changelog.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ Fixed
9191
like MetaSWAP expects.
9292
- Models imported with :meth:`imod.msw.MetaSwapModel.from_imod5_data` can be
9393
written with ``validate`` set to True.
94+
- :meth:`imod.mf6.Recharge.from_imod5_cap_data` now returns a 2D array with a
95+
``"layer"`` coordinate of ``1`` as otherwise ``primod`` throws an error when
96+
trying to derive recharge-svat mappings.
9497
- Fixed part of the code that made Pandas, Geopandas, and xarray throw a lot of
9598
``FutureWarning``s and ``DeprecationWarning``s.
9699
- Fixed performance issue when coverting very large wells (>10k) with

imod/mf6/rch.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,11 +279,8 @@ def from_imod5_cap_data(
279279
active = msw_active.all
280280

281281
data = {}
282-
layer_da = xr.full_like(
283-
target_dis.dataset.coords["layer"], np.nan, dtype=np.float64
284-
)
285-
layer_da.loc[{"layer": 1}] = 0.0
286-
data["rate"] = layer_da.where(active)
282+
zero_scalar = xr.DataArray(0.0, coords={"layer": 1})
283+
data["rate"] = zero_scalar.where(active)
287284

288285
return cls(**data, validate=True, fixed_cell=False)
289286

imod/tests/test_mf6/test_mf6_rch.py

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import imod
1212
from imod.mf6.dis import StructuredDiscretization
13+
from imod.mf6.utilities.regrid import RegridderWeightsCache
1314
from imod.mf6.write_context import WriteContext
1415
from imod.schemata import ValidationError
1516
from imod.typing.grid import is_planar_grid, is_transient_data_grid, nan_like
@@ -467,18 +468,72 @@ def test_from_imod5_cap_data(imod5_dataset):
467468
data["cap"]["boundary"] = msw_bound
468469
data["cap"]["wetted_area"] = xr.ones_like(msw_bound) * 100
469470
data["cap"]["urban_area"] = xr.ones_like(msw_bound) * 200
471+
# Compute midpoint of grid and set areas such, that cells need to be
472+
# deactivated.
473+
midpoint = tuple((int(x / 2) for x in msw_bound.shape))
470474
# Set to total cellsize, cell needs to be deactivated.
471-
data["cap"]["wetted_area"][100, 100] = 625.0
475+
data["cap"]["wetted_area"][midpoint] = 625.0
472476
# Set to zero, cell needs to be deactivated.
473-
data["cap"]["urban_area"][100, 100] = 0.0
477+
data["cap"]["urban_area"][midpoint] = 0.0
474478
# Act
475479
rch = imod.mf6.Recharge.from_imod5_cap_data(data, target_discretization)
476480
rate = rch.dataset["rate"]
477481
# Assert
482+
# Shape
483+
assert rate.dims == ("y", "x")
484+
assert "layer" in rate.coords
485+
assert rate.coords["layer"] == 1
486+
# Values
478487
np.testing.assert_array_equal(np.unique(rate), np.array([0.0, np.nan]))
479488
# Boundaries inactive in MetaSWAP
480-
assert np.isnan(rate[0, :, 0]).all()
481-
assert np.isnan(rate[0, :, -1]).all()
482-
assert np.isnan(rate[0, 0, :]).all()
483-
assert np.isnan(rate[0, -1, :]).all()
484-
assert np.isnan(rate[:, 100, 100]).all()
489+
assert np.isnan(rate[:, 0]).all()
490+
assert np.isnan(rate[:, -1]).all()
491+
assert np.isnan(rate[0, :]).all()
492+
assert np.isnan(rate[-1, :]).all()
493+
assert np.isnan(rate[midpoint]).all()
494+
495+
496+
@pytest.mark.unittest_jit
497+
def test_from_imod5_cap_data__regrid(imod5_dataset):
498+
# Arrange
499+
data = deepcopy(imod5_dataset[0])
500+
target_discretization = StructuredDiscretization.from_imod5_data(data)
501+
data["cap"] = {}
502+
msw_bound = data["bnd"]["ibound"].isel(layer=0, drop=False)
503+
data["cap"]["boundary"] = msw_bound
504+
data["cap"]["wetted_area"] = xr.ones_like(msw_bound) * 100
505+
data["cap"]["urban_area"] = xr.ones_like(msw_bound) * 200
506+
# Setup template grid
507+
dx_small, xmin, xmax, dy_small, ymin, ymax = imod.util.spatial_reference(msw_bound)
508+
dx = dx_small * 2
509+
dy = dy_small * 2
510+
expected_spatial_ref = dx, xmin, xmax, dy, ymin, ymax
511+
like = imod.util.empty_2d(*expected_spatial_ref)
512+
# Act
513+
rch = imod.mf6.Recharge.from_imod5_cap_data(data, target_discretization)
514+
rch_coarse = rch.regrid_like(like, regrid_cache=RegridderWeightsCache())
515+
# Assert
516+
actual_spatial_ref = imod.util.spatial_reference(rch_coarse.dataset["rate"])
517+
assert actual_spatial_ref == expected_spatial_ref
518+
519+
520+
@pytest.mark.unittest_jit
521+
def test_from_imod5_cap_data__clip_box(imod5_dataset):
522+
# Arrange
523+
data = deepcopy(imod5_dataset[0])
524+
target_discretization = StructuredDiscretization.from_imod5_data(data)
525+
data["cap"] = {}
526+
msw_bound = data["bnd"]["ibound"].isel(layer=0, drop=False)
527+
data["cap"]["boundary"] = msw_bound
528+
data["cap"]["wetted_area"] = xr.ones_like(msw_bound) * 100
529+
data["cap"]["urban_area"] = xr.ones_like(msw_bound) * 200
530+
# Setup template grid
531+
dx, xmin, xmax, dy, ymin, ymax = imod.util.spatial_reference(msw_bound)
532+
xmin_to_clip = xmin + 10 * dx
533+
expected_spatial_ref = dx, xmin_to_clip, xmax, dy, ymin, ymax
534+
# Act
535+
rch = imod.mf6.Recharge.from_imod5_cap_data(data, target_discretization)
536+
rch_clipped = rch.clip_box(x_min=xmin_to_clip)
537+
# Assert
538+
actual_spatial_ref = imod.util.spatial_reference(rch_clipped.dataset["rate"])
539+
assert actual_spatial_ref == expected_spatial_ref

0 commit comments

Comments
 (0)