All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.



  • imod.mf6.Modflow6Simulation.write() with binary=False no longer results in invalid MODFLOW6 input for 2D grid data, such as DIS top.

  • imod.flow.ImodflowModel.write() no longer writes incorrect projectfiles for non-grid values with a time and layer dimension.



[0.11.4] - 2022-09-05#


  • imod.mf6.GroundwaterFlowModel.write() will no longer error when a 3D DataArray with a single layer is written. It will now accept both 2D and 3D arrays with a single layer coordinate.

  • Hotfixes for imod.wq.model.SeawatModel.clip(), until this merge request is fulfilled.

  • imod.flow.ImodflowModel.write() will set the timestring in the projectfile to steady-state for BoundaryConditions without a time dimension.

  • Added imod.flow.OutputControl as this was still missing.

  • will no longer error when an associated files with 0 rows is read.

  • imod.evaluate.calculate_gxg() now correctly uses (March 14, March 28, April 14) to calculate GVG rather than (March 28, April 14, April 28).

  • imod.mf6.out.open_cbc() now correctly loads boundary fluxes.

  • imod.prepare.LayerRegridder.regrid() will now correctly skip values if top_source or bottom_source are NaN.

  • imod.gen.write() no longer errors on dataframes with empty columns.


  • Deprecate the current documentation URL: For the coming months, redirection is automatic to:

  • will now store associated files in separate directories named layer1, layer2, etc. The ID in the main IPF file is updated accordingly. Previously, if IDs were shared between different layers, the associated files would be overwritten as the IDs would result in the same file name being used over and over.

  • imod.flow.ImodflowModel.time_discretization(), imod.wq.SeawatModel.time_discretization(), imod.mf6.Simulation.time_discretization(), are renamed to: imod.flow.ImodflowModel.create_time_discretization(), imod.wq.SeawatModel.create_time_discretization(), imod.mf6.Simulation.create_time_discretization(),

  • Moved tests inside imod directory, added an entry point for pytest fixtures. Running the tests now requires an editable install, and also existing installations have to be reinstalled to run the tests.

  • The imod.mf6 model packages now all run type checks on input. This is a breaking change for scripts which provide input with an incorrect dtype.

  • imod.mf6.Solution now requires a model_names argument to specify which models should be solved in a single numerical solution. This is required to simulate groundwater flow and transport as they should be in separate solutions.

  • When writing MODFLOW6 input option blocks, a NaN value is now recognized as an alternative to None (and the entry will not be included in the options block).


  • Added support to write MetaSWAP models, imod.msw.MetaSwapModel.

  • Addes support to write coupled MetaSWAP and Modflow6 simulations, imod.couplers.MetaMod

  • imod.util.replace() has been added to find and replace different values in a DataArray.

  • imod.evaluate.calculate_gxg_points() has been added to compute GXG values for time varying point data (i.e. loaded from IPF and presented as a Pandas dataframe).

  • imod.evaluate.calculate_gxg() will return the number of years used in the GxG calculation as separate variables in the output dataset.

  • imod.visualize.spatial.plot_map() now accepts a fix and ax argument, to enable adding maps to existing axes.

  • imod.flow.ImodflowModel.create_time_discretization(), imod.wq.SeawatModel.create_time_discretization(), imod.mf6.Simulation.create_time_discretization(), now have a documentation section.

  • imod.mf6.GroundwaterTransportModel has been added with associated simple classes to allow creation of solute transport models. Advanced boundary conditions such as LAK or UZF are not yet supported.

  • imod.mf6.Buoyancy has been added to simulate density dependent groundwater flow.

[0.11.1] - 2021-12-23#


  • contextily, geopandas, pyvista, rasterio, and shapely are now fully optional dependencies. Import errors are only raised when accessing functionality that requires their use.

  • Include declxml as imod.declxml (should be internal use only!): declxml is no longer maintained on the official repository: Furthermore, it has no conda feedstock, which makes distribution via conda difficult.

[0.11.0] - 2021-12-21#


  • accepts list of file names.

  • imod.mf6.open_hds() did not read the appropriate bytes from the heads file, apart for the first timestep. It will now read the right records.

  • Use the appropriate array for modflow6 timestep duration: the imod.mf6.GroundwaterFlowModel.write() would write the timesteps multiplier in place of the duration array.

  • imod.mf6.GroundwaterFlowModel.write() will now respect the layer coordinate of DataArrays that had multiple coordinates, but were discontinuous from 1; e.g. layers [1, 3, 5] would’ve been transformed to [1, 2, 3] incorrectly.

  • imod.mf6.Modflow6Simulation.write() will no longer change working directory while writing model input – this could lead to errors when multiple processes are writing models in parallel.

  • imod.prepare.laplace_interpolate() will no longer ZeroDivisionError when given a value for ibound.



  • Documentation overhaul: different theme, add sample data for examples, add Frequently Asked Questions (FAQ) section, restructure API Reference. Examples now ru

  • Datetime columns in IPF associated files (via imod.ipf.write_assoc()) will not be placed within quotes, as this can break certain iMOD batch functions.

  • imod.mf6.Well has been renamed into imod.mf6.WellDisStructured.

  • imod.mf6.GroundwaterFlowModel.write() will now write package names into the simulation namefile.

  • imod.mf6.open_cbc() will now return a dictionary with keys flow-front-face, flow-lower-face, flow-right-face for the face flows, rather than front-face-flow for better consistency.

  • Switched to composition from inheritance for all model packages: all model packages now contain an internal (xarray) Dataset, rather than inheriting from the xarray Dataset.

  • imod.mf6.SpecificStorage or imod.mf6.StorageCoefficient is now mandatory for every MODFLOW6 model to avoid accidental steady-state configuration.


  • Module imod.tec for reading Tecplot files has been removed.

