Skip to content

Loading and saving a model

In this article we will look at loading and saving a model. First we will load a model, and store it in a new location. Then make adjustments to one of the sub models, and store the model in place. Lastly, we will look at some caveats of saving and loading models.

If you do not have a DIMR model, you can use the example model in the test data.

Load the model

We can load a model by constructing a new DIMR model by calling the DIMR with the file path to this model:

# assuming the DIMR model is stored in your current working directory.
model_path = Path("./dimr_config.xml")
dimr_model = DIMR(filepath=model_path)

It is also possible to not recursively load models:

dimr_model = DIMR(filepath=model_path, recurse=False)

This will only load a DIMR model without its underlying child file models, such as the Flow FM model.

Save the model in a new location

If we want to store the full model in a different location we can use the save function:

# Adjust this new_path to a path convenient for you.
new_path = Path("some/other/path/dimr_config.xml")  
dimr_model.save(filepath=new_path, recurse=True)

By setting recurse to True we will ensure all files (which are supported by HYDROLIB-core) are written to the new location, relative to the file path of the root model. Providing the filepath argument has the same result as first setting the filepath, and then calling save:

new_path = Path("some/other/path/dimr_config.xml")  
dimr_model.filepath = new_path
dimr_model.save(recurse=True)

As such, when calling filepath after save it should be the same as new_path. Once save has been called all files (supported by HYDROLIB-core) should be located in the parent folder.

Adjust the model in a update it on disk

Now that we have written our model in a different location, we can make some adjustments to it. We can retrieve the FM sub model as follows:

fm_component = dimr_model.component[1]  # Index 0 corresponds with the RRComponent.
fm_model = fm_component.model

We can adjust the model, by for example changing some of the properties. For example let's change the MapInterval from 60 to 30:

fm_model.output.mapinterval = 30.0

With that change made we can go ahead and save just this specific sub model, in order to update the values on disk:

fm_model.save()

By default, if no filepath is selected, it will be stored in the current save_location. This should correspond with the place where it was last stored on disk. Furthermore, by default recurse is set to False, as such we will only rewrite the .mdu file.

If we now inspect the .mdu file, we should see that the MapInterval in the output header has been set to 30:

...
[output]
...
MapInterval       = 30.0
...

Loading models on case-sensitive systems

Model files may contain references to other model files of which the casing does not match with the file on disk. On Windows, loading a model with differently cased references will work just fine, since Windows is case-insensitive. However on Linux, the referenced file cannot be found and will raise an error. To aid users in migrating their models, HYDROLIB-core offers a feature to resolve the casing of referenced files and supports three operating systems: Windows, Linux and MacOS.

Consider an MDU model file that references a network file: Network/flowfm_net.nc. The file on disk is actually called network/FlowFM_net.nc.

To load the model and simultaneously repair the file references in the in-memory model:

from hydrolib.core.dflowfm.mdu.models import FMModel
model = FMModel("FlowFM.mdu", resolve_casing=True)

# assert that file reference has been updated from Network/flowfm_net.nc to network/FlowFM_net.nc
assert model.geometry.netfile.filepath == Path("network/FlowFM_net.nc")

The resolve_casing argument is by default False. Using the resolve_casing functionality might heavily influence the performance of model loading depending on the model size, the file tree structure and the operating system.

Saving and loading models between different operating systems

In certain cases, it may be necessary to switch effortlessly between operating systems (OS) using the same model. This allows the model to be loaded seamlessly on both Unix and Windows systems. However, it is important to note that the file paths look different for both OSs. Absolute file paths on Unix have a leading slash, while on Windows systems they start with a drive letter. Additionally, Unix systems don't allow backward slashes, whereas Windows supports both forward and backward slashes in file paths. These unique differences may cause issues when attempting to interpret files references within the model on another OS.

Fortunately, HYDROLIB-core features a functionality that allows the conversion of file paths from one OS path style to another. This resolves the issue and ensures that the model functions seamlessly on both Unix and Windows systems.

Examples

Loading a model with Unix file paths on Windows:

model = FMModel(filepath=Path("p:/model/FlowFM.mdu"), path_style="unix")

Loading a model with Windows file paths on Linux/MacOS:

model = FMModel(filepath=Path("/p/model/FlowFM.mdu"), path_style="windows")

In the two examples mentioned above, the path_style option specifies the path style that is used in the model files to be loaded. This information allows HYDROLIB-core to accurately convert the file paths to match the path style of the running operating system and interpret them correctly.

Saving a model with Unix file paths on Windows:

model.save(filepath=Path("p:/model/FlowFM.mdu"), recurse=True, path_style="unix")

Saving a model with Windows file paths on Linux/MacOS:

model.save(filepath=Path("/p/model/FlowFM.mdu"), recurse=True, path_style="windows")

In the two examples mentioned above, the path_style option specifies the preferred path style of the saved model files. However, if this option is not specified when initializing or saving the model, it will default to the path style of the current operating system.

The path_style option supports these three values: * None (will default to either "windows" or "unix" depending on the running OS) * "windows" * "unix"

Other values are not supported and an error will be raised.

Caveats when saving models

There are some caveats to take into account when saving models.

Filepath changes do not automatically propagate

When changing the filepath property of a parent model, the changes in save_location will not automatically propagate. As such, when saving a child model with a relative path, if the parent model's filepath has been changed, the child model will still be saved at its original save location. In order to update the save location, synchronize_filepaths should be called on the root model.

Synchronizing filepaths is relative to the model it is called upon

synchronize_filepaths will only update the file paths of child models. As such it will not propagate changes mode in a parent model:

dimr_model.filepath = Path("some/other/path/dimr_config.xml")
fm_model.synchronize_filepaths()  # This has no effect.

Because the save_location of the fm_model has not been changed, none of the child models will change either.

Furthermore, extra care needs to be taken when dealing with FM models with the pathsRelativeToParent set to False. This option will make all relative paths of child models relative to the .mdu. If synchronize_filepaths is called on a child model of the fm model, it will instead make all save_locations relative to this child model, which is incorrect.

It is recommended to not use pathsRelativeToParent set to False.

Back to top