Source code for imod.mf6.disv

from typing import List

import numpy as np
import pandas as pd

from imod.logging import init_log_decorator
from imod.mf6.interfaces.imaskingsettings import IMaskingSettings
from imod.mf6.interfaces.iregridpackage import IRegridPackage
from imod.mf6.package import Package
from imod.mf6.regrid.regrid_schemes import DiscretizationRegridMethod
from imod.mf6.validation import DisBottomSchema
from imod.mf6.write_context import WriteContext
from imod.schemata import (
    AllValueSchema,
    AnyValueSchema,
    DimsSchema,
    DTypeSchema,
    IdentityNoDataSchema,
    IndexesSchema,
)


[docs] class VerticesDiscretization(Package, IRegridPackage, IMaskingSettings): """ Discretization by Vertices (DISV). Parameters ---------- top: array of floats (xu.UgridDataArray) bottom: array of floats (xu.UgridDataArray) idomain: array of integers (xu.UgridDataArray) validate: {True, False} Flag to indicate whether the package should be validated upon initialization. This raises a ValidationError if package input is provided in the wrong manner. Defaults to True. """ _pkg_id = "disv" _init_schemata = { "top": [ DTypeSchema(np.floating), DimsSchema("{face_dim}") | DimsSchema(), IndexesSchema(), ], "bottom": [ DTypeSchema(np.floating), DimsSchema("layer", "{face_dim}") | DimsSchema("layer"), IndexesSchema(), ], "idomain": [ DTypeSchema(np.integer), DimsSchema("layer", "{face_dim}"), IndexesSchema(), ], } _write_schemata = { "idomain": (AnyValueSchema(">", 0),), "top": ( AllValueSchema(">", "bottom", ignore=("idomain", "==", -1)), IdentityNoDataSchema(other="idomain", is_other_notnull=(">", 0)), # No need to check coords: dataset ensures they align with idomain. ), "bottom": (DisBottomSchema(other="idomain", is_other_notnull=(">", 0)),), } _grid_data = {"top": np.float64, "bottom": np.float64, "idomain": np.int32} _keyword_map = {"bottom": "botm"} _template = Package._initialize_template(_pkg_id) _regrid_method = DiscretizationRegridMethod() @property def skip_variables(self) -> List[str]: return ["bottom"]
[docs] @init_log_decorator() def __init__(self, top, bottom, idomain, validate: bool = True): dict_dataset = { "idomain": idomain, "top": top, "bottom": bottom, } super().__init__(dict_dataset) self._validate_init_schemata(validate)
def render(self, directory, pkgname, globaltimes, binary): disdirectory = directory / pkgname d = {} grid = self.dataset.ugrid.grid d["xorigin"] = grid.node_x.min() d["yorigin"] = grid.node_y.min() d["nlay"] = self.dataset["idomain"].coords["layer"].size facedim = grid.face_dimension d["ncpl"] = self.dataset["idomain"].coords[facedim].size d["nvert"] = grid.node_x.size _, d["top"] = self._compose_values( self.dataset["top"], disdirectory, "top", binary=binary ) d["botm_layered"], d["botm"] = self._compose_values( self["bottom"], disdirectory, "botm", binary=binary ) d["idomain_layered"], d["idomain"] = self._compose_values( self["idomain"], disdirectory, "idomain", binary=binary ) return self._template.render(d) def _verts_dataframe(self) -> pd.DataFrame: grid = self.dataset.ugrid.grid df = pd.DataFrame(grid.node_coordinates) df.index += 1 return df def _cell2d_dataframe(self) -> pd.DataFrame: grid = self.dataset.ugrid.grid df = pd.DataFrame(grid.face_coordinates) df.index += 1 # modflow requires clockwise; ugrid requires ccw face_nodes = grid.face_node_connectivity[:, ::-1] df[2] = (face_nodes != grid.fill_value).sum(axis=1) for i, column in enumerate(face_nodes.T): # Use extension array to write empty values # Should be more efficient than mixed column? df[3 + i] = pd.arrays.IntegerArray( values=column + 1, mask=(column == grid.fill_value), ) return df def write_blockfile(self, pkgname, globaltimes, write_context: WriteContext): dir_for_render = write_context.get_formatted_write_directory() content = self.render( dir_for_render, pkgname, globaltimes, write_context.use_binary ) filename = write_context.write_directory / f"{pkgname}.{self._pkg_id}" with open(filename, "w") as f: f.write(content) f.write("\n\n") f.write("begin vertices\n") self._verts_dataframe().to_csv( f, header=False, sep=" ", lineterminator="\n" ) f.write("end vertices\n\n") f.write("begin cell2d\n") self._cell2d_dataframe().to_csv( f, header=False, sep=" ", lineterminator="\n" ) f.write("end cell2d\n") return def _validate(self, schemata, **kwargs): # Insert additional kwargs kwargs["bottom"] = self["bottom"] errors = super()._validate(schemata, **kwargs) return errors