Skip to content

Issue #963 dump meta swap model nc#1852

Open
rleander73 wants to merge 10 commits into
masterfrom
Issue_#963_dump_MetaSWAP_model_nc
Open

Issue #963 dump meta swap model nc#1852
rleander73 wants to merge 10 commits into
masterfrom
Issue_#963_dump_MetaSWAP_model_nc

Conversation

@rleander73
Copy link
Copy Markdown

@rleander73 rleander73 commented Jun 4, 2026

Fixes #963

Description

Checklist

  • Links to correct issue
  • Update changelog, if changes affect users
  • PR title starts with Issue #nr, e.g. Issue #737
  • Unit tests were added
  • If feature added: Added/extended example
  • If feature added: Added feature to API documentation
  • If pixi.lock was changed: Ran pixi run generate-sbom and committed changes

Copy link
Copy Markdown
Contributor

@JoerivanEngelen JoerivanEngelen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the changeset is quite complete and the roundtrip tests are good.

I have some comments though:

  1. There is duplicate code in imod.mf6.Model.dump, which is never called now because imod.mf6.Modflow6Simulation doesn't call it anymore... See my detailed comments.

  2. It's very useful you added the iModel interface to MetaSwapModel. You had to add some methods to comply with the iModel interface. Unfortunately the masking methods do not work as some important methods are missing. Implementing that in this PR is out of scope, but could you add a NotImplementedError here? Furthermore could you add unittests for the others that we still think work? If it turns out in the unittests that they do not work, also replace these with a NotImplmentedError. List of methods/properties that still deserve a unittest:

    • _is_splitting_supported
    • _is_regridding_supported
    • _is_clipping_supported
    • model_id
    • options
    • domain

Comment thread imod/common/utilities/dump_model.py Outdated


@standard_log_decorator()
def _dump_model(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great that you are refactoring this to move dumping logic to a utility. Stylewise: could you rename this function to dump_model? The underscore is only used for private methods or private functions WITHIN a module (we have not documented that, so your confusion is very understandable).

)
toml_content[type(pkg).__name__][pkgname] = pkg_path.name

if hasattr(model, "simulation_settings"):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this only necessary for MetaSWAP models, right? If so, please add a comment that this is intended for MSW.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only applies to MetaSWAP models, I would rather do isinstance and ask if model is a MetaSWAP model, but that introduces a cyclic problem, therefore this indirect approach. I added a comment stating that this line is only relevant for MetaSWAP models.

Comment thread imod/mf6/model.py Outdated
Comment on lines 660 to 684
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're dumping twice now, if I'm not mistaken, this should be sufficient now:

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

Comment thread imod/mf6/simulation.py Outdated
if isinstance(value, Modflow6Model):
model_toml_path = value.dump(
directory, key, validate, mdal_compliant, crs, engine=engine
model_toml_path = _dump_model(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is not necessary: calling Modflow6Model.dump (as was done previously) is sufficient here.

Comment thread imod/msw/model.py Outdated
toml_content = tomli.load(f)

parentdir = toml_path.parent
if issubclass(cls, MetaSwapModel):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is never subclassed, so this check is not necessary right?

Comment thread imod/msw/model.py Outdated
Comment on lines +833 to +855
def purge_empty_packages(
self, model_name: Optional[str] = "", ignore_time: bool = False
) -> None:
"""
This method removes empty packages from the model in place.

Parameters
----------
model_name: str, optional
Name of the model, used for logging.
ignore_time: bool, optional
If False, packages are considered empty if they have no data at all
timesteps. If True, packages are considered empty if they have no
data at the first time step. The latter can increase performance
considerably.
"""
empty_packages = [
package_name
for package_name, package in self.items()
if package.is_empty(ignore_time=ignore_time)
]
for package_name in empty_packages:
self.pop(package_name)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the imod.msw.MetaSwapPackage class doesn't have an is_empty method, so this code doesn't work unfortunately. Could you replace this code with a NotImplementedError?

Comment thread imod/msw/model.py Outdated
improve performance when masking models with many time steps.
"""

mask_all_packages(self, mask, ignore_time_purge_empty)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MetaSwap doesn't have masking yet, so could you also change this to a NotImplementedError?

Comment thread imod/msw/pkgbase.py Outdated
Comment on lines +30 to +38
def _is_scalar_nan(da: GridDataArray):
"""
Test if is_scalar_nan, carefully avoid loading grids in memory
"""
scalar_data: bool = is_scalar(da)
if scalar_data:
stripped_value = da.to_numpy()[()]
return isinstance(stripped_value, numbers.Real) and np.isnan(stripped_value) # type: ignore[call-overload]
return False
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is also in imod.mf6.pkgbase.py, could you move this to imod.common.utilities.value_filters?

Comment thread imod/tests/test_mf6/test_mf6_model.py Outdated

def roundtrip(model, tmp_path):
model.dump(tmp_path, "test")
_dump_model(model, tmp_path, "test")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this change is not necessary? See previous comment in imod.mf6.simulation.py

from imod.util.spatial import empty_2d


def roundtrip(msw_model, tmpdir_factory, name, engine):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 4, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add dump method to MetaSWAP model

3 participants