Skip to content

Commit 00f01b6

Browse files
author
Joost Delsman
committed
Merge branch '329-imod-visualize-cross_section-does-not-support-quasi-3d-layering' of https://gitlab.com/deltares/imod/imod-python into 329-imod-visualize-cross_section-does-not-support-quasi-3d-layering
2 parents 107c942 + ec2440c commit 00f01b6

File tree

143 files changed

+9767
-1128
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

143 files changed

+9767
-1128
lines changed

docs/api/changelog.rst

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,93 @@ All notable changes to this project will be documented in this file.
66
The format is based on `Keep a Changelog`_, and this project adheres to
77
`Semantic Versioning`_.
88

9+
910
[Unreleased]
1011
------------
1112

1213
Fixed
1314
~~~~~
1415

16+
- :meth:`imod.mf6.Simulation._validate` now print all validation errors for all
17+
models and packages in one message.
18+
19+
20+
[0.13.1] - 2023-05-05
21+
---------------------
22+
23+
Added
24+
~~~~~
25+
26+
- :class:`imod.mf6.SpecificStorage` and :class:`imod.mf6.StorageCoefficient`
27+
now have a ``save_flow`` argument.
28+
29+
Fixed
30+
~~~~~
31+
32+
- :func:`imod.mf6.open_cbc` can now read storage fluxes without error.
33+
34+
35+
[0.13.0] - 2023-05-02
36+
---------------------
37+
38+
Added
39+
~~~~~
40+
41+
- :class:`imod.mf6.OutputControl` now takes parameters ``head_file``,
42+
``concentration_file``, and ``budget_file`` to specify where to store
43+
MODFLOW6 output files.
44+
- :func:`imod.util.from_mdal_compliant_ugrid2d` to "restack" the variables that
45+
have have been "unstacked" in :func:`imod.util.mdal_compliant_ugrid2d`.
46+
- Added support for the Modflow6 Lake package
47+
- :func:`imod.select.points_in_bounds`, :func:`imod.select.points_indices`,
48+
:func:`imod.select.points_values` now support unstructured grids.
49+
- Added support for the Modflow 6 Lake package: :class:`imod.mf6.Lake`,
50+
:class:`imod.mf6.LakeData`, :class:`imod.mf6.OutletManning`, :class:`OutletSpecified`,
51+
:class:`OutletWeir`. See the examples for an application of the Lake package.
52+
53+
Fixed
54+
~~~~~
55+
56+
- :meth:`imod.wq.bas.BasicFlow.thickness` returns a DataArray with the correct
57+
dimension order again. This confusingly resulted in an error when writing the
58+
:class:`imod.wq.btn.BasicTransport` package.
59+
- Fixed bug in :class:`imod.mf6.dis.StructuredDiscretization` and
60+
:class:`imod.mf6.dis.VerticesDiscretization` where
61+
``inactive bottom above active cell`` was incorrectly raised.
62+
63+
[0.12.0] - 2023-03-17
64+
---------------------
65+
66+
Added
67+
~~~~~
68+
69+
- :func:`imod.prj.read_projectfile` to read the contents of a project file into
70+
a Python dictionary.
71+
- :func:`imod.prj.open_projectfile_data` to read/open the data that is pointed
72+
to in a project file.
73+
- :func:`imod.gen.read_ascii` to read the geometry stored in ASCII text .gen files.
74+
- :class:`imod.mf6.hfb.HorizontalFlowBarrier` to support Modflow6's HFB
75+
package, works well with `xugrid.snap_to_grid` function.
76+
77+
Fixed
78+
~~~~~
79+
1580
- :func:`imod.evaluate.budget.flow_velocity` now properly computes velocity by
1681
dividing by the porosity. Before, this function computed the Darcian velocity.
1782

83+
Changed
84+
~~~~~~~
85+
86+
- :func:`imod.ipf.save` will error on duplicate IDs for associated files if a
87+
``"layer"`` column is present. As a dataframe is automatically broken down
88+
into a single IPF per layer, associated files for the first layer would be
89+
overwritten by the second, and so forth.
90+
- :meth:`imod.wq.Well.save` will now write time varying data to associated
91+
files for extration rate and concentration.
92+
- Choosing ``method="geometric_mean"`` in the Regridder will now result in NaN
93+
values in the regridded result if a geometric mean is computed over negative
94+
values; in general, a geometric mean should only be computed over physical
95+
quantities with a "true zero" (e.g. conductivity, but not elevation).
1896

1997
[0.11.6] - 2023-02-01
2098
---------------------
@@ -27,7 +105,6 @@ Added
27105
which can be used to provide keyword arguments to the writing of the Modflow 6
28106
Simulation.
29107

30-
31108
Fixed
32109
~~~~~
33110

@@ -42,8 +119,8 @@ Fixed
42119

