Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion imod/mf6/mf6_wel_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ def __init__(
self,
cellid,
rate,
id,
concentration=None,
concentration_boundary_type="aux",
save_flows: Optional[bool] = None,
Expand All @@ -153,6 +154,7 @@ def __init__(
dict_dataset = {
"cellid": cellid,
"rate": rate,
"id": id,
"concentration": concentration,
"concentration_boundary_type": concentration_boundary_type,
"save_flows": save_flows,
Expand All @@ -169,7 +171,7 @@ def _ds_to_arrdict(self, ds):
arrdict: Dict[str, Any] = {}

arrdict["data_vars"] = [
var_name for var_name in ds.data_vars if var_name != "cellid"
var_name for var_name in ds.data_vars if var_name not in ("cellid", "id")
]

dsvar = {}
Expand Down
20 changes: 16 additions & 4 deletions imod/mf6/utilities/imod5_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,16 @@ def fill_missing_layers(


def _well_from_imod5_cap_point_data(cap_data: GridDataDict) -> dict[str, np.ndarray]:
raise NotImplementedError(
"Assigning sprinkling wells with an IPF file is not supported, please specify them as IDF."
)
df_points = cap_data["artificial_recharge_layer"]
data = {}
# Order of columns is x, y, layer, the other columns are irrelevant here.
data["x"] = df_points.iloc[:, 0].to_numpy().astype(float)
data["y"] = df_points.iloc[:, 1].to_numpy().astype(float)
data["layer"] = df_points.iloc[:, 2].to_numpy().astype(int)
data["rate"] = np.zeros_like(data["x"], dtype=float)
data["id"] = df_points.index.to_numpy()

return data


def _well_from_imod5_cap_grid_data(cap_data: GridDataDict) -> dict[str, np.ndarray]:
Expand All @@ -85,7 +92,7 @@ def _well_from_imod5_cap_grid_data(cap_data: GridDataDict) -> dict[str, np.ndarr

def well_from_imod5_cap_data(
imod5_data: Imod5DataDict,
target_dis: IRegridPackage,
target_dis: Optional[IRegridPackage],
regridder_types: DataclassType,
regrid_cache: RegridderWeightsCache,
) -> dict[str, np.ndarray]:
Expand Down Expand Up @@ -121,6 +128,11 @@ def well_from_imod5_cap_data(
if has_ipf_well:
return _well_from_imod5_cap_point_data(cap_data)
else:
if target_dis is None:
raise ValueError(
"target_dis must be provided when converting iMOD5 cap data "
"from grids (IDF)"
)
cap_data_regridded = regrid_imod5_cap_data(
imod5_data, target_dis, regridder_types, regrid_cache
)["cap"]
Expand Down
37 changes: 24 additions & 13 deletions imod/mf6/wel.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ def _assign_dims(arg: Any) -> tuple[Any, ...] | xr.DataArray:
if arg.dims[0] != "time":
arg = arg.transpose()
da = xr.DataArray(
data=arg.values, coords={"time": arg["time"]}, dims=["time", "index"]
data=arg.to_numpy(), coords={"time": arg["time"]}, dims=["time", "index"]
)
return da
elif is_da:
return "index", arg.values
return "index", arg.to_numpy()
else:
return "index", arg

Expand Down Expand Up @@ -347,11 +347,11 @@ class GridAgnosticWell(BoundaryCondition, IPointDataPackage, abc.ABC):

@property
def x(self) -> npt.NDArray[np.float64]:
return self.dataset["x"].values
return self.dataset["x"].to_numpy()

@property
def y(self) -> npt.NDArray[np.float64]:
return self.dataset["y"].values
return self.dataset["y"].to_numpy()

@classmethod
def _is_grid_agnostic_package(cls) -> bool:
Expand Down Expand Up @@ -394,7 +394,9 @@ def _create_dataset_vars(
# Carefully rename the dimension and set coordinates
d_rename = {"index": "ncellid"}
ds_vars = ds_vars.rename_dims(**d_rename).rename_vars(**d_rename)
ds_vars = ds_vars.assign_coords(**{"ncellid": cellid.coords["ncellid"].values})
ds_vars = ds_vars.assign_coords(
**{"ncellid": cellid.coords["ncellid"].to_numpy()}
)

return ds_vars

Expand Down Expand Up @@ -525,9 +527,9 @@ def _to_mf6_pkg(
ds = ds.assign(**data_vars_dict) # type: ignore[arg-type]

ds = remove_inactive(ds, idomain)
ds["save_flows"] = self["save_flows"].values[()]
ds["print_flows"] = self["print_flows"].values[()]
ds["print_input"] = self["print_input"].values[()]
ds["save_flows"] = enforce_scalar(self["save_flows"])
ds["print_flows"] = enforce_scalar(self["print_flows"])
ds["print_input"] = enforce_scalar(self["print_input"])

filtered_final_well_ids = self._gather_filtered_well_ids(ds, wells_df)
if len(filtered_final_well_ids) > 0:
Expand All @@ -537,8 +539,6 @@ def _to_mf6_pkg(
)
logger.log(loglevel=LogLevel.WARNING, message=message_end)

ds = ds.drop_vars("id")

data_vars_dict = {str(k): v for k, v in ds.data_vars.items()}
return Mf6Wel(**data_vars_dict) # type: ignore[arg-type]

Expand Down Expand Up @@ -1060,8 +1060,8 @@ def _find_well_value_at_layer(
if (value is not None) and is_spatial_grid(value):
value = imod.select.points_values(
value,
x=well_dataset["x"].values,
y=well_dataset["y"].values,
x=well_dataset["x"].to_numpy(),
y=well_dataset["y"].to_numpy(),
out_of_bounds="ignore",
)
in_bounds = np.full(well_dataset.sizes["index"], False)
Expand Down Expand Up @@ -1449,7 +1449,7 @@ def _validate_imod5_depth_information(
def from_imod5_cap_data(
cls,
imod5_data: Imod5DataDict,
target_dis: StructuredDiscretization,
target_dis: Optional[StructuredDiscretization] = None,
regridder_types: CapDataWellRegridMethod = CapDataWellRegridMethod(),
regrid_cache: RegridderWeightsCache = RegridderWeightsCache(),
):
Expand Down Expand Up @@ -1489,6 +1489,17 @@ def from_imod5_cap_data(
xarray datasets, under the key of the package type to which it
belongs, as returned by
:func:`imod.formats.prj.open_projectfile_data`.
target_dis: Optional[StructuredDiscretization]
The target discretization to which the data should be regridded.
Only necessary when "artificial_recharge_layer" is an IDF grid,
otherwise ignored.
regridder_types: CapDataWellRegridMethod
The regridder type to use for the regridding of the "artificial_recharge_layer"
and "artificial_recharge_capacity" grids. Only necessary when
"artificial_recharge_layer" is an IDF grid, otherwise ignored.
regrid_cache: RegridderWeightsCache
Cache for storing intermediate regridding results. Only necessary when
"artificial_recharge_layer" is an IDF grid, otherwise ignored.
"""
data = well_from_imod5_cap_data(
imod5_data, target_dis, regridder_types, regrid_cache
Expand Down
22 changes: 22 additions & 0 deletions imod/msw/regrid/regrid_schemes.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,28 @@ class SprinklingRegridMethod(DataclassType):
max_abstraction_surfacewater: RegridVarType = (RegridderType.OVERLAP, "mean")


@dataclass(config=_CONFIG)
class SprinklingPointsRegridMethod(DataclassType):
"""
Object containing regridder methods for the
:class:`imod.msw.Sprinkling` package. This can be provided to the
``regrid_like`` method to regrid with custom settings.

Parameters
----------
art_grid: tuple, default (RegridderType.OVERLAP, "mode")

Examples
--------
Regrid with custom settings:

>>> regrid_method = SprinklingPointsRegridMethod(art_grid=(RegridderType.OVERLAP,"min"))
>>> sprinking.regrid_like(target_grid, RegridderWeightsCache(), regrid_method)
"""

art_grid: RegridVarType = (RegridderType.OVERLAP, "mode")


@dataclass(config=_CONFIG)
class MeteoGridRegridMethod(DataclassType):
"""
Expand Down
Loading
Loading