[0.10.1] - 2020-10-19#


  • imod.wq.SeawatModel.write() now generates iMOD-WQ runfiles with more intelligent use of the “macro tokens”. : is used exclusively for ranges; $ is used to signify all layers. (This makes runfiles shorter, speeding up parsing, which takes a significant amount of time in the runfile to namefile conversion of iMOD-WQ.)

  • Datetime formats are inferred based on length of the time string according to %Y%m%d%H%M%S; supported lengths 4 (year only) to 14 (full format string).



  • IO methods for IDF files will now correctly identify double precision IDFs. The correct record length identifier is 2295 rather than 2296 (2296 was a typo in the iMOD manual).

  • imod.wq.SeawatModel.write() will now write the correct path for recharge package concentration given in IDF files. It did not prepend the name of the package correctly (resulting in paths like concentration_l1.idf instead of rch/concentration_l1.idf).

  • will simplify constant cellsize arrays to a scalar value – this greatly speeds up drawing in the iMOD-GUI.

[0.10.0] - 2020-05-23#


  • imod.wq.SeawatModel.write() no longer automatically appends the model name to the directory where the input is written. Instead, it simply writes to the directory as specified.

  • returns a new DataArray rather than mutating the input da.

  • returns a DataArray with an index taken from the data of the first provided dimensions if it is a pandas.Series.

  • imod.wq.SeawatModel.write() now writes a runfile with start_hour and start_minute (this results in output IDFs with datetime format "%Y%m%d%H%M").


  • from_file() constructors have been added to all imod.wq.Package. This allows loading directly package from a netCDF file (or any file supported by xarray.open_dataset), or a path to a Zarr directory with suffix “.zarr” or “.zip”.

  • This can be combined with the cache argument in from_file() to enable caching of answers to avoid repeated computation during imod.wq.SeawatModel.write(); it works by checking whether input and output files have changed.

  • The resultdir_is_workspace argument has been added to imod.wq.SeawatModel.write(). iMOD-wq writes a number of files (e.g. list file) in the directory where the runfile is located. This results in mixing of input and output. By setting it True, all model output is written in the results directory.

  • imod.visualize.imshow_topview() has been added to visualize a complete DataArray with atleast dimensions x and y; it dumps PNGs into a specified directory.

  • Some support for 3D visualization has been added. imod.visualize.grid_3d() and imod.visualize.line_3d() have been added to produce pyvista meshes from xarray.DataArray’s and shapely polygons, respectively. imod.visualize.GridAnimation3D and imod.visualize.StaticGridAnimation3D have been added to setup 3D animations of DataArrays with transient data.

  • Support for out of core computation by imod.prepare.Regridder if source is chunked.

  • now reports the problematic file if reading errors occur.

  • imod.prepare.polygonize() added to polygonize DataArrays to GeoDataFrames.

  • Added more support for multiple species imod-wq models, specifically: scalar concentration for boundary condition packages and well IPFs.


  • imod.prepare.Regridder() detects if the like DataArray is a subset along a dimension, in which case the dimension is not regridded.

  • imod.prepare.Regridder() now slices the source array accurately before regridding, taking cell boundaries into account rather than only cell midpoints.

  • density is no longer an optional argument in imod.wq.GeneralHeadboundary and imod.wq.River. The reason is that iMOD-WQ fully removes (!) these packages if density is not present.

  • and will now also save DataArrays in which a coordinate other than x or y is descending.

  • imod.visualize.plot_map() enforces decreasing y, which ensures maps are not plotted upside down.

  • imod.util.coord_reference() now returns a scalar cellsize if coordinate is equidistant.

  • imod.prepare.Regridder.regrid() returns cellsizes as scalar when coordinates are equidistant.

  • Raise proper ValueError in imod.prepare.Regridder.regrid() consistenly when the number of dimensions to regrid does not match the regridder dimensions.

  • When writing DataArrays that have size 1 in dimension x or y: raise error if cellsize (dx or dy) is not specified; and actually use dy or dx when size is 1.