43120
- :meth:`imod.mf6.Modflow6Simulation.write` with ``binary=False`` no longer
44121
results in invalid MODFLOW6 input for 2D grid data, such as DIS top.
45-
- :meth:`imod.flow.ImodflowModel.write` no longer writes incorrect projectfiles
46-
for non-grid values with a time and layer dimension.
122+
- :meth:`imod.flow.ImodflowModel.write` no longer writes incorrect project
123+
files for non-grid values with a time and layer dimension.
47124
- :func:`imod.evaluate.interpolate_value_boundaries`: Fix edge case when
48125
successive values in z direction are exactly equal to the boundary value.
49126

docs/api/io.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.. currentmodule:: imod
1+
.. currentmodule:: imod.formats
22

33
Input/output
44
------------
@@ -24,3 +24,9 @@ Input/output
2424

2525
gen.read
2626
gen.write
27+
gen.read_ascii
28+
29+
prj.read_projectfile
30+
prj.open_projectfile_data
31+
prj.read_timfile
32+
prj.convert_to_disv

docs/api/mf6.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ Flow Packages
5757
Drainage
5858
Evapotranspiration
5959
GeneralHeadBoundary
60+
HorizontalFlowBarrierHydraulicCharacteristic
61+
HorizontalFlowBarrierMultiplier
62+
HorizontalFlowBarrierResistance
6063
InitialConditions
6164
NodePropertyFlow
6265
Recharge

docs/faq/how-do-i/modification.rst

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,29 @@ Generally, raster data is y-descending, so ``ymax`` comes before ``ymin``:
148148
.. code-block:: python
149149
150150
da_selection = da.sel(x=slice(xmin, xmax), y=slice(ymax, ymin))
151-
151+
152+
Get a single value (e.g. a summary statistic)
153+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
154+
155+
When computing an aggregation such as a mean, xarray will return a single
156+
valued DataArray. To get an ordinary Python scalar (for example a single
157+
integer or float), use ``.item()``:
158+
159+
.. code-block:: python
160+
161+
single_value = da.mean().item()
162+
163+
Increase the extent of a raster
164+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
165+
166+
Use another raster with appropriate extent, and use ``align``:
167+
168+
.. code-block:: python
169+
170+
small_aligned, big_aligned = xr.align(small, big, join="outer")
171+
172+
Make sure the cell size is the same, or the result will be non-equidistant.
173+
152174
Create an empty raster
153175
~~~~~~~~~~~~~~~~~~~~~~
154176

docs/installation.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Spatial operations:
6363
Geospatial libaries (optional):
6464

6565
* `geopandas <https://geopandas.org/en/stable/>`__
66-
* `pygeos <https://pygeos.readthedocs.io/en/stable/>`__
66+
* `shapely <https://shapely.readthedocs.io/en/stable/manual.html>`__
6767
* `pyproj <https://pyproj4.github.io/pyproj/stable/>`__
6868
* `rasterio <https://rasterio.readthedocs.io/en/latest/>`__
6969

examples/metaswap/metaswap_example.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
# Initial conditions
103103
# ``````````````````
104104

105-
gwf_model["ic"] = mf6.InitialConditions(head=0.5)
105+
gwf_model["ic"] = mf6.InitialConditions(start=0.5)
106106

107107
# %%
108108
# Output Control

examples/mf6/Henry.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@
105105
transient=False,
106106
convertible=0,
107107
)
108-
gwf_model["ic"] = imod.mf6.InitialConditions(head=0.0)
108+
gwf_model["ic"] = imod.mf6.InitialConditions(start=0.0)
109109
gwf_model["oc"] = imod.mf6.OutputControl(save_head="last", save_budget="last")
110110

111111
# %%

