pyDeltaRCM 2.1.10__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pydeltarcm-2.1.10/pyDeltaRCM.egg-info → pydeltarcm-2.2.0}/PKG-INFO +1 -1
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/custom_saving.rst +14 -9
- pydeltarcm-2.2.0/docs/source/examples/gotcha_simulataneous_models.rst +62 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/index.rst +8 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/info/outputfile.rst +20 -14
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM/_version.py +1 -1
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM/hook_tools.py +1 -1
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM/init_tools.py +207 -57
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM/iteration_tools.py +35 -4
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM/model.py +44 -36
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0/pyDeltaRCM.egg-info}/PKG-INFO +1 -1
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM.egg-info/SOURCES.txt +1 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/integration/test_checkpointing.py +321 -255
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/integration/test_consistent_outputs.py +70 -9
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/integration/test_timing_triggers.py +11 -11
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/test_init_tools.py +266 -28
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/test_iteration_tools.py +85 -9
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/LICENSE +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/MANIFEST.in +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/README.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/.nojekyll +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/_resources/checkpoint/checkpoint.npz +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/_resources/checkpoint.yaml +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/_static/style.css +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/_templates/page.html +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/conf.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/basic_runs.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/custom_class_preprocessor.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/custom_yaml.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/modelzoo.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/overwrite_topo_diffusion.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/resume_from_checkpoint.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/simple_example.ipynb +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/slight_slope.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/subsidence_region.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/updating_boundary_conditions.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/variable_bedload.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/examples/variable_velocity.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/guides/10min.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/guides/advanced_configuration_guide.inc +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/guides/developer_guide.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/guides/getting_started.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/guides/subsidence_guide.inc +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/guides/user_guide.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/index.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/info/hydrodynamics.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/info/index.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/info/initialization.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/info/modeltime.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/info/morphodynamics.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/info/yamlparameters.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/meta/citing.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/meta/conduct.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/meta/contributing.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/meta/installing.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/meta/license.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/meta/usedby.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/debug_tools/debug_demo.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/guides/10min_demo.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/guides/cover.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/guides/output_file.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/init_tools/domain_basin_inlet_depth.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/init_tools/domain_inlet_geometry.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/init_tools/domain_parameters.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/init_tools/domain_size_compare.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/modeltime/_base.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/modeltime/four_year_condensed_plot.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/modeltime/four_year_plot.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/modeltime/one_year_plot.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/sed_tools/_initial_bed_state.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/sed_tools/route_all_mud_parcels.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/sed_tools/route_all_sand_parcels.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/sed_tools/sediment_weights_examples.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/sed_tools/topo_diffusion.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/_accumulate_free_surface_walks.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/_check_for_loops.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/_smooth_free_surface.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/compute_free_surface_inputs.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/compute_free_surface_outputs.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/flooding_correction.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/run_water_iteration.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/water_weights_examples.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/reference/debug_tools/index.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/reference/hook_tools/index.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/reference/index.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/reference/init_tools/index.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/reference/iteration_tools/index.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/reference/model/index.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/reference/model/model_hooks.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/reference/model/yaml_defaults.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/reference/preprocessor/index.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/reference/sed_tools/index.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/reference/shared_tools/index.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/docs/source/reference/water_tools/index.rst +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM/__init__.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM/__main__.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM/debug_tools.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM/default.yml +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM/preprocessor.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM/sed_tools.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM/shared_tools.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM/water_tools.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM.egg-info/dependency_links.txt +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM.egg-info/entry_points.txt +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM.egg-info/requires.txt +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyDeltaRCM.egg-info/top_level.txt +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/pyproject.toml +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/setup.cfg +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/__init__.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_list_index.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_list_mix_tuple_index.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_list_tuple.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_multiple_diff_args.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_multiple_diff_kwargs.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_multiple_index_calls.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_no_grid.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_single_index.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_single_tuple.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_velocity.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_withlabel.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_iwalk.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_multiple_subplots.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_show_line_pts_Nx2_array.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_show_line_set_points.png +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/integration/__init__.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/integration/test_cli.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/test_debug_tools.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/test_logging.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/test_model.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/test_preprocessor.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/test_sed_tools.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/test_shared_tools.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/test_water_tools.py +0 -0
- {pydeltarcm-2.1.10 → pydeltarcm-2.2.0}/tests/utilities.py +0 -0
|
@@ -17,11 +17,11 @@ For example, ``self._save_fig_list['active_layer'] = ['active_layer']`` will pro
|
|
|
17
17
|
When adding variables or metadata to be initialized and subsequently saved in the output netCDF, the key-value pair relationship is as follows.
|
|
18
18
|
The key added to ``self._save_var_list`` is the name of the variable as it will be recorded in the netCDF file, this *does not* have to correspond to the name of an attribute in the model.
|
|
19
19
|
To add a variable to the metadata, a key must be added to ``self._save_var_list['meta']``.
|
|
20
|
-
The expected value for a given key is a list containing strings indicating the model attribute to be saved, its units, the variable type, and lastly the variable dimensions (e.g., ``['active_layer', 'fraction', 'f4', ('
|
|
20
|
+
The expected value for a given key is a list containing strings indicating the model attribute to be saved, its units, the variable type, and lastly the variable dimensions (e.g., ``['active_layer', 'fraction', 'f4', ('seconds', 'x', 'y')]`` for the active layer).
|
|
21
21
|
|
|
22
22
|
.. important::
|
|
23
23
|
|
|
24
|
-
The dimensions of the custom variable being specified must match *exactly* with one of the three standard dimensions: `x`, `y`, `
|
|
24
|
+
The dimensions of the custom variable being specified must match *exactly* with one of the three standard dimensions: `x`, `y`, `seconds`.
|
|
25
25
|
Use of an invalid dimension will result in an error.
|
|
26
26
|
|
|
27
27
|
An example of using the hook and creating a model subclass to customize the figures, gridded variables, and metadata being saved is provided below.
|
|
@@ -48,14 +48,19 @@ An example of using the hook and creating a model subclass to customize the figu
|
|
|
48
48
|
... self._save_fig_list['active_layer'] = ['active_layer']
|
|
49
49
|
...
|
|
50
50
|
... # save the active layer grid each save_dt w/ a short name
|
|
51
|
-
... self._save_var_list['actlay'] = [
|
|
52
|
-
...
|
|
53
|
-
...
|
|
51
|
+
... self._save_var_list['actlay'] = [
|
|
52
|
+
... 'active_layer', 'fraction',
|
|
53
|
+
... 'f4', ('seconds', 'x', 'y'),
|
|
54
|
+
... 'channel_bottom__sediment__active_layer'
|
|
55
|
+
... ]
|
|
54
56
|
...
|
|
55
57
|
... # save number of water parcels w/ a long name
|
|
56
|
-
... self._save_var_list['meta']['water_parcels'] = [
|
|
57
|
-
...
|
|
58
|
-
...
|
|
58
|
+
... self._save_var_list['meta']['water_parcels'] = [
|
|
59
|
+
... 'Np_water',
|
|
60
|
+
... 'parcels',
|
|
61
|
+
... 'i8', (),
|
|
62
|
+
... 'model_water__number_parcels'
|
|
63
|
+
... ]
|
|
59
64
|
|
|
60
65
|
Next, we instantiate the model class.
|
|
61
66
|
|
|
@@ -83,4 +88,4 @@ For simplicity we will just check that the appropriate parameters were added to
|
|
|
83
88
|
{'active_layer': ['active_layer']}
|
|
84
89
|
|
|
85
90
|
>>> print(mdl._save_var_list)
|
|
86
|
-
{'meta': {'water_parcels': ['Np_water', 'parcels', 'i8', ()]}, 'actlay': ['active_layer', 'fraction', 'f4', ('
|
|
91
|
+
{'meta': {'water_parcels': ['Np_water', 'parcels', 'i8', (), 'model_water__number_parcels']}, 'actlay': ['active_layer', 'fraction', 'f4', ('seconds', 'x', 'y'), 'channel_bottom__sediment__active_layer']}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Instantiating and running two models iteratively on the same core is not reproducible
|
|
2
|
+
=====================================================================================
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
You cannot run models "simultaneously" and get reproducible results.
|
|
6
|
+
|
|
7
|
+
In an ideal world, two models with same seed should give same result,
|
|
8
|
+
regardless of how they are run. But if two models are called intermittently,
|
|
9
|
+
then the result is not reproducible (at least on a per-model basis) because
|
|
10
|
+
the random-number generator is thrown out of sync with respect to the single
|
|
11
|
+
model and seed. More explanation below.
|
|
12
|
+
|
|
13
|
+
.. note::
|
|
14
|
+
|
|
15
|
+
As of 03/2026, numba does not implement random number generation as an
|
|
16
|
+
object, and so we cannot aviod this "gotcha".
|
|
17
|
+
|
|
18
|
+
.. code::
|
|
19
|
+
|
|
20
|
+
# initialize models
|
|
21
|
+
test1 = DeltaModel()
|
|
22
|
+
test2 = DeltaModel()
|
|
23
|
+
|
|
24
|
+
for _ in range(0, 5):
|
|
25
|
+
test1.update()
|
|
26
|
+
test2.update()
|
|
27
|
+
|
|
28
|
+
test1.finalize()
|
|
29
|
+
test2.finalize()
|
|
30
|
+
|
|
31
|
+
# test that gives same result (WILL FAIL)
|
|
32
|
+
difference = test1.eta - test2.eta
|
|
33
|
+
assert np.all(difference == 0)
|
|
34
|
+
|
|
35
|
+
.. DEVNOTE: see test in tests/integration/test_consistent_outputs.py in TestConsistentOutputsSameSeed called test_same_models_simulataneous_not_parallel
|
|
36
|
+
|
|
37
|
+
**The above code will fail to generate reproducible results.**
|
|
38
|
+
|
|
39
|
+
The problem is that both test and test2 access the same underlying random
|
|
40
|
+
number generator in Numba, and therefore follow different trajectories over
|
|
41
|
+
time. The only way around this is to instantiate the models sequentially
|
|
42
|
+
(resetting the seed via the instantiation of the second one after finishing
|
|
43
|
+
the first one), or instantiating the objects in subprocesses (this is what
|
|
44
|
+
the `preprocessor` does for parallel runs).
|
|
45
|
+
|
|
46
|
+
Of course, if you don't care about reproducibility at the moment (e.g., prototyping, testing approaches, etc), you can totally use the above approach. **Your final model code for analysis should be reproducible and not use this approach!**
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
The below code will work to give reproducible results.
|
|
50
|
+
|
|
51
|
+
.. code::
|
|
52
|
+
|
|
53
|
+
test1 = DeltaModel(input_file=p1)
|
|
54
|
+
for _ in range(0, 5):
|
|
55
|
+
test1.update()
|
|
56
|
+
test1.finalize()
|
|
57
|
+
|
|
58
|
+
test2 = DeltaModel(input_file=p2)
|
|
59
|
+
for _ in range(0, 5):
|
|
60
|
+
test2.update()
|
|
61
|
+
test2.finalize()
|
|
62
|
+
|
|
@@ -10,30 +10,35 @@ Gridded Variables
|
|
|
10
10
|
|
|
11
11
|
In any given run, the saving parameters "save_<var>_grids" control whether or
|
|
12
12
|
not that 2-D grid variable (e.g. velocity) is saved to the netCDF4 file. In
|
|
13
|
-
the netCDF4 file, a 3-D array with the dimensions `
|
|
13
|
+
the netCDF4 file, a 3-D array with the dimensions `seconds` :math:`\times`
|
|
14
14
|
`x` :math:`\times` `y` is created for each 2-D grid variable that is set to
|
|
15
15
|
be saved. Note that `x` is the *downstream* coordinate, rather than the
|
|
16
16
|
Cartesian `x` when displaying the grid. The appropriate units for all
|
|
17
17
|
variables are stored: for example "meters per second" for the *velocity*
|
|
18
|
-
grid.
|
|
18
|
+
grid. All variables include a description via the `long_name` attribute.
|
|
19
19
|
|
|
20
|
-
..
|
|
20
|
+
.. important::
|
|
21
21
|
|
|
22
|
-
The format of the output netCDF file
|
|
23
|
-
old format is documented
|
|
24
|
-
in :attr:`~pyDeltaRCM.model.DeltaModel.legacy_netcdf`, and
|
|
25
|
-
parameter `legacy_netcdf` can be used to create
|
|
26
|
-
the old coordinate configuration.
|
|
22
|
+
The format of the output netCDF file coordinates changed in `v2.2.0`. The
|
|
23
|
+
old format (up to v2.1.9) is documented
|
|
24
|
+
in :attr:`~pyDeltaRCM.model.DeltaModel.legacy_netcdf`, and the input
|
|
25
|
+
parameter `legacy_netcdf` can be used to create an output netcdf file with
|
|
26
|
+
the old coordinate configuration. The output format for pyDeltaRCM v2.1.0
|
|
27
|
+
and earlier is deprecated and has been removed. Changing to the new output
|
|
28
|
+
format should be a small change for most users, with only the name of the
|
|
29
|
+
temporal dimension and the metadata subgroup changing in the new output.
|
|
27
30
|
|
|
28
31
|
|
|
29
32
|
Grid Coordinates
|
|
30
33
|
================
|
|
31
34
|
|
|
32
|
-
Grid coordinates are specified in the variables `
|
|
33
|
-
These arrays are 1D arrays, which specify the location
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
Grid coordinates are specified in the variables `seconds`, `x`, and `y` in the
|
|
36
|
+
output netCDF4 file. These arrays are 1D arrays, which specify the location
|
|
37
|
+
of each cell in the domain in *dimensional* coordinates (e.g., meters). In
|
|
38
|
+
the downstream direction, the distance of each cell from the inlet boundary
|
|
39
|
+
is specified in `x` in meters. Similarly, the cross-domain distance is
|
|
40
|
+
specified in `y` in meters. Lastly, the `seconds` variable is stored as a 1D
|
|
41
|
+
array recording model elapsed time in seconds.
|
|
37
42
|
|
|
38
43
|
|
|
39
44
|
Model Metadata
|
|
@@ -53,6 +58,7 @@ saved as metadata are the following:
|
|
|
53
58
|
- Sediment concentration: `C0_percent`
|
|
54
59
|
- Characteristic Velocity: `u0`
|
|
55
60
|
- If subsidence is enabled:
|
|
61
|
+
|
|
56
62
|
- Subsidence start time: `start_subsidence`
|
|
57
63
|
- Subsidence rate: `sigma`
|
|
58
64
|
|
|
@@ -66,7 +72,7 @@ library. These libraries range from the
|
|
|
66
72
|
to higher-level libraries such as
|
|
67
73
|
`xarray <https://github.com/pydata/xarray>`_. For deltas, and specifically
|
|
68
74
|
*pyDeltaRCM*, there is also a package under development called
|
|
69
|
-
`
|
|
75
|
+
`sandplover <https://github.com/sandpiper-toolchain/sandplover>`_,
|
|
70
76
|
that is being designed to help post-process and analyze *pyDeltaRCM* outputs.
|
|
71
77
|
|
|
72
78
|
|
|
@@ -237,7 +237,7 @@ class hook_tools(abc.ABC):
|
|
|
237
237
|
.. note::
|
|
238
238
|
|
|
239
239
|
For a vector of time-varying metadata, the dimension
|
|
240
|
-
should be specified as ('
|
|
240
|
+
should be specified as ('time').
|
|
241
241
|
|
|
242
242
|
Expected format for time varying grid entries as keys within the
|
|
243
243
|
`self._save_var_list` dictionary:
|
|
@@ -225,9 +225,9 @@ class init_tools(abc.ABC):
|
|
|
225
225
|
self.out_dir = self._input_file_vars["out_dir"]
|
|
226
226
|
self.verbose = self._input_file_vars["verbose"]
|
|
227
227
|
if self._input_file_vars["legacy_netcdf"]:
|
|
228
|
-
self._netcdf_coords = ("total_time", "length", "width")
|
|
229
|
-
else:
|
|
230
228
|
self._netcdf_coords = ("time", "x", "y")
|
|
229
|
+
else:
|
|
230
|
+
self._netcdf_coords = ("seconds", "x", "y")
|
|
231
231
|
|
|
232
232
|
def process_input_to_model(self) -> None:
|
|
233
233
|
"""Process input file to model variables.
|
|
@@ -659,6 +659,22 @@ class init_tools(abc.ABC):
|
|
|
659
659
|
file_path = os.path.join(directory, filename)
|
|
660
660
|
_msg = "Target output NetCDF4 file: {file}".format(file=file_path)
|
|
661
661
|
self.log_info(_msg, verbosity=2)
|
|
662
|
+
if not self._legacy_netcdf:
|
|
663
|
+
_sandsuet_version = "1.0.0"
|
|
664
|
+
_msg = "Output file in sandsuet version {ver} schema".format(
|
|
665
|
+
ver=_sandsuet_version
|
|
666
|
+
)
|
|
667
|
+
else:
|
|
668
|
+
_msg = "Output file in legacy schema"
|
|
669
|
+
warnings.warn(
|
|
670
|
+
"Creating output netcdf file in legacy schema. This format is "
|
|
671
|
+
"provided as a convenience for users who are currently "
|
|
672
|
+
"relying on workflows that use an old format of netcdf file. "
|
|
673
|
+
"It will be removed in the future. Any new workflows should "
|
|
674
|
+
"leverage the sandsuet formatted data specification "
|
|
675
|
+
"(i.e., `legacy_netcdf=False`)."
|
|
676
|
+
)
|
|
677
|
+
self.log_info(_msg, verbosity=1)
|
|
662
678
|
|
|
663
679
|
if (os.path.exists(file_path)) and (self._clobber_netcdf is False):
|
|
664
680
|
raise FileExistsError(
|
|
@@ -678,6 +694,8 @@ class init_tools(abc.ABC):
|
|
|
678
694
|
self.output_netcdf.source = "pyDeltaRCM v{ver}".format(
|
|
679
695
|
ver=self.__pyDeltaRCM_version__
|
|
680
696
|
)
|
|
697
|
+
if not self._legacy_netcdf:
|
|
698
|
+
self.output_netcdf.sandsuet_version = _sandsuet_version
|
|
681
699
|
|
|
682
700
|
# create master dimensions (pulls from `self._netcdf_coords`)
|
|
683
701
|
self.output_netcdf.createDimension(self._netcdf_coords[1], self.L)
|
|
@@ -685,77 +703,158 @@ class init_tools(abc.ABC):
|
|
|
685
703
|
self.output_netcdf.createDimension(self._netcdf_coords[0], None)
|
|
686
704
|
|
|
687
705
|
# create master coordinates (as netCDF variables)
|
|
688
|
-
time = self.output_netcdf.createVariable(
|
|
689
|
-
"time", "f4", (self._netcdf_coords[0],)
|
|
690
|
-
)
|
|
691
|
-
time.units = "second"
|
|
692
|
-
|
|
693
706
|
if self._legacy_netcdf:
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
"x", "f4", self._netcdf_coords[1:]
|
|
707
|
+
time = self.output_netcdf.createVariable(
|
|
708
|
+
"time", "f4", (self._netcdf_coords[0],)
|
|
697
709
|
)
|
|
698
|
-
y = self.output_netcdf.createVariable(
|
|
699
|
-
"y", "f4", self._netcdf_coords[1:]
|
|
700
|
-
)
|
|
701
|
-
x[:] = self.x
|
|
702
|
-
y[:] = self.y
|
|
703
710
|
|
|
704
711
|
else:
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
y[:] = self.yc
|
|
712
|
+
time = self.output_netcdf.createVariable(
|
|
713
|
+
"seconds", "f4", (self._netcdf_coords[0],)
|
|
714
|
+
)
|
|
715
|
+
time.units = "second"
|
|
710
716
|
|
|
717
|
+
# new output format is 1d x and y
|
|
718
|
+
x = self.output_netcdf.createVariable("x", "f4", ("x"))
|
|
719
|
+
y = self.output_netcdf.createVariable("y", "f4", ("y"))
|
|
720
|
+
x[:] = self.xc
|
|
721
|
+
y[:] = self.yc
|
|
711
722
|
x.units = "meter"
|
|
712
723
|
y.units = "meter"
|
|
713
724
|
|
|
714
|
-
# set up
|
|
715
|
-
def _create_grid_variable(
|
|
725
|
+
# set up function to output data grids
|
|
726
|
+
def _create_grid_variable(
|
|
727
|
+
varname, varunits, vartype="f4", vardims=(), varlong=None
|
|
728
|
+
):
|
|
716
729
|
_v = self.output_netcdf.createVariable(varname, vartype, vardims)
|
|
717
730
|
_v.units = varunits
|
|
731
|
+
if varlong is not None:
|
|
732
|
+
# long_name is provided, record it
|
|
733
|
+
_v.long_name = varlong
|
|
734
|
+
else:
|
|
735
|
+
if not self._legacy_netcdf:
|
|
736
|
+
raise ValueError(
|
|
737
|
+
f"long name must be provided for all variables to create a "
|
|
738
|
+
f"sandsuet compliant data output, "
|
|
739
|
+
f"but was not provided for variable '{varname}'."
|
|
740
|
+
)
|
|
718
741
|
|
|
742
|
+
# loop through main output data grids
|
|
719
743
|
_var_list = list(self._save_var_list.keys())
|
|
720
|
-
_var_list.remove("meta")
|
|
744
|
+
_var_list.remove("meta") # remove group from list
|
|
721
745
|
for _val in _var_list:
|
|
746
|
+
if isinstance(self._save_var_list[_val], list):
|
|
747
|
+
### for now, we silently convert to dictionary format
|
|
748
|
+
# # inputs should be specified as a dictionary
|
|
749
|
+
# warnings.warn(
|
|
750
|
+
# f"Specification format for output data should be `dict`, "
|
|
751
|
+
# f"but was `list`. Converting `list` for one or more variables "
|
|
752
|
+
# f"to `dict` based on item order. This compatability will "
|
|
753
|
+
# f"be removed in a future version."
|
|
754
|
+
# )
|
|
755
|
+
###
|
|
756
|
+
# do the conversion
|
|
757
|
+
__inlist = self._save_var_list[_val]
|
|
758
|
+
__varname = _val
|
|
759
|
+
__varlong = __inlist[4] if len(__inlist) > 4 else None
|
|
760
|
+
_vardict = dict(
|
|
761
|
+
varname=__varname, # use dict key as varname
|
|
762
|
+
varunits=__inlist[1],
|
|
763
|
+
vartype=__inlist[2],
|
|
764
|
+
vardims=__inlist[3],
|
|
765
|
+
varlong=__varlong,
|
|
766
|
+
)
|
|
767
|
+
else:
|
|
768
|
+
_vardict = self._save_var_list[_val]
|
|
769
|
+
|
|
722
770
|
_create_grid_variable(
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
771
|
+
varname=_vardict["varname"],
|
|
772
|
+
varunits=_vardict["varunits"],
|
|
773
|
+
vartype=_vardict["vartype"],
|
|
774
|
+
vardims=_vardict["vardims"],
|
|
775
|
+
varlong=_vardict["varlong"],
|
|
727
776
|
)
|
|
728
777
|
|
|
729
|
-
#
|
|
778
|
+
# find name for subgroup data and make list
|
|
779
|
+
if self._legacy_netcdf:
|
|
780
|
+
self._subgroup_name = "meta"
|
|
781
|
+
else:
|
|
782
|
+
self._subgroup_name = "auxdata"
|
|
783
|
+
self.output_netcdf.createGroup(self._subgroup_name)
|
|
784
|
+
|
|
785
|
+
# set up function to output additional data in subgroup
|
|
730
786
|
def _create_meta_variable(
|
|
731
|
-
varname, varvalue, varunits, vartype="f4", vardims=()
|
|
787
|
+
varname, varvalue, varunits, vartype="f4", vardims=(), varlong=None
|
|
732
788
|
):
|
|
733
789
|
_v = self.output_netcdf.createVariable(
|
|
734
|
-
"
|
|
790
|
+
f"{self._subgroup_name}/" + varname, vartype, vardims
|
|
735
791
|
)
|
|
736
792
|
_v.units = varunits
|
|
793
|
+
# convert string to value from model attrs
|
|
794
|
+
if isinstance(varvalue, str):
|
|
795
|
+
varvalue = getattr(self, varvalue)
|
|
796
|
+
# fill variable
|
|
737
797
|
_v[:] = varvalue
|
|
798
|
+
if varlong is not None:
|
|
799
|
+
# long_name is provided, record it
|
|
800
|
+
_v.long_name = varlong
|
|
801
|
+
else:
|
|
802
|
+
if not self._legacy_netcdf:
|
|
803
|
+
raise ValueError(
|
|
804
|
+
f"long name must be provided for all variables to create a "
|
|
805
|
+
f"sandsuet compliant data output, "
|
|
806
|
+
f"but was not provided for variable '{varname}'."
|
|
807
|
+
)
|
|
738
808
|
|
|
739
|
-
|
|
809
|
+
# loop through additional data in subgroup
|
|
740
810
|
for _val in self._save_var_list["meta"].keys():
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
811
|
+
if isinstance(self._save_var_list["meta"][_val], list):
|
|
812
|
+
### for now, we silently convert to dictionary format
|
|
813
|
+
# inputs should be specified as a dictionary
|
|
814
|
+
# warnings.warn(
|
|
815
|
+
# f"Specification format for output subgroup data should be `dict`, "
|
|
816
|
+
# f"but was `list`. Converting `list` for one or more subgroup variables "
|
|
817
|
+
# f"to `dict` based on item order. This compatability will "
|
|
818
|
+
# f"be removed in a future version."
|
|
819
|
+
# )
|
|
820
|
+
###
|
|
821
|
+
# do the conversion
|
|
822
|
+
__inlist = self._save_var_list["meta"][_val]
|
|
823
|
+
__varname = _val
|
|
824
|
+
if __inlist[0] is None:
|
|
825
|
+
warnings.warn(
|
|
826
|
+
UserWarning(
|
|
827
|
+
"Specifying `None` for time varying dimensions "
|
|
828
|
+
"of model outputs will soon be deprecated. "
|
|
829
|
+
"Change to specifying the name of the "
|
|
830
|
+
"variable to save a string, and/or convert to "
|
|
831
|
+
"dictionary inputs."
|
|
832
|
+
)
|
|
833
|
+
)
|
|
834
|
+
__varvalue = None
|
|
835
|
+
else:
|
|
836
|
+
__varvalue = getattr(self, __inlist[0])
|
|
837
|
+
__varlong = __inlist[4] if len(__inlist) > 4 else None
|
|
838
|
+
_vardict = dict(
|
|
839
|
+
varname=__varname,
|
|
840
|
+
varvalue=__varvalue,
|
|
841
|
+
varunits=__inlist[1],
|
|
842
|
+
vartype=__inlist[2],
|
|
843
|
+
vardims=__inlist[3],
|
|
844
|
+
varlong=__varlong,
|
|
749
845
|
)
|
|
750
|
-
|
|
846
|
+
|
|
751
847
|
else:
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
848
|
+
_vardict = self._save_var_list["meta"][_val]
|
|
849
|
+
|
|
850
|
+
_create_meta_variable(
|
|
851
|
+
varname=_vardict["varname"],
|
|
852
|
+
varvalue=_vardict["varvalue"],
|
|
853
|
+
varunits=_vardict["varunits"],
|
|
854
|
+
vartype=_vardict["vartype"],
|
|
855
|
+
vardims=_vardict["vardims"],
|
|
856
|
+
varlong=_vardict["varlong"],
|
|
857
|
+
)
|
|
759
858
|
|
|
760
859
|
_msg = "Output netCDF file created"
|
|
761
860
|
self.log_info(_msg, verbosity=2)
|
|
@@ -788,17 +887,54 @@ class init_tools(abc.ABC):
|
|
|
788
887
|
Sets up the dictionary object for the standard metadata.
|
|
789
888
|
"""
|
|
790
889
|
# fixed metadata
|
|
791
|
-
self._save_var_list["meta"]["L0"] = [
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
890
|
+
self._save_var_list["meta"]["L0"] = [
|
|
891
|
+
"L0",
|
|
892
|
+
"cells",
|
|
893
|
+
"i8",
|
|
894
|
+
(),
|
|
895
|
+
"channel_entrance__length",
|
|
896
|
+
]
|
|
897
|
+
self._save_var_list["meta"]["N0"] = [
|
|
898
|
+
"N0",
|
|
899
|
+
"cells",
|
|
900
|
+
"i8",
|
|
901
|
+
(),
|
|
902
|
+
"channel_entrance__width",
|
|
903
|
+
]
|
|
904
|
+
self._save_var_list["meta"]["CTR"] = [
|
|
905
|
+
"CTR",
|
|
906
|
+
"cells",
|
|
907
|
+
"i8",
|
|
908
|
+
(),
|
|
909
|
+
"channel_entrance__y_position",
|
|
910
|
+
]
|
|
911
|
+
self._save_var_list["meta"]["dx"] = [
|
|
912
|
+
"dx",
|
|
913
|
+
"meters",
|
|
914
|
+
"f4",
|
|
915
|
+
(),
|
|
916
|
+
"model_grid_cell_edge__length",
|
|
917
|
+
]
|
|
918
|
+
self._save_var_list["meta"]["h0"] = [
|
|
919
|
+
"h0",
|
|
920
|
+
"meters",
|
|
921
|
+
"f4",
|
|
922
|
+
(),
|
|
923
|
+
"channel_entrance__depth",
|
|
924
|
+
]
|
|
925
|
+
self._save_var_list["meta"]["hb"] = [
|
|
926
|
+
"hb",
|
|
927
|
+
"meters",
|
|
928
|
+
"f4",
|
|
929
|
+
(),
|
|
930
|
+
"basin_bottom_initial__depth",
|
|
931
|
+
]
|
|
797
932
|
self._save_var_list["meta"]["cell_type"] = [
|
|
798
933
|
"cell_type",
|
|
799
934
|
"type",
|
|
800
935
|
"i8",
|
|
801
936
|
self._netcdf_coords[1:],
|
|
937
|
+
"model_grid_cell__type",
|
|
802
938
|
]
|
|
803
939
|
# subsidence metadata
|
|
804
940
|
if self._toggle_subsidence:
|
|
@@ -807,37 +943,43 @@ class init_tools(abc.ABC):
|
|
|
807
943
|
"seconds",
|
|
808
944
|
"i8",
|
|
809
945
|
(),
|
|
946
|
+
"basin_bottom_vertical_rate_of_change__start_time",
|
|
810
947
|
]
|
|
811
948
|
self._save_var_list["meta"]["sigma"] = [
|
|
812
949
|
"sigma",
|
|
813
950
|
"meters per timestep",
|
|
814
951
|
"f4",
|
|
815
952
|
self._netcdf_coords[1:],
|
|
953
|
+
"basin_bottom__vertical_rate_of_change",
|
|
816
954
|
]
|
|
817
955
|
# time-varying metadata
|
|
818
956
|
self._save_var_list["meta"]["H_SL"] = [
|
|
819
|
-
|
|
957
|
+
"H_SL",
|
|
820
958
|
"meters",
|
|
821
959
|
"f4",
|
|
822
960
|
(self._netcdf_coords[0]),
|
|
961
|
+
"basin_water_surface__elevation",
|
|
823
962
|
]
|
|
824
963
|
self._save_var_list["meta"]["f_bedload"] = [
|
|
825
|
-
|
|
964
|
+
"f_bedload",
|
|
826
965
|
"fraction",
|
|
827
966
|
"f4",
|
|
828
967
|
(self._netcdf_coords[0]),
|
|
968
|
+
"channel_entrance_water_sediment_sand__volume_fraction",
|
|
829
969
|
]
|
|
830
970
|
self._save_var_list["meta"]["C0_percent"] = [
|
|
831
|
-
|
|
971
|
+
"C0_percent",
|
|
832
972
|
"percent",
|
|
833
973
|
"f4",
|
|
834
974
|
(self._netcdf_coords[0]),
|
|
975
|
+
"channel_entrance__water_sediment__volume_percent",
|
|
835
976
|
]
|
|
836
977
|
self._save_var_list["meta"]["u0"] = [
|
|
837
|
-
|
|
978
|
+
"u0",
|
|
838
979
|
"meters per second",
|
|
839
980
|
"f4",
|
|
840
981
|
(self._netcdf_coords[0]),
|
|
982
|
+
"channel_entrance__speed",
|
|
841
983
|
]
|
|
842
984
|
|
|
843
985
|
def _load_past_etas(self, checkpoint):
|
|
@@ -1030,6 +1172,14 @@ class init_tools(abc.ABC):
|
|
|
1030
1172
|
# set object attribute for model
|
|
1031
1173
|
self.output_netcdf = Dataset(file_path, "r+", format="NETCDF4")
|
|
1032
1174
|
|
|
1175
|
+
# find subgroup name, supporting legacy file format
|
|
1176
|
+
if "meta" in self.output_netcdf.groups.keys():
|
|
1177
|
+
self._subgroup_name = "meta"
|
|
1178
|
+
elif "auxdata" in self.output_netcdf.groups.keys():
|
|
1179
|
+
self._subgroup_name = "auxdata"
|
|
1180
|
+
else:
|
|
1181
|
+
self._subgroup_name = self.output_netcdf.groups.keys()[0]
|
|
1182
|
+
|
|
1033
1183
|
# synch netcdf file
|
|
1034
1184
|
self.output_netcdf.sync()
|
|
1035
1185
|
|
|
@@ -254,7 +254,10 @@ class iteration_tools(abc.ABC):
|
|
|
254
254
|
self.log_info(_msg, verbosity=1)
|
|
255
255
|
|
|
256
256
|
if self._save_metadata or self._save_any_grids:
|
|
257
|
-
|
|
257
|
+
if self._legacy_netcdf:
|
|
258
|
+
self.output_netcdf.variables["time"][save_idx] = self._time
|
|
259
|
+
else:
|
|
260
|
+
self.output_netcdf.variables["seconds"][save_idx] = self._time
|
|
258
261
|
|
|
259
262
|
# ------------------ Figures ------------------
|
|
260
263
|
if len(self._save_fig_list) > 0:
|
|
@@ -302,8 +305,18 @@ class iteration_tools(abc.ABC):
|
|
|
302
305
|
_var_list = list(self._save_var_list.keys())
|
|
303
306
|
_var_list.remove("meta")
|
|
304
307
|
for _val in _var_list:
|
|
308
|
+
# get the inital value from either list or dict
|
|
309
|
+
if isinstance(self._save_var_list[_val], list):
|
|
310
|
+
_modelvar = self._save_var_list[_val][0]
|
|
311
|
+
_ncvar = _val
|
|
312
|
+
else:
|
|
313
|
+
_modelvar = self._save_var_list[_val]["varvalue"]
|
|
314
|
+
_ncvar = self._save_var_list[_val]["varname"]
|
|
315
|
+
|
|
305
316
|
self.save_grids(
|
|
306
|
-
|
|
317
|
+
var_name=_ncvar,
|
|
318
|
+
var=getattr(self, _modelvar),
|
|
319
|
+
save_idx=save_idx,
|
|
307
320
|
)
|
|
308
321
|
|
|
309
322
|
# ------------------ metadata ------------------
|
|
@@ -312,9 +325,27 @@ class iteration_tools(abc.ABC):
|
|
|
312
325
|
self.log_info(_msg, verbosity=2)
|
|
313
326
|
|
|
314
327
|
for _val in self._save_var_list["meta"].keys():
|
|
328
|
+
# get the values from either list or dict
|
|
329
|
+
if isinstance(self._save_var_list["meta"][_val], list):
|
|
330
|
+
_dims = len(self._save_var_list["meta"][_val][3])
|
|
331
|
+
_modelvar = self._save_var_list["meta"][_val][0]
|
|
332
|
+
_ncvar = _val
|
|
333
|
+
else:
|
|
334
|
+
_dims = len(self._save_var_list["meta"][_val]["vardims"])
|
|
335
|
+
_modelvar = self._save_var_list["meta"][_val]["varvalue"]
|
|
336
|
+
_ncvar = self._save_var_list["meta"][_val]["varname"]
|
|
337
|
+
|
|
338
|
+
# safety check, if None, replace with name of key (_val)
|
|
339
|
+
if _modelvar is None:
|
|
340
|
+
_modelvar = _val
|
|
341
|
+
|
|
315
342
|
# use knowledge of time-varying values to save them
|
|
316
|
-
if
|
|
317
|
-
self.output_netcdf[
|
|
343
|
+
if _dims > 2:
|
|
344
|
+
self.output_netcdf[self._subgroup_name][_ncvar][save_idx] = getattr(
|
|
345
|
+
self, _modelvar
|
|
346
|
+
)
|
|
347
|
+
else:
|
|
348
|
+
pass # do not re-save values that do not change over time
|
|
318
349
|
|
|
319
350
|
# -------------------- sync --------------------
|
|
320
351
|
if self._save_metadata or self._save_any_grids:
|