Most MF6 packages have spatial data arrays as input. These arrays are discrete: they are defined over the simulation grid and contain values associated to each cell.
Regridding these package means: create a new package with spatial data arrays defined over a different grid. Computing what the values in these new arrays should be, is done by xugrid.
xugrid will compute a regridded array based on:
the original array
the original discretization (this is described in the coordinates of the original arry)
the new discretization
a regridding method
More information on the available regridding methods can be found in the xugrid documentation https://deltares.github.io/xugrid/user_guide.html
The regridding method that should be used depends on the property being regridded. For example a thermodynamically intensive property (whose value do not depend intrinsically on the grid block size) such as temperature or density can be regridded by an averaging approach (for upscaling) or sampling (for downscaling). Extensive properties (whose values do depend on the grid block size) include (water) mass and pore volume of a gridblock, and the regridding method should be chosen to reflect that. Finally regridding methods for conductivity-like properties follow the rules for parallel or serial resistors- at least when the tensor rotation angles are constant or comparable in the involved gridblocks.
Note that the different regridding methods may have a different output domain when regridding: if the original array has no-data values in some cells, then the output array may have no-data values as well, and where these end up depends on the chosen regridding method. Also note that regridding is only possible in the xy-plane, and not across the layer dimension. The output array will have the same number of layers as the input array.
Obtaining the final (i)domain#In many real-world models, some cells will be inactive or marked as “vertical passthrough” (VPT) in the idomain array of the simulation. Some packages require that all cells that are inactictive or VPT in idomain are excluded from the package as well. An example is the npf package: cells that are inactive or VPT in idomain, should not have conductivity data in the npf package. Therefore at the end of the regridding process, a final step consists in enforcing consistency between those of idomain and all the packages. This is a 2-step process:
for cells that do not have inputs in crucial packages like npf or storage, idomain will be set to inactive.
for cells that are marked as inactive or VPT in idomain, all package inputs will be removed from all the packages
This synchronization step between idomain and the packages is automated, and it is carried out when calling regrid_like on the simulation object or the model object. There are 2 caveats:
the synchronization between idomain and the package domains is done on the model-level. If we have a simulation containing both a flow model and a transport model then idomain for flow is determined independent from that for transport. These models may therefore end up using different domains (this may lead to undesired results, so a manual synchronization may be necessary between the flow regridding and the transport regridding) This manual synchronization can be done using the “mask_all_packages” function- this function removes input from all packages that are marked as inactive or VPT in the idomain passed to this method.
The idomain/packages synchronization step is carried out when regridding a model, and when regridding a model it will use default methods for all the packages. So if you have regridded some packages yourself with non-default methods, then these are not taken into account during this synchonization step.
The regrid_like function is available on packages, models and simulations. When the default methods are acceptable, regridding the whole simulation is the most convenient from a user-perspective.
Regridding using non-default methods#When non-default methods are used for one or more packages, these should be regridded separately. In that case, the most convenient approach is likely:
pop the packages that should use non-default methods from the source simulation (the popping is optional, and is only recommended for packages whose presence is not mandatory for validation.)
regrid the source simulation: this takes care of all the packages that should use default methods.
regrid the package(s) where you want to use non-standard rergridding methods indivudually starting from the packages in the source simulation
insert the custom-regridded packages to the regridded simulation (or replace the package regridded with default methods with the one you just regridded with non-default methods if it was not popped)
In code, consider an example where we want to regrid the recharge package using non default methods then we would do the following. First we’ll load some example simulation. There is a separate example contained in Regional model that you should look at if you are interested in the model building
import imod tmpdir = imod.util.temporary_directory() original_simulation = imod.data.hondsrug_simulation(tmpdir / "hondsrug_saved")
To reduce computational overhead for this example, we are going to clip off most of the timesteps.
original_simulation = original_simulation.clip_box(time_max="2010-01-01")
Let’s take a look at the original discretization:
original_simulation["GWF"]["dis"]
StructuredDiscretization
<xarray.Dataset> Size: 11MB Dimensions: (x: 500, y: 200, layer: 13) Coordinates: * x (x) float64 4kB 2.375e+05 2.375e+05 2.376e+05 ... 2.5e+05 2.5e+05 * y (y) float64 2kB 5.64e+05 5.64e+05 5.639e+05 ... 5.59e+05 5.59e+05 dx float64 8B ... dy float64 8B ... * layer (layer) int32 52B 1 2 3 4 5 6 7 8 9 10 11 12 13 Data variables: idomain (layer, y, x) int32 5MB ... top (y, x) float32 400kB ... bottom (layer, y, x) float32 5MB ...
x
(x)
float64
2.375e+05 2.375e+05 ... 2.5e+05
array([237512.5, 237537.5, 237562.5, ..., 249937.5, 249962.5, 249987.5], shape=(500,))
y
(y)
float64
5.64e+05 5.64e+05 ... 5.59e+05
array([563987.5, 563962.5, 563937.5, 563912.5, 563887.5, 563862.5, 563837.5, 563812.5, 563787.5, 563762.5, 563737.5, 563712.5, 563687.5, 563662.5, 563637.5, 563612.5, 563587.5, 563562.5, 563537.5, 563512.5, 563487.5, 563462.5, 563437.5, 563412.5, 563387.5, 563362.5, 563337.5, 563312.5, 563287.5, 563262.5, 563237.5, 563212.5, 563187.5, 563162.5, 563137.5, 563112.5, 563087.5, 563062.5, 563037.5, 563012.5, 562987.5, 562962.5, 562937.5, 562912.5, 562887.5, 562862.5, 562837.5, 562812.5, 562787.5, 562762.5, 562737.5, 562712.5, 562687.5, 562662.5, 562637.5, 562612.5, 562587.5, 562562.5, 562537.5, 562512.5, 562487.5, 562462.5, 562437.5, 562412.5, 562387.5, 562362.5, 562337.5, 562312.5, 562287.5, 562262.5, 562237.5, 562212.5, 562187.5, 562162.5, 562137.5, 562112.5, 562087.5, 562062.5, 562037.5, 562012.5, 561987.5, 561962.5, 561937.5, 561912.5, 561887.5, 561862.5, 561837.5, 561812.5, 561787.5, 561762.5, 561737.5, 561712.5, 561687.5, 561662.5, 561637.5, 561612.5, 561587.5, 561562.5, 561537.5, 561512.5, 561487.5, 561462.5, 561437.5, 561412.5, 561387.5, 561362.5, 561337.5, 561312.5, 561287.5, 561262.5, 561237.5, 561212.5, 561187.5, 561162.5, 561137.5, 561112.5, 561087.5, 561062.5, 561037.5, 561012.5, 560987.5, 560962.5, 560937.5, 560912.5, 560887.5, 560862.5, 560837.5, 560812.5, 560787.5, 560762.5, 560737.5, 560712.5, 560687.5, 560662.5, 560637.5, 560612.5, 560587.5, 560562.5, 560537.5, 560512.5, 560487.5, 560462.5, 560437.5, 560412.5, 560387.5, 560362.5, 560337.5, 560312.5, 560287.5, 560262.5, 560237.5, 560212.5, 560187.5, 560162.5, 560137.5, 560112.5, 560087.5, 560062.5, 560037.5, 560012.5, 559987.5, 559962.5, 559937.5, 559912.5, 559887.5, 559862.5, 559837.5, 559812.5, 559787.5, 559762.5, 559737.5, 559712.5, 559687.5, 559662.5, 559637.5, 559612.5, 559587.5, 559562.5, 559537.5, 559512.5, 559487.5, 559462.5, 559437.5, 559412.5, 559387.5, 559362.5, 559337.5, 559312.5, 559287.5, 559262.5, 559237.5, 559212.5, 559187.5, 559162.5, 559137.5, 559112.5, 559087.5, 559062.5, 559037.5, 559012.5])
dx
()
float64
...
[1 values with dtype=float64]
dy
()
float64
...
[1 values with dtype=float64]
layer
(layer)
int32
1 2 3 4 5 6 7 8 9 10 11 12 13
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], dtype=int32)
idomain
(layer, y, x)
int32
...
[1300000 values with dtype=int32]
top
(y, x)
float32
...
[100000 values with dtype=float32]
bottom
(layer, y, x)
float32
...
[1300000 values with dtype=float32]
PandasIndex
PandasIndex(Index([237512.5, 237537.5, 237562.5, 237587.5, 237612.5, 237637.5, 237662.5, 237687.5, 237712.5, 237737.5, ... 249762.5, 249787.5, 249812.5, 249837.5, 249862.5, 249887.5, 249912.5, 249937.5, 249962.5, 249987.5], dtype='float64', name='x', length=500))
PandasIndex
PandasIndex(Index([563987.5, 563962.5, 563937.5, 563912.5, 563887.5, 563862.5, 563837.5, 563812.5, 563787.5, 563762.5, ... 559237.5, 559212.5, 559187.5, 559162.5, 559137.5, 559112.5, 559087.5, 559062.5, 559037.5, 559012.5], dtype='float64', name='y', length=200))
PandasIndex
PandasIndex(Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], dtype='int32', name='layer'))
We want to regrid this to the following target grid:
import xarray as xr import imod dx = 100 dy = -100 xmin = 237500.0 xmax = 250000.0 ymin = 559000.0 ymax = 564000.0 target_grid = imod.util.empty_2d( dx=dx, dy=dy, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax ) target_grid
<xarray.DataArray (y: 50, x: 125)> Size: 50kB array([[nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], ..., [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], shape=(50, 125)) Coordinates: * x (x) float64 1kB 2.376e+05 2.376e+05 2.378e+05 ... 2.498e+05 2.5e+05 * y (y) float64 400B 5.64e+05 5.638e+05 ... 5.592e+05 5.59e+05 dx float64 8B 100.0 dy float64 8B -100.0
nan nan nan nan nan nan nan nan ... nan nan nan nan nan nan nan nan
array([[nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], ..., [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], shape=(50, 125))
x
(x)
float64
2.376e+05 2.376e+05 ... 2.5e+05
array([237550., 237650., 237750., 237850., 237950., 238050., 238150., 238250., 238350., 238450., 238550., 238650., 238750., 238850., 238950., 239050., 239150., 239250., 239350., 239450., 239550., 239650., 239750., 239850., 239950., 240050., 240150., 240250., 240350., 240450., 240550., 240650., 240750., 240850., 240950., 241050., 241150., 241250., 241350., 241450., 241550., 241650., 241750., 241850., 241950., 242050., 242150., 242250., 242350., 242450., 242550., 242650., 242750., 242850., 242950., 243050., 243150., 243250., 243350., 243450., 243550., 243650., 243750., 243850., 243950., 244050., 244150., 244250., 244350., 244450., 244550., 244650., 244750., 244850., 244950., 245050., 245150., 245250., 245350., 245450., 245550., 245650., 245750., 245850., 245950., 246050., 246150., 246250., 246350., 246450., 246550., 246650., 246750., 246850., 246950., 247050., 247150., 247250., 247350., 247450., 247550., 247650., 247750., 247850., 247950., 248050., 248150., 248250., 248350., 248450., 248550., 248650., 248750., 248850., 248950., 249050., 249150., 249250., 249350., 249450., 249550., 249650., 249750., 249850., 249950.])
y
(y)
float64
5.64e+05 5.638e+05 ... 5.59e+05
array([563950., 563850., 563750., 563650., 563550., 563450., 563350., 563250., 563150., 563050., 562950., 562850., 562750., 562650., 562550., 562450., 562350., 562250., 562150., 562050., 561950., 561850., 561750., 561650., 561550., 561450., 561350., 561250., 561150., 561050., 560950., 560850., 560750., 560650., 560550., 560450., 560350., 560250., 560150., 560050., 559950., 559850., 559750., 559650., 559550., 559450., 559350., 559250., 559150., 559050.])
dx
()
float64
100.0
dy
()
float64
-100.0
PandasIndex
PandasIndex(Index([237550.0, 237650.0, 237750.0, 237850.0, 237950.0, 238050.0, 238150.0, 238250.0, 238350.0, 238450.0, ... 249050.0, 249150.0, 249250.0, 249350.0, 249450.0, 249550.0, 249650.0, 249750.0, 249850.0, 249950.0], dtype='float64', name='x', length=125))
PandasIndex
PandasIndex(Index([563950.0, 563850.0, 563750.0, 563650.0, 563550.0, 563450.0, 563350.0, 563250.0, 563150.0, 563050.0, 562950.0, 562850.0, 562750.0, 562650.0, 562550.0, 562450.0, 562350.0, 562250.0, 562150.0, 562050.0, 561950.0, 561850.0, 561750.0, 561650.0, 561550.0, 561450.0, 561350.0, 561250.0, 561150.0, 561050.0, 560950.0, 560850.0, 560750.0, 560650.0, 560550.0, 560450.0, 560350.0, 560250.0, 560150.0, 560050.0, 559950.0, 559850.0, 559750.0, 559650.0, 559550.0, 559450.0, 559350.0, 559250.0, 559150.0, 559050.0], dtype='float64', name='y'))
This is a grid of nans, and we require a grid of ones, which can create with xarray:
target_grid = xr.ones_like(target_grid) target_grid
<xarray.DataArray (y: 50, x: 125)> Size: 50kB array([[1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], ..., [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.]], shape=(50, 125)) Coordinates: * x (x) float64 1kB 2.376e+05 2.376e+05 2.378e+05 ... 2.498e+05 2.5e+05 * y (y) float64 400B 5.64e+05 5.638e+05 ... 5.592e+05 5.59e+05 dx float64 8B 100.0 dy float64 8B -100.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 ... 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
array([[1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], ..., [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.], [1., 1., 1., ..., 1., 1., 1.]], shape=(50, 125))
x
(x)
float64
2.376e+05 2.376e+05 ... 2.5e+05
array([237550., 237650., 237750., 237850., 237950., 238050., 238150., 238250., 238350., 238450., 238550., 238650., 238750., 238850., 238950., 239050., 239150., 239250., 239350., 239450., 239550., 239650., 239750., 239850., 239950., 240050., 240150., 240250., 240350., 240450., 240550., 240650., 240750., 240850., 240950., 241050., 241150., 241250., 241350., 241450., 241550., 241650., 241750., 241850., 241950., 242050., 242150., 242250., 242350., 242450., 242550., 242650., 242750., 242850., 242950., 243050., 243150., 243250., 243350., 243450., 243550., 243650., 243750., 243850., 243950., 244050., 244150., 244250., 244350., 244450., 244550., 244650., 244750., 244850., 244950., 245050., 245150., 245250., 245350., 245450., 245550., 245650., 245750., 245850., 245950., 246050., 246150., 246250., 246350., 246450., 246550., 246650., 246750., 246850., 246950., 247050., 247150., 247250., 247350., 247450., 247550., 247650., 247750., 247850., 247950., 248050., 248150., 248250., 248350., 248450., 248550., 248650., 248750., 248850., 248950., 249050., 249150., 249250., 249350., 249450., 249550., 249650., 249750., 249850., 249950.])
y
(y)
float64
5.64e+05 5.638e+05 ... 5.59e+05
array([563950., 563850., 563750., 563650., 563550., 563450., 563350., 563250., 563150., 563050., 562950., 562850., 562750., 562650., 562550., 562450., 562350., 562250., 562150., 562050., 561950., 561850., 561750., 561650., 561550., 561450., 561350., 561250., 561150., 561050., 560950., 560850., 560750., 560650., 560550., 560450., 560350., 560250., 560150., 560050., 559950., 559850., 559750., 559650., 559550., 559450., 559350., 559250., 559150., 559050.])
dx
()
float64
100.0
dy
()
float64
-100.0
PandasIndex
PandasIndex(Index([237550.0, 237650.0, 237750.0, 237850.0, 237950.0, 238050.0, 238150.0, 238250.0, 238350.0, 238450.0, ... 249050.0, 249150.0, 249250.0, 249350.0, 249450.0, 249550.0, 249650.0, 249750.0, 249850.0, 249950.0], dtype='float64', name='x', length=125))
PandasIndex
PandasIndex(Index([563950.0, 563850.0, 563750.0, 563650.0, 563550.0, 563450.0, 563350.0, 563250.0, 563150.0, 563050.0, 562950.0, 562850.0, 562750.0, 562650.0, 562550.0, 562450.0, 562350.0, 562250.0, 562150.0, 562050.0, 561950.0, 561850.0, 561750.0, 561650.0, 561550.0, 561450.0, 561350.0, 561250.0, 561150.0, 561050.0, 560950.0, 560850.0, 560750.0, 560650.0, 560550.0, 560450.0, 560350.0, 560250.0, 560150.0, 560050.0, 559950.0, 559850.0, 559750.0, 559650.0, 559550.0, 559450.0, 559350.0, 559250.0, 559150.0, 559050.0], dtype='float64', name='y'))
Next, we’ll remove the recharge package and obtain it as a variable:
original_rch_package = original_simulation["GWF"].pop("rch") original_rch_package
Recharge
<xarray.Dataset> Size: 21MB Dimensions: (y: 200, x: 500, layer: 13, time: 2) Coordinates: * y (y) float64 2kB 5.64e+05 5.64e+05 ... 5.59e+05 5.59e+05 * x (x) float64 4kB 2.375e+05 2.375e+05 ... 2.5e+05 2.5e+05 dx float64 8B ... dy float64 8B ... * layer (layer) int32 52B 1 2 3 4 5 6 7 8 9 10 11 12 13 * time (time) datetime64[ns] 16B 2009-12-30T23:59:59 2009-12-31 Data variables: rate (time, layer, y, x) float64 21MB nan nan nan ... nan nan nan print_input bool 1B False print_flows bool 1B False save_flows bool 1B False observations object 8B None repeat_stress object 8B None
y
(y)
float64
5.64e+05 5.64e+05 ... 5.59e+05
array([563987.5, 563962.5, 563937.5, 563912.5, 563887.5, 563862.5, 563837.5, 563812.5, 563787.5, 563762.5, 563737.5, 563712.5, 563687.5, 563662.5, 563637.5, 563612.5, 563587.5, 563562.5, 563537.5, 563512.5, 563487.5, 563462.5, 563437.5, 563412.5, 563387.5, 563362.5, 563337.5, 563312.5, 563287.5, 563262.5, 563237.5, 563212.5, 563187.5, 563162.5, 563137.5, 563112.5, 563087.5, 563062.5, 563037.5, 563012.5, 562987.5, 562962.5, 562937.5, 562912.5, 562887.5, 562862.5, 562837.5, 562812.5, 562787.5, 562762.5, 562737.5, 562712.5, 562687.5, 562662.5, 562637.5, 562612.5, 562587.5, 562562.5, 562537.5, 562512.5, 562487.5, 562462.5, 562437.5, 562412.5, 562387.5, 562362.5, 562337.5, 562312.5, 562287.5, 562262.5, 562237.5, 562212.5, 562187.5, 562162.5, 562137.5, 562112.5, 562087.5, 562062.5, 562037.5, 562012.5, 561987.5, 561962.5, 561937.5, 561912.5, 561887.5, 561862.5, 561837.5, 561812.5, 561787.5, 561762.5, 561737.5, 561712.5, 561687.5, 561662.5, 561637.5, 561612.5, 561587.5, 561562.5, 561537.5, 561512.5, 561487.5, 561462.5, 561437.5, 561412.5, 561387.5, 561362.5, 561337.5, 561312.5, 561287.5, 561262.5, 561237.5, 561212.5, 561187.5, 561162.5, 561137.5, 561112.5, 561087.5, 561062.5, 561037.5, 561012.5, 560987.5, 560962.5, 560937.5, 560912.5, 560887.5, 560862.5, 560837.5, 560812.5, 560787.5, 560762.5, 560737.5, 560712.5, 560687.5, 560662.5, 560637.5, 560612.5, 560587.5, 560562.5, 560537.5, 560512.5, 560487.5, 560462.5, 560437.5, 560412.5, 560387.5, 560362.5, 560337.5, 560312.5, 560287.5, 560262.5, 560237.5, 560212.5, 560187.5, 560162.5, 560137.5, 560112.5, 560087.5, 560062.5, 560037.5, 560012.5, 559987.5, 559962.5, 559937.5, 559912.5, 559887.5, 559862.5, 559837.5, 559812.5, 559787.5, 559762.5, 559737.5, 559712.5, 559687.5, 559662.5, 559637.5, 559612.5, 559587.5, 559562.5, 559537.5, 559512.5, 559487.5, 559462.5, 559437.5, 559412.5, 559387.5, 559362.5, 559337.5, 559312.5, 559287.5, 559262.5, 559237.5, 559212.5, 559187.5, 559162.5, 559137.5, 559112.5, 559087.5, 559062.5, 559037.5, 559012.5])
x
(x)
float64
2.375e+05 2.375e+05 ... 2.5e+05
array([237512.5, 237537.5, 237562.5, ..., 249937.5, 249962.5, 249987.5], shape=(500,))
dx
()
float64
...
[1 values with dtype=float64]
dy
()
float64
...
[1 values with dtype=float64]
layer
(layer)
int32
1 2 3 4 5 6 7 8 9 10 11 12 13
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], dtype=int32)
time
(time)
datetime64[ns]
2009-12-30T23:59:59 2009-12-31
array(['2009-12-30T23:59:59.000000000', '2009-12-31T00:00:00.000000000'], dtype='datetime64[ns]')
rate
(time, layer, y, x)
float64
nan nan nan nan ... nan nan nan nan
array([[[[ nan, ..., 0.000834], ..., [0.000918, ..., nan]], ..., [[ nan, ..., nan], ..., [ nan, ..., nan]]], [[[ nan, ..., 0.001638], ..., [0.001982, ..., nan]], ..., [[ nan, ..., nan], ..., [ nan, ..., nan]]]], shape=(2, 13, 200, 500))
print_input
()
bool
False
print_flows
()
bool
False
save_flows
()
bool
False
observations
()
object
None
array(None, dtype=object)
repeat_stress
()
object
None
array(None, dtype=object)
PandasIndex
PandasIndex(Index([563987.5, 563962.5, 563937.5, 563912.5, 563887.5, 563862.5, 563837.5, 563812.5, 563787.5, 563762.5, ... 559237.5, 559212.5, 559187.5, 559162.5, 559137.5, 559112.5, 559087.5, 559062.5, 559037.5, 559012.5], dtype='float64', name='y', length=200))
PandasIndex
PandasIndex(Index([237512.5, 237537.5, 237562.5, 237587.5, 237612.5, 237637.5, 237662.5, 237687.5, 237712.5, 237737.5, ... 249762.5, 249787.5, 249812.5, 249837.5, 249862.5, 249887.5, 249912.5, 249937.5, 249962.5, 249987.5], dtype='float64', name='x', length=500))
PandasIndex
PandasIndex(Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], dtype='int32', name='layer'))
PandasIndex
PandasIndex(DatetimeIndex(['2009-12-30 23:59:59', '2009-12-31 00:00:00'], dtype='datetime64[ns]', name='time', freq=None))
Now regrid the simulation (without recharge):
regridded_simulation = original_simulation.regrid_like("regridded", target_grid)
Let’s look at the discretization again:
regridded_simulation["GWF"]["dis"]
StructuredDiscretization
<xarray.Dataset> Size: 1MB Dimensions: (layer: 13, y: 50, x: 125) Coordinates: dx float64 8B 100.0 dy float64 8B -100.0 * layer (layer) int32 52B 1 2 3 4 5 6 7 8 9 10 11 12 13 * y (y) float64 400B 5.64e+05 5.638e+05 ... 5.592e+05 5.59e+05 * x (x) float64 1kB 2.376e+05 2.376e+05 2.378e+05 ... 2.498e+05 2.5e+05 Data variables: idomain (layer, y, x) int64 650kB -16 -16 -16 -16 -16 -16 ... 1 1 1 1 1 1 top (y, x) float32 25kB nan nan nan nan nan nan ... nan nan nan nan nan bottom (layer, y, x) float32 325kB 6.329 6.432 6.536 ... -166.8 -166.8
dx
()
float64
100.0
dy
()
float64
-100.0
layer
(layer)
int32
1 2 3 4 5 6 7 8 9 10 11 12 13
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], dtype=int32)
y
(y)
float64
5.64e+05 5.638e+05 ... 5.59e+05
array([563950., 563850., 563750., 563650., 563550., 563450., 563350., 563250., 563150., 563050., 562950., 562850., 562750., 562650., 562550., 562450., 562350., 562250., 562150., 562050., 561950., 561850., 561750., 561650., 561550., 561450., 561350., 561250., 561150., 561050., 560950., 560850., 560750., 560650., 560550., 560450., 560350., 560250., 560150., 560050., 559950., 559850., 559750., 559650., 559550., 559450., 559350., 559250., 559150., 559050.])
x
(x)
float64
2.376e+05 2.376e+05 ... 2.5e+05
array([237550., 237650., 237750., 237850., 237950., 238050., 238150., 238250., 238350., 238450., 238550., 238650., 238750., 238850., 238950., 239050., 239150., 239250., 239350., 239450., 239550., 239650., 239750., 239850., 239950., 240050., 240150., 240250., 240350., 240450., 240550., 240650., 240750., 240850., 240950., 241050., 241150., 241250., 241350., 241450., 241550., 241650., 241750., 241850., 241950., 242050., 242150., 242250., 242350., 242450., 242550., 242650., 242750., 242850., 242950., 243050., 243150., 243250., 243350., 243450., 243550., 243650., 243750., 243850., 243950., 244050., 244150., 244250., 244350., 244450., 244550., 244650., 244750., 244850., 244950., 245050., 245150., 245250., 245350., 245450., 245550., 245650., 245750., 245850., 245950., 246050., 246150., 246250., 246350., 246450., 246550., 246650., 246750., 246850., 246950., 247050., 247150., 247250., 247350., 247450., 247550., 247650., 247750., 247850., 247950., 248050., 248150., 248250., 248350., 248450., 248550., 248650., 248750., 248850., 248950., 249050., 249150., 249250., 249350., 249450., 249550., 249650., 249750., 249850., 249950.])
idomain
(layer, y, x)
int64
-16 -16 -16 -16 -16 ... 1 1 1 1 1
array([[[-16, -16, -16, ..., 1, 1, 1], [-16, -16, -16, ..., 1, 1, 1], [-16, -16, -16, ..., 1, 1, 1], ..., [ 1, 1, 1, ..., -16, -16, -16], [ 1, 1, 1, ..., -16, -16, -16], [ 1, 1, 1, ..., -16, -16, -16]], [[-16, -16, -16, ..., -16, -16, -16], [-16, -16, -16, ..., -16, -16, -16], [-16, -16, -16, ..., -16, -16, -16], ..., [-16, -16, -16, ..., -16, -16, -16], [-16, -16, -16, ..., -16, -16, -16], [-16, -16, -16, ..., -16, -16, -16]], [[ 1, 1, 1, ..., 1, 1, 1], [ 1, 1, 1, ..., 1, 1, 1], [ 1, 1, 1, ..., 1, 1, 1], ..., ... ..., [ 1, 1, 1, ..., 1, 1, 1], [ 1, 1, 1, ..., 1, 1, 1], [ 1, 1, 1, ..., 1, 1, 1]], [[ 1, 1, 1, ..., -16, -16, -16], [ 1, 1, 1, ..., -16, -16, -16], [ 1, 1, 1, ..., -16, -16, -16], ..., [-16, -16, -16, ..., -16, -16, -16], [-16, -16, -16, ..., -16, -16, -16], [-16, -16, -16, ..., -16, -16, -16]], [[ 1, 1, 1, ..., 1, 1, 1], [ 1, 1, 1, ..., 1, 1, 1], [ 1, 1, 1, ..., 1, 1, 1], ..., [ 1, 1, 1, ..., 1, 1, 1], [ 1, 1, 1, ..., 1, 1, 1], [ 1, 1, 1, ..., 1, 1, 1]]], shape=(13, 50, 125))
top
(y, x)
float32
nan nan nan nan ... nan nan nan nan
array([[ nan, nan, nan, ..., 2.422 , 2.4668 , 2.5116 ], [ nan, nan, nan, ..., 2.336 , 2.3724 , 2.4088 ], [ nan, nan, nan, ..., 2.25 , 2.278 , 2.306 ], ..., [9.574 , 9.092 , 8.61 , ..., nan, nan, nan], [9.4996 , 9.1048 , 8.71 , ..., nan, nan, nan], [9.4252 , 9.117599, 8.809999, ..., nan, nan, nan]], shape=(50, 125), dtype=float32)
bottom
(layer, y, x)
float32
6.329 6.432 6.536 ... -166.8 -166.8
array([[[ 6.3288 , 6.4324 , 6.536 , ..., -4.072 , -2.7284 , -1.3848 ], [ 6.4664 , 6.6172 , 6.768 , ..., -4.656 , -3.2212 , -1.7864 ], [ 6.604 , 6.802 , 7. , ..., -5.24 , -3.714 , -2.188 ], ..., [ 7.888 , 7.724 , 7.56 , ..., 2.92 , 2.952 , 2.984 ], [ 8.0056 , 7.8608 , 7.716 , ..., 3.088 , 3.0896 , 3.0912 ], [ 8.1232 , 7.9976 , 7.872 , ..., 3.256 , 3.2272 , 3.1984 ]], [[ 6.3288 , 6.4324 , 6.536 , ..., -4.072 , -2.7284 , -1.3848 ], [ 6.4664 , 6.6172 , 6.768 , ..., -4.656 , -3.2212 , -1.7864 ], [ 6.604 , 6.802 , 7. , ..., -5.24 , -3.714 , -2.188 ], ... [-100.706 , -100.408 , -100.11 , ..., -88.82 , -88.792 , -88.764 ], [-100.6516 , -100.3648 , -100.078 , ..., -88.77 , -88.7412 , -88.7124 ], [-100.5972 , -100.3216 , -100.046 , ..., -88.72 , -88.6904 , -88.6608 ]], [[-161.11 , -161.11 , -158.41 , ..., -187.276 , -187.276 , -187.276 ], [-161.11 , -161.11 , -158.41 , ..., -187.276 , -187.276 , -187.276 ], [-159.45 , -159.45 , -156.73 , ..., -186.67 , -186.67 , -186.67 ], ..., [-175.28 , -175.28 , -173.5 , ..., -166.763 , -166.763 , -166.763 ], [-175.28 , -175.28 , -173.5 , ..., -166.763 , -166.763 , -166.763 ], [-175.28 , -175.28 , -173.5 , ..., -166.763 , -166.763 , -166.763 ]]], shape=(13, 50, 125), dtype=float32)
PandasIndex
PandasIndex(Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], dtype='int32', name='layer'))
PandasIndex
PandasIndex(Index([563950.0, 563850.0, 563750.0, 563650.0, 563550.0, 563450.0, 563350.0, 563250.0, 563150.0, 563050.0, 562950.0, 562850.0, 562750.0, 562650.0, 562550.0, 562450.0, 562350.0, 562250.0, 562150.0, 562050.0, 561950.0, 561850.0, 561750.0, 561650.0, 561550.0, 561450.0, 561350.0, 561250.0, 561150.0, 561050.0, 560950.0, 560850.0, 560750.0, 560650.0, 560550.0, 560450.0, 560350.0, 560250.0, 560150.0, 560050.0, 559950.0, 559850.0, 559750.0, 559650.0, 559550.0, 559450.0, 559350.0, 559250.0, 559150.0, 559050.0], dtype='float64', name='y'))
PandasIndex
PandasIndex(Index([237550.0, 237650.0, 237750.0, 237850.0, 237950.0, 238050.0, 238150.0, 238250.0, 238350.0, 238450.0, ... 249050.0, 249150.0, 249250.0, 249350.0, 249450.0, 249550.0, 249650.0, 249750.0, 249850.0, 249950.0], dtype='float64', name='x', length=125))
All packages have been regridded, for example the NPF package:
regridded_simulation["GWF"]["npf"]
NodePropertyFlow
<xarray.Dataset> Size: 652kB Dimensions: (layer: 13, y: 50, x: 125) Coordinates: dx float64 8B 100.0 dy float64 8B -100.0 * layer (layer) int32 52B 1 2 3 4 ... 11 12 13 * y (y) float64 400B 5.64e+05 ... 5.59e+05 * x (x) float64 1kB 2.376e+05 ... 2.5e+05 Data variables: (12/22) icelltype int32 4B 0 k (layer, y, x) float32 325kB nan ... ... rewet bool 1B False rewet_layer object 8B None rewet_factor object 8B None rewet_iterations object 8B None ... ... dewatered bool 1B True perched bool 1B True save_specific_discharge bool 1B False save_saturation bool 1B False xt3d_option bool 1B False rhs_option bool 1B False
dx
()
float64
100.0
dy
()
float64
-100.0
layer
(layer)
int32
1 2 3 4 5 6 7 8 9 10 11 12 13
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], dtype=int32)
y
(y)
float64
5.64e+05 5.638e+05 ... 5.59e+05
array([563950., 563850., 563750., 563650., 563550., 563450., 563350., 563250., 563150., 563050., 562950., 562850., 562750., 562650., 562550., 562450., 562350., 562250., 562150., 562050., 561950., 561850., 561750., 561650., 561550., 561450., 561350., 561250., 561150., 561050., 560950., 560850., 560750., 560650., 560550., 560450., 560350., 560250., 560150., 560050., 559950., 559850., 559750., 559650., 559550., 559450., 559350., 559250., 559150., 559050.])
x
(x)
float64
2.376e+05 2.376e+05 ... 2.5e+05
array([237550., 237650., 237750., 237850., 237950., 238050., 238150., 238250., 238350., 238450., 238550., 238650., 238750., 238850., 238950., 239050., 239150., 239250., 239350., 239450., 239550., 239650., 239750., 239850., 239950., 240050., 240150., 240250., 240350., 240450., 240550., 240650., 240750., 240850., 240950., 241050., 241150., 241250., 241350., 241450., 241550., 241650., 241750., 241850., 241950., 242050., 242150., 242250., 242350., 242450., 242550., 242650., 242750., 242850., 242950., 243050., 243150., 243250., 243350., 243450., 243550., 243650., 243750., 243850., 243950., 244050., 244150., 244250., 244350., 244450., 244550., 244650., 244750., 244850., 244950., 245050., 245150., 245250., 245350., 245450., 245550., 245650., 245750., 245850., 245950., 246050., 246150., 246250., 246350., 246450., 246550., 246650., 246750., 246850., 246950., 247050., 247150., 247250., 247350., 247450., 247550., 247650., 247750., 247850., 247950., 248050., 248150., 248250., 248350., 248450., 248550., 248650., 248750., 248850., 248950., 249050., 249150., 249250., 249350., 249450., 249550., 249650., 249750., 249850., 249950.])
icelltype
()
int32
0
k
(layer, y, x)
float32
nan nan nan nan ... 4.38 4.651 6.06
array([[[ nan, nan, nan, ..., 1.71045101e+00, 2.06758380e+00, 2.13754582e+00], [ nan, nan, nan, ..., 2.57982802e+00, 2.92900181e+00, 2.97071409e+00], [ nan, nan, nan, ..., 3.26586366e+00, 3.61737657e+00, 4.02017498e+00], ..., [6.52613735e+00, 7.31937456e+00, 8.07691193e+00, ..., nan, nan, nan], [6.75934601e+00, 7.43262911e+00, 7.75328350e+00, ..., nan, nan, nan], [6.89848566e+00, 7.72873783e+00, 7.24491787e+00, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], ... nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]], [[3.50853882e+01, 3.35398254e+01, 3.31028404e+01, ..., 1.11550407e+01, 1.10419674e+01, 1.10544491e+01], [3.57339859e+01, 3.40993958e+01, 3.36731339e+01, ..., 1.07958746e+01, 1.06821775e+01, 1.07412310e+01], [3.71318932e+01, 3.54708900e+01, 3.50784569e+01, ..., 1.06320744e+01, 1.04805851e+01, 1.05435915e+01], ..., [5.03838577e+01, 5.14991608e+01, 5.39692154e+01, ..., 4.94934893e+00, 7.53968716e+00, 1.01326780e+01], [5.07901382e+01, 5.20933380e+01, 5.46933594e+01, ..., 4.54834080e+00, 6.02678776e+00, 8.55815029e+00], [5.12099190e+01, 5.24668083e+01, 5.51531830e+01, ..., 4.37981462e+00, 4.65149546e+00, 6.05957603e+00]]], shape=(13, 50, 125), dtype=float32)
rewet
()
bool
False
rewet_layer
()
object
None
array(None, dtype=object)
rewet_factor
()
object
None
array(None, dtype=object)
rewet_iterations
()
object
None
array(None, dtype=object)
rewet_method
()
object
None
array(None, dtype=object)
k22
()
object
None
array(None, dtype=object)
k33
(layer, y, x)
float32
nan nan nan ... 4.379 4.635 5.987
array([[[ nan, nan, nan, ..., 1.68908155e+00, 2.05299568e+00, 2.07375240e+00], [ nan, nan, nan, ..., 2.56002688e+00, 2.90870237e+00, 2.93282318e+00], [ nan, nan, nan, ..., 3.25846219e+00, 3.60833979e+00, 3.96773362e+00], ..., [6.52359343e+00, 7.31123686e+00, 8.06107712e+00, ..., nan, nan, nan], [6.75605583e+00, 7.42485857e+00, 7.72925758e+00, ..., nan, nan, nan], [6.89221048e+00, 7.72043324e+00, 7.19585562e+00, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], ... nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]], [[3.50840683e+01, 3.35387764e+01, 3.31001320e+01, ..., 1.11541767e+01, 1.10412979e+01, 1.10539465e+01], [3.57323608e+01, 3.40979767e+01, 3.36704140e+01, ..., 1.07952986e+01, 1.06817684e+01, 1.07408428e+01], [3.71310349e+01, 3.54699516e+01, 3.50761642e+01, ..., 1.06316519e+01, 1.04804630e+01, 1.05433397e+01], ..., [5.03830185e+01, 5.14964905e+01, 5.39657822e+01, ..., 4.91560221e+00, 7.46072292e+00, 1.01161366e+01], [5.07891464e+01, 5.20898857e+01, 5.46896210e+01, ..., 4.54136038e+00, 5.96547222e+00, 8.49976540e+00], [5.12087021e+01, 5.24633751e+01, 5.51496162e+01, ..., 4.37948227e+00, 4.63479853e+00, 5.98664236e+00]]], shape=(13, 50, 125), dtype=float32)
angle1
()
object
None
array(None, dtype=object)
angle2
()
object
None
array(None, dtype=object)
angle3
()
object
None
array(None, dtype=object)
alternative_cell_averaging
()
object
None
array(None, dtype=object)
save_flows
()
bool
True
starting_head_as_confined_thickness
()
bool
False
variable_vertical_conductance
()
bool
True
dewatered
()
bool
True
perched
()
bool
True
save_specific_discharge
()
bool
False
save_saturation
()
bool
False
xt3d_option
()
bool
False
rhs_option
()
bool
False
PandasIndex
PandasIndex(Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], dtype='int32', name='layer'))
PandasIndex
PandasIndex(Index([563950.0, 563850.0, 563750.0, 563650.0, 563550.0, 563450.0, 563350.0, 563250.0, 563150.0, 563050.0, 562950.0, 562850.0, 562750.0, 562650.0, 562550.0, 562450.0, 562350.0, 562250.0, 562150.0, 562050.0, 561950.0, 561850.0, 561750.0, 561650.0, 561550.0, 561450.0, 561350.0, 561250.0, 561150.0, 561050.0, 560950.0, 560850.0, 560750.0, 560650.0, 560550.0, 560450.0, 560350.0, 560250.0, 560150.0, 560050.0, 559950.0, 559850.0, 559750.0, 559650.0, 559550.0, 559450.0, 559350.0, 559250.0, 559150.0, 559050.0], dtype='float64', name='y'))
PandasIndex
PandasIndex(Index([237550.0, 237650.0, 237750.0, 237850.0, 237950.0, 238050.0, 238150.0, 238250.0, 238350.0, 238450.0, ... 249050.0, 249150.0, 249250.0, 249350.0, 249450.0, 249550.0, 249650.0, 249750.0, 249850.0, 249950.0], dtype='float64', name='x', length=125))
Let’s make a comparison plot of the hydraulic conductivities:
import matplotlib.pyplot as plt import numpy as np fig, axes = plt.subplots(nrows=2, sharex=True) plot_kwargs = {"colors": "viridis", "levels": np.linspace(0.0, 100.0, 21), "fig": fig} imod.visualize.spatial.plot_map( original_simulation["GWF"]["npf"]["k"].sel(layer=3), ax=axes[0], **plot_kwargs ) imod.visualize.spatial.plot_map( regridded_simulation["GWF"]["npf"]["k"].sel(layer=3), ax=axes[1], **plot_kwargs ) axes[0].set_ylabel("original") axes[1].set_ylabel("regridded")
Text(28.472222222222243, 0.5, 'regridded')
Set up the input needed for custom regridding. Create a regridder weight-cache. This object can (and should) be reused for all the packages that undergo custom regridding at this stage.
from imod.util.regrid import RegridderWeightsCache regrid_cache = RegridderWeightsCache() regrid_cache
<imod.util.regrid.RegridderWeightsCache object at 0x0000016F386DB350>
Regrid the recharge package with a custom regridder. In this case we opt for the centroid locator regridder. This regridder is similar to using a “nearest neighbour” lookup.
from imod.common.utilities.regrid import RegridderType from imod.mf6.regrid import RechargeRegridMethod regridder_types = RechargeRegridMethod(rate=(RegridderType.CENTROIDLOCATOR,)) regridded_recharge = original_rch_package.regrid_like( target_grid, regrid_cache=regrid_cache, regridder_types=regridder_types, ) regridded_recharge
Recharge
<xarray.Dataset> Size: 1MB Dimensions: (layer: 13, time: 2, y: 50, x: 125) Coordinates: dx float64 8B 100.0 dy float64 8B -100.0 * layer (layer) int32 52B 1 2 3 4 5 6 7 8 9 10 11 12 13 * time (time) datetime64[ns] 16B 2009-12-30T23:59:59 2009-12-31 * y (y) float64 400B 5.64e+05 5.638e+05 ... 5.592e+05 5.59e+05 * x (x) float64 1kB 2.376e+05 2.376e+05 ... 2.498e+05 2.5e+05 Data variables: rate (time, layer, y, x) float64 1MB nan nan nan ... nan nan nan print_input bool 1B False print_flows bool 1B False save_flows bool 1B False observations object 8B None repeat_stress object 8B None fixed_cell bool 1B False
dx
()
float64
100.0
dy
()
float64
-100.0
layer
(layer)
int32
1 2 3 4 5 6 7 8 9 10 11 12 13
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], dtype=int32)
time
(time)
datetime64[ns]
2009-12-30T23:59:59 2009-12-31
array(['2009-12-30T23:59:59.000000000', '2009-12-31T00:00:00.000000000'], dtype='datetime64[ns]')
y
(y)
float64
5.64e+05 5.638e+05 ... 5.59e+05
array([563950., 563850., 563750., 563650., 563550., 563450., 563350., 563250., 563150., 563050., 562950., 562850., 562750., 562650., 562550., 562450., 562350., 562250., 562150., 562050., 561950., 561850., 561750., 561650., 561550., 561450., 561350., 561250., 561150., 561050., 560950., 560850., 560750., 560650., 560550., 560450., 560350., 560250., 560150., 560050., 559950., 559850., 559750., 559650., 559550., 559450., 559350., 559250., 559150., 559050.])
x
(x)
float64
2.376e+05 2.376e+05 ... 2.5e+05
array([237550., 237650., 237750., 237850., 237950., 238050., 238150., 238250., 238350., 238450., 238550., 238650., 238750., 238850., 238950., 239050., 239150., 239250., 239350., 239450., 239550., 239650., 239750., 239850., 239950., 240050., 240150., 240250., 240350., 240450., 240550., 240650., 240750., 240850., 240950., 241050., 241150., 241250., 241350., 241450., 241550., 241650., 241750., 241850., 241950., 242050., 242150., 242250., 242350., 242450., 242550., 242650., 242750., 242850., 242950., 243050., 243150., 243250., 243350., 243450., 243550., 243650., 243750., 243850., 243950., 244050., 244150., 244250., 244350., 244450., 244550., 244650., 244750., 244850., 244950., 245050., 245150., 245250., 245350., 245450., 245550., 245650., 245750., 245850., 245950., 246050., 246150., 246250., 246350., 246450., 246550., 246650., 246750., 246850., 246950., 247050., 247150., 247250., 247350., 247450., 247550., 247650., 247750., 247850., 247950., 248050., 248150., 248250., 248350., 248450., 248550., 248650., 248750., 248850., 248950., 249050., 249150., 249250., 249350., 249450., 249550., 249650., 249750., 249850., 249950.])
rate
(time, layer, y, x)
float64
nan nan nan nan ... nan nan nan nan
array([[[[ nan, nan, nan, ..., 0.00083373, 0.00083373, 0.00083373], [ nan, nan, nan, ..., 0.00083373, 0.00083373, 0.00083373], [ nan, nan, nan, ..., 0.00083373, 0.00083373, 0.00083373], ..., [0.00091826, 0.00091826, 0.00091826, ..., nan, nan, nan], [0.00091826, 0.00091826, 0.00091826, ..., nan, nan, nan], [0.00091826, 0.00091826, 0.00091826, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], ... [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], ..., [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]]]], shape=(2, 13, 50, 125))
print_input
()
bool
False
print_flows
()
bool
False
save_flows
()
bool
False
observations
()
object
None
array(None, dtype=object)
repeat_stress
()
object
None
array(None, dtype=object)
fixed_cell
()
bool
False
PandasIndex
PandasIndex(Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], dtype='int32', name='layer'))
PandasIndex
PandasIndex(DatetimeIndex(['2009-12-30 23:59:59', '2009-12-31 00:00:00'], dtype='datetime64[ns]', name='time', freq=None))
PandasIndex
PandasIndex(Index([563950.0, 563850.0, 563750.0, 563650.0, 563550.0, 563450.0, 563350.0, 563250.0, 563150.0, 563050.0, 562950.0, 562850.0, 562750.0, 562650.0, 562550.0, 562450.0, 562350.0, 562250.0, 562150.0, 562050.0, 561950.0, 561850.0, 561750.0, 561650.0, 561550.0, 561450.0, 561350.0, 561250.0, 561150.0, 561050.0, 560950.0, 560850.0, 560750.0, 560650.0, 560550.0, 560450.0, 560350.0, 560250.0, 560150.0, 560050.0, 559950.0, 559850.0, 559750.0, 559650.0, 559550.0, 559450.0, 559350.0, 559250.0, 559150.0, 559050.0], dtype='float64', name='y'))
PandasIndex
PandasIndex(Index([237550.0, 237650.0, 237750.0, 237850.0, 237950.0, 238050.0, 238150.0, 238250.0, 238350.0, 238450.0, ... 249050.0, 249150.0, 249250.0, 249350.0, 249450.0, 249550.0, 249650.0, 249750.0, 249850.0, 249950.0], dtype='float64', name='x', length=125))
Next, add the recharge package to the regridded simulation
regridded_simulation["GWF"]["rch"] = regridded_recharge # We can also reattach the original again original_simulation["GWF"]["rch"] = original_rch_packageComparison with histograms#
In the next segment we will compare the input of the models on different grids. We advice to always check how your input is regridded. In this example we upscaled grid, many input parameters are regridded with a mean
method. This means that their input range is reduced, which can be seen in tailings in the histograms becoming shorter
def plot_histograms_side_by_side(array_original, array_regridded, title): """This function creates a plot of normalized histograms of the 2 input DataArray. It plots a title above each histogram.""" _, (ax0, ax1) = plt.subplots(1, 2, sharex=True, sharey=True, tight_layout=True) array_original.plot.hist(ax=ax0, bins=25, density=True) array_regridded.plot.hist(ax=ax1, bins=25, density=True) ax0.title.set_text(f"{title} (original)") ax1.title.set_text(f"{title} (regridded)")
Compare constant head arrays.
plot_histograms_side_by_side( original_simulation["GWF"]["chd"]["head"], regridded_simulation["GWF"]["chd"]["head"], "chd head", )
Compare horizontal hydraulic conductivities.
plot_histograms_side_by_side( original_simulation["GWF"]["npf"]["k"], regridded_simulation["GWF"]["npf"]["k"], "npf k", )
Compare vertical hydraulic conductivities.
plot_histograms_side_by_side( original_simulation["GWF"]["npf"]["k33"], regridded_simulation["GWF"]["npf"]["k33"], "npf k33", )
Compare starting heads.
plot_histograms_side_by_side( original_simulation["GWF"]["ic"]["start"], regridded_simulation["GWF"]["ic"]["start"], "ic start", )
Compare river stages.
plot_histograms_side_by_side( original_simulation["GWF"]["riv"]["stage"], regridded_simulation["GWF"]["riv"]["stage"], "riv stage", )
Compare river bottom elevations.
plot_histograms_side_by_side( original_simulation["GWF"]["riv"]["bottom_elevation"], regridded_simulation["GWF"]["riv"]["bottom_elevation"], "riv bottom elevation", )
Compare riverbed conductance.
plot_histograms_side_by_side( original_simulation["GWF"]["riv"]["conductance"], regridded_simulation["GWF"]["riv"]["conductance"], "riv conductance", )
Compare recharge rates.
plot_histograms_side_by_side( original_simulation["GWF"]["rch"]["rate"], regridded_simulation["GWF"]["rch"]["rate"], "rch rate", )
Compare drainage elevations.
plot_histograms_side_by_side( original_simulation["GWF"]["drn-pipe"]["elevation"], regridded_simulation["GWF"]["drn-pipe"]["elevation"], "drn-pipe elevation", )
Compare drain conductances.
plot_histograms_side_by_side( original_simulation["GWF"]["drn-pipe"]["conductance"], regridded_simulation["GWF"]["drn-pipe"]["conductance"], "drn-pipe conductance", )
Let’s compare outputs now.
# Write simulation original_simulation.write(tmpdir / "original") # Run and open heads original_simulation.run() hds_original = original_simulation.open_head() hds_original
<xarray.DataArray 'head' (time: 2, layer: 13, y: 200, x: 500)> Size: 21MB dask.array<stack, shape=(2, 13, 200, 500), dtype=float64, chunksize=(1, 13, 200, 500), chunktype=numpy.ndarray> Coordinates: * x (x) float64 4kB 2.375e+05 2.375e+05 2.376e+05 ... 2.5e+05 2.5e+05 * y (y) float64 2kB 5.64e+05 5.64e+05 5.639e+05 ... 5.59e+05 5.59e+05 dx float64 8B 25.0 dy float64 8B -25.0 * layer (layer) int64 104B 1 2 3 4 5 6 7 8 9 10 11 12 13 * time (time) float64 16B 1.157e-05 365.0
dask.array<chunksize=(1, 13, 200, 500), meta=np.ndarray>
Array Chunk Bytes 19.84 MiB 9.92 MiB Shape (2, 13, 200, 500) (1, 13, 200, 500) Dask graph 2 chunks in 5 graph layers Data type float64 numpy.ndarray 2 1 500 200 13x
(x)
float64
2.375e+05 2.375e+05 ... 2.5e+05
array([237512.5, 237537.5, 237562.5, ..., 249937.5, 249962.5, 249987.5], shape=(500,))
y
(y)
float64
5.64e+05 5.64e+05 ... 5.59e+05
array([563987.5, 563962.5, 563937.5, 563912.5, 563887.5, 563862.5, 563837.5, 563812.5, 563787.5, 563762.5, 563737.5, 563712.5, 563687.5, 563662.5, 563637.5, 563612.5, 563587.5, 563562.5, 563537.5, 563512.5, 563487.5, 563462.5, 563437.5, 563412.5, 563387.5, 563362.5, 563337.5, 563312.5, 563287.5, 563262.5, 563237.5, 563212.5, 563187.5, 563162.5, 563137.5, 563112.5, 563087.5, 563062.5, 563037.5, 563012.5, 562987.5, 562962.5, 562937.5, 562912.5, 562887.5, 562862.5, 562837.5, 562812.5, 562787.5, 562762.5, 562737.5, 562712.5, 562687.5, 562662.5, 562637.5, 562612.5, 562587.5, 562562.5, 562537.5, 562512.5, 562487.5, 562462.5, 562437.5, 562412.5, 562387.5, 562362.5, 562337.5, 562312.5, 562287.5, 562262.5, 562237.5, 562212.5, 562187.5, 562162.5, 562137.5, 562112.5, 562087.5, 562062.5, 562037.5, 562012.5, 561987.5, 561962.5, 561937.5, 561912.5, 561887.5, 561862.5, 561837.5, 561812.5, 561787.5, 561762.5, 561737.5, 561712.5, 561687.5, 561662.5, 561637.5, 561612.5, 561587.5, 561562.5, 561537.5, 561512.5, 561487.5, 561462.5, 561437.5, 561412.5, 561387.5, 561362.5, 561337.5, 561312.5, 561287.5, 561262.5, 561237.5, 561212.5, 561187.5, 561162.5, 561137.5, 561112.5, 561087.5, 561062.5, 561037.5, 561012.5, 560987.5, 560962.5, 560937.5, 560912.5, 560887.5, 560862.5, 560837.5, 560812.5, 560787.5, 560762.5, 560737.5, 560712.5, 560687.5, 560662.5, 560637.5, 560612.5, 560587.5, 560562.5, 560537.5, 560512.5, 560487.5, 560462.5, 560437.5, 560412.5, 560387.5, 560362.5, 560337.5, 560312.5, 560287.5, 560262.5, 560237.5, 560212.5, 560187.5, 560162.5, 560137.5, 560112.5, 560087.5, 560062.5, 560037.5, 560012.5, 559987.5, 559962.5, 559937.5, 559912.5, 559887.5, 559862.5, 559837.5, 559812.5, 559787.5, 559762.5, 559737.5, 559712.5, 559687.5, 559662.5, 559637.5, 559612.5, 559587.5, 559562.5, 559537.5, 559512.5, 559487.5, 559462.5, 559437.5, 559412.5, 559387.5, 559362.5, 559337.5, 559312.5, 559287.5, 559262.5, 559237.5, 559212.5, 559187.5, 559162.5, 559137.5, 559112.5, 559087.5, 559062.5, 559037.5, 559012.5])
dx
()
float64
25.0
dy
()
float64
-25.0
layer
(layer)
int64
1 2 3 4 5 6 7 8 9 10 11 12 13
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13])
time
(time)
float64
1.157e-05 365.0
array([1.157407e-05, 3.650000e+02])
PandasIndex
PandasIndex(Index([237512.5, 237537.5, 237562.5, 237587.5, 237612.5, 237637.5, 237662.5, 237687.5, 237712.5, 237737.5, ... 249762.5, 249787.5, 249812.5, 249837.5, 249862.5, 249887.5, 249912.5, 249937.5, 249962.5, 249987.5], dtype='float64', name='x', length=500))
PandasIndex
PandasIndex(Index([563987.5, 563962.5, 563937.5, 563912.5, 563887.5, 563862.5, 563837.5, 563812.5, 563787.5, 563762.5, ... 559237.5, 559212.5, 559187.5, 559162.5, 559137.5, 559112.5, 559087.5, 559062.5, 559037.5, 559012.5], dtype='float64', name='y', length=200))
PandasIndex
PandasIndex(Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], dtype='int64', name='layer'))
PandasIndex
PandasIndex(Index([1.1574074074074073e-05, 365.00001157407405], dtype='float64', name='time'))
regridded_simulation.write(tmpdir / "regridded", validate=False) regridded_simulation.run() hds_regridded = regridded_simulation.open_head() hds_regridded
<xarray.DataArray 'head' (time: 2, layer: 13, y: 50, x: 125)> Size: 1MB dask.array<stack, shape=(2, 13, 50, 125), dtype=float64, chunksize=(1, 13, 50, 125), chunktype=numpy.ndarray> Coordinates: * x (x) float64 1kB 2.376e+05 2.376e+05 2.378e+05 ... 2.498e+05 2.5e+05 * y (y) float64 400B 5.64e+05 5.638e+05 ... 5.592e+05 5.59e+05 dx float64 8B 100.0 dy float64 8B -100.0 * layer (layer) int64 104B 1 2 3 4 5 6 7 8 9 10 11 12 13 * time (time) float64 16B 1.157e-05 365.0
dask.array<chunksize=(1, 13, 50, 125), meta=np.ndarray>
Array Chunk Bytes 1.24 MiB 634.77 kiB Shape (2, 13, 50, 125) (1, 13, 50, 125) Dask graph 2 chunks in 5 graph layers Data type float64 numpy.ndarray 2 1 125 50 13x
(x)
float64
2.376e+05 2.376e+05 ... 2.5e+05
array([237550., 237650., 237750., 237850., 237950., 238050., 238150., 238250., 238350., 238450., 238550., 238650., 238750., 238850., 238950., 239050., 239150., 239250., 239350., 239450., 239550., 239650., 239750., 239850., 239950., 240050., 240150., 240250., 240350., 240450., 240550., 240650., 240750., 240850., 240950., 241050., 241150., 241250., 241350., 241450., 241550., 241650., 241750., 241850., 241950., 242050., 242150., 242250., 242350., 242450., 242550., 242650., 242750., 242850., 242950., 243050., 243150., 243250., 243350., 243450., 243550., 243650., 243750., 243850., 243950., 244050., 244150., 244250., 244350., 244450., 244550., 244650., 244750., 244850., 244950., 245050., 245150., 245250., 245350., 245450., 245550., 245650., 245750., 245850., 245950., 246050., 246150., 246250., 246350., 246450., 246550., 246650., 246750., 246850., 246950., 247050., 247150., 247250., 247350., 247450., 247550., 247650., 247750., 247850., 247950., 248050., 248150., 248250., 248350., 248450., 248550., 248650., 248750., 248850., 248950., 249050., 249150., 249250., 249350., 249450., 249550., 249650., 249750., 249850., 249950.])
y
(y)
float64
5.64e+05 5.638e+05 ... 5.59e+05
array([563950., 563850., 563750., 563650., 563550., 563450., 563350., 563250., 563150., 563050., 562950., 562850., 562750., 562650., 562550., 562450., 562350., 562250., 562150., 562050., 561950., 561850., 561750., 561650., 561550., 561450., 561350., 561250., 561150., 561050., 560950., 560850., 560750., 560650., 560550., 560450., 560350., 560250., 560150., 560050., 559950., 559850., 559750., 559650., 559550., 559450., 559350., 559250., 559150., 559050.])
dx
()
float64
100.0
dy
()
float64
-100.0
layer
(layer)
int64
1 2 3 4 5 6 7 8 9 10 11 12 13
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13])
time
(time)
float64
1.157e-05 365.0
array([1.157407e-05, 3.650000e+02])
PandasIndex
PandasIndex(Index([237550.0, 237650.0, 237750.0, 237850.0, 237950.0, 238050.0, 238150.0, 238250.0, 238350.0, 238450.0, ... 249050.0, 249150.0, 249250.0, 249350.0, 249450.0, 249550.0, 249650.0, 249750.0, 249850.0, 249950.0], dtype='float64', name='x', length=125))
PandasIndex
PandasIndex(Index([563950.0, 563850.0, 563750.0, 563650.0, 563550.0, 563450.0, 563350.0, 563250.0, 563150.0, 563050.0, 562950.0, 562850.0, 562750.0, 562650.0, 562550.0, 562450.0, 562350.0, 562250.0, 562150.0, 562050.0, 561950.0, 561850.0, 561750.0, 561650.0, 561550.0, 561450.0, 561350.0, 561250.0, 561150.0, 561050.0, 560950.0, 560850.0, 560750.0, 560650.0, 560550.0, 560450.0, 560350.0, 560250.0, 560150.0, 560050.0, 559950.0, 559850.0, 559750.0, 559650.0, 559550.0, 559450.0, 559350.0, 559250.0, 559150.0, 559050.0], dtype='float64', name='y'))
PandasIndex
PandasIndex(Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], dtype='int64', name='layer'))
PandasIndex
PandasIndex(Index([1.1574074074074073e-05, 365.00001157407405], dtype='float64', name='time'))
Let’s make a comparison plot of the regridded heads.
fig, axes = plt.subplots(nrows=2, sharex=True) plot_kwargs = {"colors": "viridis", "levels": np.linspace(0.0, 11.0, 12), "fig": fig} imod.visualize.spatial.plot_map( hds_original.isel(layer=6, time=-1), ax=axes[0], **plot_kwargs ) imod.visualize.spatial.plot_map( hds_regridded.isel(layer=6, time=-1), ax=axes[1], **plot_kwargs ) axes[0].set_ylabel("original") axes[1].set_ylabel("regridded")
Text(28.472222222222243, 0.5, 'regridded')A note on regridding conductivity#
In the npf package, it is possible to use for definining the conductivity tensor:
1 array (K)
2 arrays (K and K22)
3 arrays (K, K22, K33)
If 1 array is given the tensor is called isotropic. Defining only K gives the same behavior as specifying K, K22 and K33 with the same value. When regridding, K33 has a default method different from that of K and K22, but it can only be applied if K33 exists in the source model in the first place. So it is recommended to introduce K33 as a separate array in the source model even if it is isotropic. Also note that default regridding methods were chosen assuming that K and K22 are roughly horizontal and K33 roughly vertical. But this may not be the case if the input arrays angle2 and/or angle3 have large values.
Regridding boundary conditions#Special care must be taken when regridding boundary conditions, and it is recommended that users verify the balance output of a regridded simulation and compare it to the original model. If the regridded simulation is a good representation of the original simulation, the mass contributions on the balance by the different boundary conditions should be comparable in both simulations. To achieve this, it may be necessary to tweak the input or the regridding methods. An example of this is upscaling recharge (so the target grid has coarser cells than the source grid). Its default method is averaging, with the following rules:
if a cell in the source grid is inactive in the source recharge package (meaning no recharge), it will not count when averaging. So if a target cell has partial overlap with one source recharge cell, and the rest of the target cell has no overlap with any source active recharge cell, it will get the recharge of the one cell it has overlap with. But since the target cell is larger, this effectively means the regridded recharge will be more in the regridded simulation than it was in the source simulation
but we do the same regridding this time assigning a zero recharge to cells without recharge then the averaging will take the zero-recharge cells into account and the regridded recharge will be the same as the source recharge.
Transport simulations can be unstable if constraints related to the grid Peclet number and the courant number are exceeded. This can easily happen when regridding. It may be necessary to reduce the simulation’s time step size especially when downscaling, to prevent numerical issues. Increasing dispersivities or the molecular diffusion constant can also help to stabilize the simulation. Inversely, when upscaling, a larger time step size can be acceptable.
Unsupported packages#Some packages cannot be regridded. This includes the Lake package and the UZF package. Such packages should be removed from the simulation before regridding, and then new packages should be created by the user and then added to the regridded simulation.
This code snippet prints all default methods:
from dataclasses import asdict import pandas as pd from imod.tests.fixtures.package_instance_creation import ALL_PACKAGE_INSTANCES regrid_method_setup = { "package name": [], "array name": [], "method name": [], "function name": [], } regrid_method_table = pd.DataFrame(regrid_method_setup) counter = 0 for pkg in ALL_PACKAGE_INSTANCES: if hasattr(pkg, "_regrid_method"): package_name = type(pkg).__name__ regrid_methods = asdict(pkg.get_regrid_methods()) for array_name in regrid_methods.keys(): method_name = regrid_methods[array_name][0].name function_name = "" if len(regrid_methods[array_name]) > 0: function_name = regrid_methods[array_name][1] regrid_method_table.loc[counter] = ( package_name, array_name, method_name, function_name, ) counter = counter + 1 # Set multi index to group with packages regrid_method_table = regrid_method_table.set_index(["package name", "array name"]) # Pandas by default displays at max 60 rows, which this table exceeds. nrows = regrid_method_table.shape[0] # Configure pandas to increase the max amount of displayable rows. pd.set_option("display.max_rows", nrows + 1) # Display rows: regrid_method_tablemethod name function name package name array name StructuredDiscretization top OVERLAP mean bottom OVERLAP mean idomain OVERLAP mode Dispersion diffusion_coefficient OVERLAP mean longitudinal_horizontal OVERLAP mean transversal_horizontal1 OVERLAP mean longitudinal_vertical OVERLAP mean transversal_horizontal2 OVERLAP mean transversal_vertical OVERLAP mean InitialConditions start OVERLAP mean MobileStorageTransfer porosity OVERLAP mean decay OVERLAP mean decay_sorbed OVERLAP mean bulk_density OVERLAP mean distcoef OVERLAP mean sp2 OVERLAP mean NodePropertyFlow icelltype OVERLAP mode k OVERLAP geometric_mean k22 OVERLAP geometric_mean k33 OVERLAP harmonic_mean angle1 OVERLAP mean angle2 OVERLAP mean angle3 OVERLAP mean rewet_layer OVERLAP mean SpecificStorage convertible OVERLAP mode specific_storage OVERLAP mean specific_yield OVERLAP mean StorageCoefficient convertible OVERLAP mode storage_coefficient OVERLAP mean specific_yield OVERLAP mean ConstantHead head OVERLAP mean concentration OVERLAP mean ibound OVERLAP mode Drainage elevation OVERLAP mean conductance RELATIVEOVERLAP conductance concentration OVERLAP mean Evapotranspiration surface OVERLAP mean rate OVERLAP mean depth OVERLAP mean proportion_rate OVERLAP mean proportion_depth OVERLAP mean GeneralHeadBoundary head OVERLAP mean conductance RELATIVEOVERLAP conductance concentration OVERLAP mean Recharge rate OVERLAP mean concentration OVERLAP mean River stage OVERLAP mean conductance RELATIVEOVERLAP conductance bottom_elevation OVERLAP mean concentration OVERLAP mean infiltration_factor OVERLAP mean VerticesDiscretization top OVERLAP mean bottom OVERLAP mean idomain OVERLAP mode Dispersion diffusion_coefficient OVERLAP mean longitudinal_horizontal OVERLAP mean transversal_horizontal1 OVERLAP mean longitudinal_vertical OVERLAP mean transversal_horizontal2 OVERLAP mean transversal_vertical OVERLAP mean InitialConditions start OVERLAP mean MobileStorageTransfer porosity OVERLAP mean decay OVERLAP mean decay_sorbed OVERLAP mean bulk_density OVERLAP mean distcoef OVERLAP mean sp2 OVERLAP mean NodePropertyFlow icelltype OVERLAP mode k OVERLAP geometric_mean k22 OVERLAP geometric_mean k33 OVERLAP harmonic_mean angle1 OVERLAP mean angle2 OVERLAP mean angle3 OVERLAP mean rewet_layer OVERLAP mean SpecificStorage convertible OVERLAP mode specific_storage OVERLAP mean specific_yield OVERLAP mean StorageCoefficient convertible OVERLAP mode storage_coefficient OVERLAP mean specific_yield OVERLAP mean ConstantHead head OVERLAP mean concentration OVERLAP mean ibound OVERLAP mode Drainage elevation OVERLAP mean conductance RELATIVEOVERLAP conductance concentration OVERLAP mean Evapotranspiration surface OVERLAP mean rate OVERLAP mean depth OVERLAP mean proportion_rate OVERLAP mean proportion_depth OVERLAP mean GeneralHeadBoundary head OVERLAP mean conductance RELATIVEOVERLAP conductance concentration OVERLAP mean Recharge rate OVERLAP mean concentration OVERLAP mean River stage OVERLAP mean conductance RELATIVEOVERLAP conductance bottom_elevation OVERLAP mean concentration OVERLAP mean infiltration_factor OVERLAP mean
Total running time of the script: (1 minutes 36.332 seconds)
Gallery generated by Sphinx-Gallery
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4