examples/mf6/circle.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@
114114
gwf_model["chd"] = imod.mf6.ConstantHead(
115115
constant_head, print_input=True, print_flows=True, save_flows=True
116116
)
117-
gwf_model["ic"] = imod.mf6.InitialConditions(head=0.0)
117+
gwf_model["ic"] = imod.mf6.InitialConditions(start=0.0)
118118
gwf_model["npf"] = imod.mf6.NodePropertyFlow(
119119
icelltype=icelltype,
120120
k=k,
@@ -218,7 +218,7 @@
218218

219219
ds = ds.ugrid.assign_edge_coords()
220220
fig, ax = plt.subplots()
221-
head.isel(time=0, layer=0).ugrid.plot(ax=ax)
221+
head.isel(time=0, layer=0).compute().ugrid.plot(ax=ax)
222222
ds.isel(time=0, layer=0).plot.quiver(
223223
x="mesh2d_edge_x", y="mesh2d_edge_y", u="u", v="v", color="white"
224224
)
@@ -227,3 +227,28 @@
227227
# %%
228228
# As would be expected from our model input, we observe circular groundwater
229229
# mounding and increasing flows as we move from the center to the exterior.
230+
231+
# %%
232+
# Slice the model domain
233+
# ----------------------
234+
#
235+
# We may also quickly setup a smaller model. We'll select half of the original
236+
# domain.
237+
238+
half_simulation = simulation.clip_box(x_max=0.0)
239+
240+
# %%
241+
# Let's run the model, read the results, and visualize.
242+
243+
modeldir = imod.util.temporary_directory()
244+
half_simulation.write(modeldir)
245+
half_simulation.run()
246+
head = imod.mf6.out.open_hds(
247+
modeldir / "GWF_1/GWF_1.hds",
248+
modeldir / "GWF_1/disv.disv.grb",
249+
)
250+
251+
fig, ax = plt.subplots()
252+
head.isel(time=0, layer=0).compute().ugrid.plot(ax=ax)
253+
ax.set_aspect(1)
254+
# %%

examples/mf6/circle_transport.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@
152152
print_flows=True,
153153
save_flows=True,
154154
)
155-
gwf_model["ic"] = imod.mf6.InitialConditions(head=0.0)
155+
gwf_model["ic"] = imod.mf6.InitialConditions(start=0.0)
156156
gwf_model["npf"] = imod.mf6.NodePropertyFlow(
157157
icelltype=icelltype,
158158
k=k,

examples/mf6/ex01_twri.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
print_flows=True,
118118
save_flows=True,
119119
)
120-
gwf_model["ic"] = imod.mf6.InitialConditions(head=0.0)
120+
gwf_model["ic"] = imod.mf6.InitialConditions(start=0.0)
121121
gwf_model["npf"] = imod.mf6.NodePropertyFlow(
122122
icelltype=icelltype,
123123
k=k,

examples/mf6/example_1d_transport.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def create_transport_model(flowmodel, speciesname, dispersivity, retardation, de
8080
decay_sorbed=decay,
8181
bulk_density=rhobulk,
8282
distcoef=kd,
83-
decay_order="first",
83+
first_order_decay=True,
8484
sorption=sorption,
8585
)
8686

examples/mf6/hondsrug.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import matplotlib.pyplot as plt
2525
import numpy as np
2626
import pandas as pd
27-
import scipy.ndimage.morphology
27+
import scipy.ndimage
2828
import xarray as xr
2929

3030
import imod
@@ -208,7 +208,7 @@
208208

209209
def outer_edge(da):
210210
data = da.copy()
211-
from_edge = scipy.ndimage.morphology.binary_erosion(data)
211+
from_edge = scipy.ndimage.binary_erosion(data)
212212
is_edge = (data == 1) & (from_edge == 0)
213213
return is_edge.astype(bool)
214214

@@ -226,7 +226,7 @@ def outer_edge(da):
226226
# Using the previously created function and the 2d template,
227227
# the outer edge is defined for this example.
228228

229-
edge = outer_edge(xr.full_like(like_2d.drop("layer"), 1))
229+
edge = outer_edge(xr.full_like(like_2d.drop_vars("layer"), 1))
230230

231231
# %%
232232
# Adding information to the CHD package
@@ -489,15 +489,18 @@ def outer_edge(da):
489489
{"layer": layer},
490490
("layer",),
491491
)
492-
times_sto = [
493-
np.datetime64("2009-12-30T23:59:59.000000000"),
494-
np.datetime64("2009-12-31T00:00:00.000000000"),
495-
np.datetime64("2010-12-31T00:00:00.000000000"),
496-
np.datetime64("2011-12-31T00:00:00.000000000"),
497-
np.datetime64("2012-12-31T00:00:00.000000000"),
498-
np.datetime64("2013-12-31T00:00:00.000000000"),
499-
np.datetime64("2014-12-31T00:00:00.000000000"),
500-
]
492+
times_sto = np.array(
493+
[
494+
"2009-12-30T23:59:59.00",
495+
"2009-12-31T00:00:00.00",
496+
"2010-12-31T00:00:00.00",
497+
"2011-12-31T00:00:00.00",
498+
"2012-12-31T00:00:00.00",
499+
"2013-12-31T00:00:00.00",
500+
"2014-12-31T00:00:00.00",
501+
],
502+
dtype="datetime64[ns]",
503+
)
501504

502505
transient = xr.DataArray(
503506
[False, True, True, True, True, True, True], {"time": times_sto}, ("time",)
@@ -513,7 +516,11 @@ def outer_edge(da):
513516
# specific yield and if the layers are convertible.
514517

515518
gwf_model["sto"] = imod.mf6.SpecificStorage(
516-
specific_storage=ss, specific_yield=sy, transient=transient, convertible=0
519+
specific_storage=ss,
520+
specific_yield=sy,
521+
transient=transient,
522+
convertible=0,
523+
save_flows=True,
517524
)
518525

519526
# %%

0 commit comments

Comments
 (0)