[0.9.0] - 2020-01-19#


  • IDF files representing data of arbitrary dimensionality can be opened and saved. This enables reading and writing files with more dimensions than just x, y, layer, and time.

  • Added multi-species support for (imod.wq)

  • GDAL rasters representing N-dimensional data can be opened and saved similar to (imod.idf) in (imod.rasterio)

  • Writing GDAL rasters using and (imod.rasterio.write()) auto-detects GDAL driver based on file extension

  • 64-bit IDF files can be opened

  • 64-bit IDF files can be written using and (imod.idf.write()) using keyword dtype=np.float64

  • sel and isel methods to SeawatModel to support taking out a subdomain

  • Docstrings for the Modflow 6 classes in imod.mf6

  • function to get the upper active layer from ibound xr.DataArray



[0.8.0] - 2019-10-14#


  • Laplace grid interpolation imod.prepare.laplace_interpolate()

  • Experimental Modflow 6 structured model write support imod.mf6

  • More supported visualizations imod.visualize

  • More extensive reading and writing of GDAL raster in imod.rasterio


[0.7.1] - 2019-08-07#


  • "multilinear" has been added as a regridding option to imod.prepare.Regridder to do linear interpolation up to three dimensions.

  • Boundary condition packages in imod.wq support a method called add_timemap to do cyclical boundary conditions, such as summer and winter stages.


  • no longer fails on a single IDF when it is a voxel IDF (when it has top and bottom data).

  • imod.prepare.celltable now succesfully does parallel chunkwise operations, rather than raising an error.

  • imod.Regridder’s regrid method now succesfully returns source if all dimensions already have the right cell sizes, rather than raising an error.

  • imod.idf.open_subdomains is much faster now at merging different subdomain IDFs of a parallel modflow simulation.

  • no longer suffers from extremely slow execution when the DataArray to save is chunked (it got extremely slow in some cases).

  • Package checks in imod.wq.SeawatModel succesfully reduces over dimensions.

  • Fix last case in imod.prepare.reproject where it did not allocate a new array yet, but returned like instead of the reprojected result.

[0.7.0] - 2019-07-23#


  • imod.wq module to create iMODFLOW Water Quality models

  • conda-forge recipe to install imod (

  • significantly extended documentation and examples

  • imod.prepare module with many data mangling functions

  • module for extracting data along cross sections or at points

  • imod.visualize module added to visualize results

  • imod.idf.open_subdomains() function to open and merge the IDF results of a parallelized run

  • now infers delimeters for the headers and the body

  • can now deal with heterogeneous delimiters between multiple IPF files, and between the headers and body in a single file


  • Namespaces: lift many functions one level, such that you can use e.g. the function imod.prepare.reproject instead of imod.prepare.reproject.reproject


  • All that was deprecated in v0.6.0


  • imod.seawat_write() is deprecated, use the write method of imod.wq.SeawatModel instead

  • is deprecated, use imod.wq instead

  • is deprecated, use imod.wq instead

[0.6.1] - 2019-04-17#


  • Support nonequidistant models in runfile


  • Time conversion in runfile now also accepts cftime objects

[0.6.0] - 2019-03-15#

The primary change is that a number of functions have been renamed to better communicate what they do.

The load function name was not appropriate for IDFs, since the IDFs are not loaded into memory. Rather, they are opened and the headers are read; the data is only loaded when needed, in accordance with xarray’s design; compare for example xarray.open_dataset. The function has been renamed to open.

Similarly, load for IPFs has been deprecated. now reads both single and multiple IPF files into a single pandas.DataFrame.


  • imod.idf.setnodataheader


  • Opening IDFs with imod.idf.load, use instead

  • Opening a set of IDFs with imod.idf.loadset, use imod.idf.open_dataset instead

  • Reading IPFs with imod.ipf.load, use

  • Reading IDF data into a dask array with imod.idf.dask, use imod.idf._dask instead

  • Reading an iMOD-seawat .tec file, use instead.


  • Use np.datetime64 when dates are within time bounds, use cftime.DatetimeProlepticGregorian when they are not (matches xarray defaults)

  • assert is no longer used to catch faulty input arguments, appropriate exceptions are raised instead


  • sorts both paths and headers consistently so data does not end up mixed up in the DataArray

  • Return an xarray.CFTimeIndex rather than an array of cftime.DatimeProlepticGregorian objects

  • properly forwards nodata argument to write

  • idf.write coerces coordinates to floats before writing

  • Significant performance increase for reading IPF timeseries by specifying the datetime format

  • ipf.write no longer writes ,, for missing data (which iMOD does not accept)

[0.5.0] - 2019-02-26#


  • Reading IDFs with the chunks option


  • Reading IDFs with the memmap option

  • imod.idf.dataarray, use imod.idf.load instead


  • Reading IDFs gives delayed objects, which are only read on demand by dask

  • IDF: instead of res and transform attributes, use dx and dy coordinates (0D or 1D)

  • Use cftime.DatetimeProlepticGregorian to support time instead of np.datetime64, allowing longer timespans

  • Repository moved from to


  • Notebook in examples folder for synthetic model example

  • Support for nonequidistant IDF files, by adding dx and dy coordinates


  • IPF support implicit itype