Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/api/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ Added
- Functionality to dump and load MODFLOW 6 simulations to/from zarr and zipstore
formats. See :meth:`imod.mf6.Modflow6Simulation.dump` and
:meth:`imod.mf6.Modflow6Simulation.from_file` for more information.
- Functionality to dump and load MetaSwap models to/from netcdf
format. See :meth:`imod.msw.MetaSwapModel.dump` and
:meth:`imod.msw.MetaSwapModel.from_file` for more information.

Changed
~~~~~~~
Expand Down
3 changes: 2 additions & 1 deletion docs/api/msw.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Model objects & methods

MetaSwapModel
MetaSwapModel.write
MetaSwapModel.dump
MetaSwapModel.from_imod5_data
MetaSwapModel.regrid_like
MetaSwapModel.clip_box
Expand Down Expand Up @@ -172,4 +173,4 @@ Mappings
CouplerMapping.clip_box
CouplerMapping.from_imod5_data
CouplerMapping.get_regrid_methods
CouplerMapping.write
CouplerMapping.write
85 changes: 85 additions & 0 deletions imod/common/utilities/dump_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import collections
from pathlib import Path
from typing import Any, Optional

import tomli_w

from imod.common.interfaces.imodel import IModel
from imod.common.serializer import EngineType
from imod.logging.logging_decorators import standard_log_decorator
from imod.mf6.validation_settings import ValidationSettings
from imod.schemata import ValidationError


@standard_log_decorator()
def _dump_model(
Comment thread
JoerivanEngelen marked this conversation as resolved.
Outdated
model: IModel,
directory,
modelname,
validate: bool = True,
mdal_compliant: bool = False,
crs: Optional[Any] = None,
engine: EngineType = "netcdf4",
) -> Path:
"""
Dump model to files. Writes a model definition as .TOML file, which
points to data for each package. Each package is stored as a separate
NetCDF. Structured grids are saved as regular NetCDFs, unstructured
grids are saved as UGRID NetCDF. Structured grids are always made GDAL
compliant, unstructured grids can be made MDAL compliant optionally.

Parameters
----------
directory: str or Path
directory to dump simulation into.
modelname: str
modelname, will be used to create a subdirectory.
validate: bool, optional
Whether to validate simulation data. Defaults to True.
mdal_compliant: bool, optional
Convert data with
:func:`imod.prepare.spatial.mdal_compliant_ugrid2d` to MDAL
compliant unstructured grids. Defaults to False.
crs: Any, optional
Anything accepted by rasterio.crs.CRS.from_user_input
Requires ``rioxarray`` installed.
engine : str, optional
File engine used to write packages. Options are ``'netcdf4'``,
``'zarr'``, and ``'zarr.zip'``. NetCDF4 is readable by many other
softwares, for example QGIS. Zarr is optimized for big data, cloud
storage and parallel access. The ``'zarr.zip'`` option is an
experimental option which creates a zipped zarr store in a single
file, which is easier to copy and automatically compresses data as
well. Default is ``'netcdf4'``.

"""
modeldirectory = Path(directory) / modelname
modeldirectory.mkdir(exist_ok=True, parents=True)

# validation currently only supports MF6, but we want to keep the option to turn it on for other
validation_context = ValidationSettings(validate=validate)
if validation_context.validate:
statusinfo = model.validate(modelname, validation_context)
if statusinfo.has_errors():
raise ValidationError(statusinfo.to_string())

toml_content: dict = collections.defaultdict(dict)

for pkgname, pkg in model.items():
pkg_path = pkg.to_file(
modeldirectory,
pkgname,
mdal_compliant=mdal_compliant,
crs=crs,
engine=engine,
)
toml_content[type(pkg).__name__][pkgname] = pkg_path.name

if hasattr(model, "simulation_settings"):
Comment thread
JoerivanEngelen marked this conversation as resolved.
toml_content["simulation_settings"] = model.simulation_settings

toml_path = modeldirectory / f"{modelname}.toml"
with open(toml_path, "wb") as f:
tomli_w.dump(toml_content, f)

return toml_path
11 changes: 11 additions & 0 deletions imod/mf6/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from imod.common.serializer import EngineType
from imod.common.statusinfo import NestedStatusInfo, StatusInfo, StatusInfoBase
from imod.common.utilities.clip import clip_box_dataset
from imod.common.utilities.dump_model import _dump_model
from imod.common.utilities.mask import mask_all_packages
from imod.common.utilities.regrid import _regrid_like
from imod.common.utilities.schemata import (
Expand Down Expand Up @@ -658,6 +659,16 @@ def dump(

toml_content: dict[str, Any] = collections.defaultdict(dict)

_dump_model(
self,
modeldirectory,
modelname,
validate=validate,
mdal_compliant=mdal_compliant,
crs=crs,
engine=engine,
)

for pkgname, pkg in self.items():
pkg_path = pkg.to_file(
modeldirectory,
Expand Down
5 changes: 3 additions & 2 deletions imod/mf6/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from imod.common.serializer import EngineType
from imod.common.statusinfo import NestedStatusInfo
from imod.common.utilities.dataclass_type import DataclassType
from imod.common.utilities.dump_model import _dump_model
from imod.common.utilities.mask import mask_all_models
from imod.common.utilities.partitioninfo import create_partition_info
from imod.common.utilities.regrid import _regrid_like
Expand Down Expand Up @@ -1037,8 +1038,8 @@ def dump(
for key, value in self.items():
cls_name = type(value).__name__
if isinstance(value, Modflow6Model):
model_toml_path = value.dump(
directory, key, validate, mdal_compliant, crs, engine=engine
model_toml_path = _dump_model(
Comment thread
JoerivanEngelen marked this conversation as resolved.
Outdated
value, directory, key, validate, mdal_compliant, crs, engine=engine
)
toml_content[cls_name][key] = model_toml_path.relative_to(
directory
Expand Down
Loading
Loading