Source code for imod.msw.idf_mapping

from dataclasses import asdict
from typing import Optional

import numpy as np
import xarray as xr

from imod.mf6.interfaces.iregridpackage import IRegridPackage
from imod.mf6.utilities.regrid import RegridderWeightsCache, _regrid_array
from imod.msw.fixed_format import VariableMetaData
from imod.msw.pkgbase import MetaSwapPackage
from imod.msw.regrid.regrid_schemes import IdfMappingRegridMethod
from imod.typing import GridDataArray
from imod.util.regrid_method_type import RegridMethodType
from imod.util.spatial import spatial_reference


[docs] class IdfMapping(MetaSwapPackage, IRegridPackage): """ Describes svat location in the IDF grid. Note that MetaSWAP can only write equidistant grids. """ _file_name = "idf_svat.inp" _metadata_dict = { "svat": VariableMetaData(10, 1, 9999999, int), "rows": VariableMetaData(10, 1, 9999999, int), "columns": VariableMetaData(10, 1, 9999999, int), "y_grid": VariableMetaData(15, -9999999.0, 9999999.0, float), "x_grid": VariableMetaData(15, -9999999.0, 9999999.0, float), } _with_subunit = () _without_subunit = ("rows", "columns", "y_grid", "x_grid") _to_fill = () _regrid_method = IdfMappingRegridMethod() # NOTE that it is stated in the IO manual: "The x- and y-coordinates should # increase with increasing col, row." But the example works with decreasing # y-coordinates.
[docs] def __init__(self, area, nodata): super().__init__() self.dataset["area"] = area self.dataset["nodata"] = nodata nrow = self.dataset.coords["y"].size ncol = self.dataset.coords["x"].size y_index = xr.DataArray( np.arange(1, nrow + 1), coords={"y": self.dataset.coords["y"]}, dims=("y",) ) x_index = xr.DataArray( np.arange(1, ncol + 1), coords={"x": self.dataset.coords["x"]}, dims=("x",) ) rows, columns = xr.broadcast(y_index, x_index) self.dataset["rows"] = rows self.dataset["columns"] = columns y_grid, x_grid = xr.broadcast(self.dataset["y"], self.dataset["x"]) self.dataset["x_grid"] = x_grid self.dataset["y_grid"] = y_grid
def get_output_settings(self): grid = self.dataset["area"] dx, xmin, _, dy, ymin, _ = spatial_reference(grid) ncol = grid["x"].size nrow = grid["y"].size # If non-equidistant, spatial_reference returned a 1d array instead of # float if (not np.isscalar(dx)) or (not np.isscalar(dy)): raise ValueError("MetaSWAP only supports equidistant grids") nodata = self.dataset["nodata"].values return { "simgro_opt": -1, "idf_per": 1, "idf_dx": dx, "idf_dy": np.abs(dy), "idf_ncol": ncol, "idf_nrow": nrow, "idf_xmin": xmin, "idf_ymin": ymin, "idf_nodata": nodata, } def regrid_like( self, target_grid: GridDataArray, regrid_context: RegridderWeightsCache, regridder_types: Optional[RegridMethodType] = None, ) -> "MetaSwapPackage": if regridder_types is None: regridder_settings = asdict(self.get_regrid_methods(), dict_factory=dict) else: regridder_settings = asdict(regridder_types, dict_factory=dict) nodata = self.dataset["nodata"].values[()] regridded_area = _regrid_array( self.dataset["area"], regrid_context, regridder_settings["area"][0], regridder_settings["area"][1], target_grid, ) return type(self)(regridded_area, nodata)