Source code for hydromt_wflow.workflows.soilparams

"""Functions for individual soil parameters."""

import numpy as np
import xarray as xr
from hydromt import raster


[docs] def ksathorfrac( da: xr.DataArray, ds_like: xr.Dataset, resampling_method: str, ) -> xr.DataArray: """Create KsatHorfrac map. Based on the data properties of the WflowModel. Parameters ---------- da : xr.DataArray KsathorFrac values, i.e. an xarray.DataArray containing the values from \ the predefined KsatHorFrac map. ds_like : xr.Dataset Dataset at model resolution. resampling_method : str Scale method when up- or downscaling. Returns ------- xr.DataArray A xarray DataArray containing the scaled KsatHorFrac values. """ # Transfer data to a logaritmic scale da = np.log10(da) # Reproject the data da = da.raster.reproject_like( ds_like, method=resampling_method, ) # Scale the data back to normal values da = np.power(10, da) # Fill all nodata holes in the map da = da.interpolate_na(dim=da.raster.x_dim, method="linear") da = da.interpolate_na( dim=da.raster.x_dim, method="nearest", fill_value="extrapolate" ) # Set the default no fill value for doubles da = da.fillna(-9999.0) da.raster.set_nodata(-9999.0) # Return as a dataset to be used for 'set_grid' return da
def calc_kv_at_depth(depth, kv_0, f): """ Calculate the kv value at a certain depth. Value is based on the kv at the surface, the f parameter that describes the exponential decline and the depth. Parameters ---------- depth Depth at which kv needs to be calculated kv_0 The vertical conductivity at the surface f The value describing the exponential decline Returns ------- kv_z The kv value at the requested depth """ kv_z = kv_0 * np.exp(-f * depth) return kv_z def calc_kvfrac(kv_depth, target): """Calculate the kvfrac. Based on the kv value at a certain depth and the target value. Parameters ---------- kv_depth: Value of kv at a certain depth target: Target kv value Returns ------- kvfrac: The value which kv_depths needs to be multiplied with to reach the target value """ kvfrac = target / kv_depth return kvfrac def update_kvfrac( ds_model, kv0_mask, f_mask, wflow_thicknesslayers, target_conductivity ): """ Calculate kvfrac values for each layer. Done such that the bottom of the layer equals to the target_conductivity. Calculation assumes exponentially declining vertical conductivities, based on the f parameter. If no target_conductivity is specified, kvfrac is set to be equal to 1. Parameters ---------- ds_model Dataset of the wflow model kv0_mask Values of vertical conductivity at the surface, masked to paddy locations f_mask Values of the f parameter, masked to paddy locations wflow_thicknesslayers List of requested layers in the wflow model target_conductivity List of target conductivities for each layer (None if no target value is requested) Returns ------- da_kvfrac Maps for each layer with the required kvfrac value """ # Convert to np.array wflow_thicknesslayers = np.array(wflow_thicknesslayers) target_conductivity = np.array(target_conductivity) # Prepare emtpy dataarray da_kvfrac = raster.full_like(ds_model["c"]) # Set all values to 1 da_kvfrac = da_kvfrac.where( ds_model["wflow_dem"].raster.mask_nodata().isnull(), 1.0 ) # Get the actual depths wflow_depths = np.cumsum(wflow_thicknesslayers) # Find the index of the layers where a kvfrac should be set idx = np.where(target_conductivity is not None)[0] # Loop through the target_conductivity values for idx, target in enumerate(target_conductivity): if target is not None: depth = wflow_depths[idx] # Calculate the kv at that depth (only for the pixels that have paddy # fields) kv_depth = calc_kv_at_depth(depth=depth, kv_0=kv0_mask, f=f_mask) paddy_values = calc_kvfrac(kv_depth=kv_depth, target=target) # Set the values in the correct places kvfrac = xr.where( paddy_values.raster.mask_nodata().isnull(), da_kvfrac.loc[dict(layer=idx)], paddy_values, ) kvfrac = kvfrac.fillna(-9999) kvfrac.raster.set_nodata(-9999) # Update layer in dataarray da_kvfrac.loc[dict(layer=idx)] = kvfrac return da_kvfrac