Source code for imod.wq.lpf

import jinja2

from imod.wq.pkgbase import Package


[docs] class LayerPropertyFlow(Package): """ The Layer-Property Flow (LPF) package is used to specify properties controlling flow between cells. Parameters ---------- k_horizontal: float or xr.DataArray of floats is the hydraulic conductivity along rows (HK). HK is multiplied by horizontal anisotropy (see horizontal_anisotropy) to obtain hydraulic conductivity along columns. k_vertical: float or xr.DataArray of floats is the vertical hydraulic conductivity (VKA). horizontal_anisotropy: float or xr.DataArray of floats contains a value for each layer that is the horizontal anisotropy (CHANI). Use as many records as needed to enter a value of CHANI for each layer. The horizontal anisotropy is the ratio of the hydraulic conductivity along columns (the Y direction) to the hydraulic conductivity along rows (the X direction). interblock: int contains a flag for each layer that defines the method of calculating interblock transmissivity (LAYAVG). Use as many records needed to enter a value for each layer. 0 = harmonic mean (This is most appropriate for confined and unconfined aquifers with abrupt boundaries in transmissivity at the cell boundaries or for confined aquifers with uniform hydraulic conductivity). 1 = logarithmic mean (This is most appropriate for confined aquifers with gradually varying transmissivities). 2 = arithmetic mean of saturated thickness and logarithmic-mean hydraulic conductivity. (This is most appropriate for unconfined aquifers with gradually varying transmissivities). layer_type: int contains a flag for each layer that specifies the layer type (LAYTYP). Use as many records needed to enter a value for each layer. 0 = confined not 0 = convertible specific_storage: float or xr.DataArray of floats is specific storage (SS). Read only for a transient simulation (at least one transient stress period). Include only if at least one stress period is transient. Specific storage is the amount of water released when the head in an aquifer drops by 1 m, in one meter of the aquifer (or model layer). The unit is: ((m3 / m2) / m head change) / m aquifer = m-1 specific_yield: float or xr.DataArray of floats is specific yield (SY). Read only for a transient simulation (at least one transient stress period) and if the layer is convertible (layer_type is not 0). Include only if at least one stress period is transient. The specific yield is the volume of water released from (or added to) the pore matrix for one meter of head change. The unit is: (m3 / m2) / m head change = dimensionless save_budget: int is a flag and a unit number (ILPFCB). If save_budget > 0, it is the unit number to which cell-by-cell flow terms will be written when "SAVE BUDGET" or a non-zero value for save_budget is specified in Output Control. The terms that are saved are storage, constant-head flow, and flow between adjacent cells. If save_budget = 0, cell-by-cell flow terms will not be written. If save_budget < 0, cell-by-cell flow for constant-head cells will be written in the listing file when "SAVE BUDGET" or a non-zero value for ICBCFL is specified in Output Control. Cell-by-cell flow to storage and between adjacent cells will not be written to any file. The flow terms that will be saved are the flows through the right, front, and lower cell face. Positive values represent flows toward higher column, row, or layer numbers. layer_wet: int contains a flag for each layer that indicates if wetting is active. Use as many records as needed to enter a value for each layer. 0 = wetting is inactive not 0 = wetting is active interval_wet: int is the iteration interval for attempting to wet cells. Wetting is attempted every interval_wet iteration (IWETIT). If using the PCG solver (Hill, 1990), this applies to outer iterations, not inner iterations. If interval_wet less than or equal to 0, it is changed to 1. method_wet: int is a flag that determines which equation is used to define the initial head at cells that become wet (IHDWET). If method_wet = 0, this equation is used: h = BOT + WETFCT (hn - BOT). (hn is the head in the neighboring cell that is causing the dry cell to convert to an active cell.) If method_wet is not 0, this equation is used: h = BOT + WETFCT(THRESH). WETFCT is a factor that is included in the calculation of the head that is initially established at a cell when it is converted from dry to wet. head_dry: float, optional is the head that is assigned to cells that are converted to dry during a simulation (HDRY). Although this value plays no role in the model calculations, it is useful as an indicator when looking at the resulting heads that are output from the model. HDRY is thus similar to HNOFLO in the Basic Package, which is the value assigned to cells that are no-flow cells at the start of a model simulation. Default value: 1.0e20. """ _pkg_id = "lpf" _mapping = ( ("laytyp", "layer_type"), ("layavg", "interblock"), ("chani", "horizontal_anisotropy"), ("hk", "k_horizontal"), ("vka", "k_vertical"), ("ss", "specific_storage"), ("sy", "specific_yield"), ("laywet", "layer_wet"), ) _template = jinja2.Template( "[lpf]\n" " ilpfcb = {{save_budget}}\n" " hdry = {{head_dry}}\n" " layvka_l? = 0\n" " {%- for name, dictname in mapping -%}\n" " {%- for layer, value in dicts[dictname].items() %}\n" " {{name}}_l{{layer}} = {{value}}\n" " {%- endfor -%}\n" " {%- endfor -%}\n" ) _keywords = { "save_budget": {False: 0, True: 1}, "method_wet": {"wetfactor": 0, "bottom": 1}, }
[docs] def __init__( self, k_horizontal, k_vertical, horizontal_anisotropy=1.0, interblock=0, layer_type=0, specific_storage=0.0001, specific_yield=0.15, save_budget=False, layer_wet=0, interval_wet=0.001, method_wet="wetfactor", head_dry=1.0e20, ): super().__init__() self["k_horizontal"] = k_horizontal self["k_vertical"] = k_vertical self["horizontal_anisotropy"] = horizontal_anisotropy self["interblock"] = interblock self["layer_type"] = layer_type self["specific_storage"] = specific_storage self["specific_yield"] = specific_yield self["save_budget"] = save_budget self["layer_wet"] = layer_wet self["interval_wet"] = interval_wet self["method_wet"] = method_wet self["head_dry"] = head_dry
def _render(self, directory, nlayer, *args, **kwargs): d = {} # Don't include absentee members mapping = tuple( [(k, v) for k, v in self._mapping if v in self.dataset.data_vars] ) d["mapping"] = mapping dicts = {} da_vars = [t[1] for t in self._mapping] for varname in self.dataset.data_vars.keys(): if varname in da_vars: dicts[varname] = self._compose_values_layer( varname, directory, nlayer=nlayer ) else: d[varname] = self.dataset[varname].values if varname == "save_budget" or varname == "method_wet": self._replace_keyword(d, varname) d["dicts"] = dicts return self._template.render(d) def _pkgcheck(self, ibound=None): to_check = [ "k_horizontal", "k_vertical", "horizontal_anisotropy", "specific_storage", "specific_yield", ] self._check_positive(to_check) self._check_location_consistent(to_check)