pyDeltaRCM 2.1.9__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.
Files changed (135) hide show
  1. {pydeltarcm-2.1.9/pyDeltaRCM.egg-info → pydeltarcm-2.2.0}/PKG-INFO +1 -1
  2. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/conf.py +4 -2
  3. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/custom_saving.rst +14 -9
  4. pydeltarcm-2.2.0/docs/source/examples/gotcha_simulataneous_models.rst +62 -0
  5. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/index.rst +8 -0
  6. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/info/outputfile.rst +20 -14
  7. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM/_version.py +1 -1
  8. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM/hook_tools.py +1 -1
  9. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM/init_tools.py +208 -59
  10. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM/iteration_tools.py +35 -4
  11. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM/model.py +44 -36
  12. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM/water_tools.py +10 -6
  13. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0/pyDeltaRCM.egg-info}/PKG-INFO +1 -1
  14. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM.egg-info/SOURCES.txt +1 -0
  15. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/integration/test_checkpointing.py +321 -255
  16. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/integration/test_consistent_outputs.py +70 -9
  17. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/integration/test_timing_triggers.py +11 -11
  18. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/test_init_tools.py +266 -28
  19. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/test_iteration_tools.py +85 -9
  20. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/LICENSE +0 -0
  21. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/MANIFEST.in +0 -0
  22. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/README.rst +0 -0
  23. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/.nojekyll +0 -0
  24. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/_resources/checkpoint/checkpoint.npz +0 -0
  25. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/_resources/checkpoint.yaml +0 -0
  26. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/_static/style.css +0 -0
  27. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/_templates/page.html +0 -0
  28. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/basic_runs.rst +0 -0
  29. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/custom_class_preprocessor.rst +0 -0
  30. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/custom_yaml.rst +0 -0
  31. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/modelzoo.rst +0 -0
  32. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/overwrite_topo_diffusion.rst +0 -0
  33. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/resume_from_checkpoint.rst +0 -0
  34. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/simple_example.ipynb +0 -0
  35. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/slight_slope.rst +0 -0
  36. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/subsidence_region.rst +0 -0
  37. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/updating_boundary_conditions.rst +0 -0
  38. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/variable_bedload.rst +0 -0
  39. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/examples/variable_velocity.rst +0 -0
  40. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/guides/10min.rst +0 -0
  41. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/guides/advanced_configuration_guide.inc +0 -0
  42. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/guides/developer_guide.rst +0 -0
  43. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/guides/getting_started.rst +0 -0
  44. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/guides/subsidence_guide.inc +0 -0
  45. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/guides/user_guide.rst +0 -0
  46. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/index.rst +0 -0
  47. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/info/hydrodynamics.rst +0 -0
  48. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/info/index.rst +0 -0
  49. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/info/initialization.rst +0 -0
  50. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/info/modeltime.rst +0 -0
  51. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/info/morphodynamics.rst +0 -0
  52. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/info/yamlparameters.rst +0 -0
  53. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/meta/citing.rst +0 -0
  54. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/meta/conduct.rst +0 -0
  55. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/meta/contributing.rst +0 -0
  56. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/meta/installing.rst +0 -0
  57. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/meta/license.rst +0 -0
  58. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/meta/usedby.rst +0 -0
  59. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/debug_tools/debug_demo.py +0 -0
  60. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/guides/10min_demo.py +0 -0
  61. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/guides/cover.py +0 -0
  62. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/guides/output_file.py +0 -0
  63. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/init_tools/domain_basin_inlet_depth.py +0 -0
  64. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/init_tools/domain_inlet_geometry.py +0 -0
  65. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/init_tools/domain_parameters.py +0 -0
  66. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/init_tools/domain_size_compare.py +0 -0
  67. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/modeltime/_base.py +0 -0
  68. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/modeltime/four_year_condensed_plot.py +0 -0
  69. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/modeltime/four_year_plot.py +0 -0
  70. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/modeltime/one_year_plot.py +0 -0
  71. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/sed_tools/_initial_bed_state.py +0 -0
  72. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/sed_tools/route_all_mud_parcels.py +0 -0
  73. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/sed_tools/route_all_sand_parcels.py +0 -0
  74. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/sed_tools/sediment_weights_examples.py +0 -0
  75. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/sed_tools/topo_diffusion.py +0 -0
  76. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/_accumulate_free_surface_walks.py +0 -0
  77. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/_check_for_loops.py +0 -0
  78. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/_smooth_free_surface.py +0 -0
  79. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/compute_free_surface_inputs.py +0 -0
  80. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/compute_free_surface_outputs.py +0 -0
  81. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/flooding_correction.py +0 -0
  82. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/run_water_iteration.py +0 -0
  83. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/pyplots/water_tools/water_weights_examples.py +0 -0
  84. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/reference/debug_tools/index.rst +0 -0
  85. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/reference/hook_tools/index.rst +0 -0
  86. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/reference/index.rst +0 -0
  87. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/reference/init_tools/index.rst +0 -0
  88. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/reference/iteration_tools/index.rst +0 -0
  89. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/reference/model/index.rst +0 -0
  90. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/reference/model/model_hooks.rst +0 -0
  91. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/reference/model/yaml_defaults.rst +0 -0
  92. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/reference/preprocessor/index.rst +0 -0
  93. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/reference/sed_tools/index.rst +0 -0
  94. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/reference/shared_tools/index.rst +0 -0
  95. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/docs/source/reference/water_tools/index.rst +0 -0
  96. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM/__init__.py +0 -0
  97. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM/__main__.py +0 -0
  98. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM/debug_tools.py +0 -0
  99. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM/default.yml +0 -0
  100. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM/preprocessor.py +0 -0
  101. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM/sed_tools.py +0 -0
  102. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM/shared_tools.py +0 -0
  103. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM.egg-info/dependency_links.txt +0 -0
  104. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM.egg-info/entry_points.txt +0 -0
  105. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM.egg-info/requires.txt +0 -0
  106. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyDeltaRCM.egg-info/top_level.txt +0 -0
  107. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/pyproject.toml +0 -0
  108. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/setup.cfg +0 -0
  109. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/__init__.py +0 -0
  110. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type.png +0 -0
  111. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_list_index.png +0 -0
  112. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_list_mix_tuple_index.png +0 -0
  113. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_list_tuple.png +0 -0
  114. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_multiple_diff_args.png +0 -0
  115. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_multiple_diff_kwargs.png +0 -0
  116. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_multiple_index_calls.png +0 -0
  117. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_no_grid.png +0 -0
  118. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_single_index.png +0 -0
  119. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_cell_type_single_tuple.png +0 -0
  120. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_velocity.png +0 -0
  121. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_domain_withlabel.png +0 -0
  122. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_iwalk.png +0 -0
  123. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_plot_multiple_subplots.png +0 -0
  124. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_show_line_pts_Nx2_array.png +0 -0
  125. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/imgs_baseline/test_show_line_set_points.png +0 -0
  126. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/integration/__init__.py +0 -0
  127. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/integration/test_cli.py +0 -0
  128. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/test_debug_tools.py +0 -0
  129. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/test_logging.py +0 -0
  130. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/test_model.py +0 -0
  131. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/test_preprocessor.py +0 -0
  132. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/test_sed_tools.py +0 -0
  133. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/test_shared_tools.py +0 -0
  134. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/test_water_tools.py +0 -0
  135. {pydeltarcm-2.1.9 → pydeltarcm-2.2.0}/tests/utilities.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyDeltaRCM
3
- Version: 2.1.9
3
+ Version: 2.2.0
4
4
  Summary: Python version of original Matlab DeltaRCM.
5
5
  Author-email: Andrew Moodie <amoodie@tamu.edu>
6
6
  Maintainer-email: Andrew Moodie <amoodie@tamu.edu>
@@ -113,5 +113,7 @@ linkcheck_ignore = [
113
113
  r'https://doi.org/10.1029/2021GL095053',
114
114
  r'https://doi.org/10.1029/2018GL079405',
115
115
  r'https://doi.org/10.1029/2022JF006762',
116
- r'https://doi.org/10.1086/626637'
117
- ]
116
+ r'https://doi.org/10.1086/626637',
117
+ r'https://doi.org/10.1029/2023JE008183',
118
+ r'https://doi.org/10.1029/2023je008183'
119
+ ]
@@ -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', ('time', 'x', 'y')]`` for the active layer).
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`, `time`.
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'] = ['active_layer', 'fraction',
52
- ... 'f4', ('time',
53
- ... 'x', 'y')]
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'] = ['Np_water',
57
- ... 'parcels',
58
- ... 'i8', ()]
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', ('time', 'x', 'y')]}
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
+
@@ -11,6 +11,14 @@ Running the model
11
11
  basic_runs
12
12
  resume_from_checkpoint
13
13
 
14
+ Common "gotchas"
15
+ ----------------
16
+
17
+ .. toctree::
18
+ :maxdepth: 1
19
+
20
+ gotcha_simulataneous_models
21
+
14
22
 
15
23
  Modifying initial conditions
16
24
  ----------------------------
@@ -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 `time` :math:`\times`
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
- .. note::
20
+ .. important::
21
21
 
22
- The format of the output netCDF file coordinate changed in `v2.1.0`. The
23
- old format is documented
24
- in :attr:`~pyDeltaRCM.model.DeltaModel.legacy_netcdf`, and that input
25
- parameter `legacy_netcdf` can be used to create on output netcdf file with
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 `time`, `x`, and `y` in the output netCDF4 file.
33
- These arrays are 1D arrays, which specify the location of each cell in the domain in *dimensional* coordinates (e.g., meters).
34
- In the downstream direction, the distance of each cell from the inlet boundary is specified in `x` in meters.
35
- Similarly, the cross-domain distance is specified in `y` in meters.
36
- Lastly, the `time` variable is stored as a 1D array with model `time` in seconds.
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
- `DeltaMetrics <https://github.com/DeltaRCM/DeltaMetrics>`_,
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
 
@@ -3,4 +3,4 @@ def __version__() -> str:
3
3
  Private version declaration, gets assigned to pyDeltaRCM.__version__
4
4
  during import
5
5
  """
6
- return "2.1.9"
6
+ return "2.2.0"
@@ -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 ('total_time').
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.
@@ -386,7 +386,6 @@ class init_tools(abc.ABC):
386
386
 
387
387
  # kernels for topographic smoothing
388
388
  self.kernel1 = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]]).astype(np.int64)
389
-
390
389
  self.kernel2 = np.array([[1, 1, 1], [1, 0, 1], [1, 1, 1]]).astype(np.int64)
391
390
 
392
391
  def create_boundary_conditions(self) -> None:
@@ -434,7 +433,7 @@ class init_tools(abc.ABC):
434
433
 
435
434
  # at inlet
436
435
  self.qw0 = self.u0 * self.h0 # water unit input discharge
437
- self.Qp_water = self.Qw0 / self._Np_water # volume each water parcel
436
+ self.Qp_water = self.Qw0 / self._Np_water # discharge each water parcel
438
437
  self.qs0 = self.qw0 * self.C0 # sed unit discharge
439
438
  self.dVs = 0.1 * self.N0**2 * self.V0 # total sed added per timestep
440
439
  self.Qs0 = self.Qw0 * self.C0 # sediment total input discharge
@@ -660,6 +659,22 @@ class init_tools(abc.ABC):
660
659
  file_path = os.path.join(directory, filename)
661
660
  _msg = "Target output NetCDF4 file: {file}".format(file=file_path)
662
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)
663
678
 
664
679
  if (os.path.exists(file_path)) and (self._clobber_netcdf is False):
665
680
  raise FileExistsError(
@@ -679,6 +694,8 @@ class init_tools(abc.ABC):
679
694
  self.output_netcdf.source = "pyDeltaRCM v{ver}".format(
680
695
  ver=self.__pyDeltaRCM_version__
681
696
  )
697
+ if not self._legacy_netcdf:
698
+ self.output_netcdf.sandsuet_version = _sandsuet_version
682
699
 
683
700
  # create master dimensions (pulls from `self._netcdf_coords`)
684
701
  self.output_netcdf.createDimension(self._netcdf_coords[1], self.L)
@@ -686,77 +703,158 @@ class init_tools(abc.ABC):
686
703
  self.output_netcdf.createDimension(self._netcdf_coords[0], None)
687
704
 
688
705
  # create master coordinates (as netCDF variables)
689
- time = self.output_netcdf.createVariable(
690
- "time", "f4", (self._netcdf_coords[0],)
691
- )
692
- time.units = "second"
693
-
694
706
  if self._legacy_netcdf:
695
- # old format is 2d array x and y
696
- x = self.output_netcdf.createVariable(
697
- "x", "f4", self._netcdf_coords[1:]
698
- )
699
- y = self.output_netcdf.createVariable(
700
- "y", "f4", self._netcdf_coords[1:]
707
+ time = self.output_netcdf.createVariable(
708
+ "time", "f4", (self._netcdf_coords[0],)
701
709
  )
702
- x[:] = self.x
703
- y[:] = self.y
704
710
 
705
711
  else:
706
- # new output format is 1d x and y
707
- x = self.output_netcdf.createVariable("x", "f4", ("x"))
708
- y = self.output_netcdf.createVariable("y", "f4", ("y"))
709
- x[:] = self.xc
710
- y[:] = self.yc
712
+ time = self.output_netcdf.createVariable(
713
+ "seconds", "f4", (self._netcdf_coords[0],)
714
+ )
715
+ time.units = "second"
711
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
712
722
  x.units = "meter"
713
723
  y.units = "meter"
714
724
 
715
- # set up variables for output data grids
716
- def _create_grid_variable(varname, varunits, vartype="f4", vardims=()):
725
+ # set up function to output data grids
726
+ def _create_grid_variable(
727
+ varname, varunits, vartype="f4", vardims=(), varlong=None
728
+ ):
717
729
  _v = self.output_netcdf.createVariable(varname, vartype, vardims)
718
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
+ )
719
741
 
742
+ # loop through main output data grids
720
743
  _var_list = list(self._save_var_list.keys())
721
- _var_list.remove("meta")
744
+ _var_list.remove("meta") # remove group from list
722
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
+
723
770
  _create_grid_variable(
724
- _val,
725
- self._save_var_list[_val][1],
726
- self._save_var_list[_val][2],
727
- self._save_var_list[_val][3],
771
+ varname=_vardict["varname"],
772
+ varunits=_vardict["varunits"],
773
+ vartype=_vardict["vartype"],
774
+ vardims=_vardict["vardims"],
775
+ varlong=_vardict["varlong"],
728
776
  )
729
777
 
730
- # set up metadata group and populate variables
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
731
786
  def _create_meta_variable(
732
- varname, varvalue, varunits, vartype="f4", vardims=()
787
+ varname, varvalue, varunits, vartype="f4", vardims=(), varlong=None
733
788
  ):
734
789
  _v = self.output_netcdf.createVariable(
735
- "meta/" + varname, vartype, vardims
790
+ f"{self._subgroup_name}/" + varname, vartype, vardims
736
791
  )
737
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
738
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
+ )
739
808
 
740
- self.output_netcdf.createGroup("meta")
809
+ # loop through additional data in subgroup
741
810
  for _val in self._save_var_list["meta"].keys():
742
- # time-varying initialize w/ None value
743
- if self._save_var_list["meta"][_val][0] is None:
744
- _create_meta_variable(
745
- _val,
746
- self._save_var_list["meta"][_val][0],
747
- self._save_var_list["meta"][_val][1],
748
- self._save_var_list["meta"][_val][2],
749
- self._save_var_list["meta"][_val][3],
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,
750
845
  )
751
- # for scalars, get the attribute and store it
846
+
752
847
  else:
753
- _create_meta_variable(
754
- _val,
755
- getattr(self, self._save_var_list["meta"][_val][0]),
756
- self._save_var_list["meta"][_val][1],
757
- self._save_var_list["meta"][_val][2],
758
- self._save_var_list["meta"][_val][3],
759
- )
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
+ )
760
858
 
761
859
  _msg = "Output netCDF file created"
762
860
  self.log_info(_msg, verbosity=2)
@@ -789,17 +887,54 @@ class init_tools(abc.ABC):
789
887
  Sets up the dictionary object for the standard metadata.
790
888
  """
791
889
  # fixed metadata
792
- self._save_var_list["meta"]["L0"] = ["L0", "cells", "i8", ()]
793
- self._save_var_list["meta"]["N0"] = ["N0", "cells", "i8", ()]
794
- self._save_var_list["meta"]["CTR"] = ["CTR", "cells", "i8", ()]
795
- self._save_var_list["meta"]["dx"] = ["dx", "meters", "f4", ()]
796
- self._save_var_list["meta"]["h0"] = ["h0", "meters", "f4", ()]
797
- self._save_var_list["meta"]["hb"] = ["hb", "meters", "f4", ()]
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
+ ]
798
932
  self._save_var_list["meta"]["cell_type"] = [
799
933
  "cell_type",
800
934
  "type",
801
935
  "i8",
802
936
  self._netcdf_coords[1:],
937
+ "model_grid_cell__type",
803
938
  ]
804
939
  # subsidence metadata
805
940
  if self._toggle_subsidence:
@@ -808,37 +943,43 @@ class init_tools(abc.ABC):
808
943
  "seconds",
809
944
  "i8",
810
945
  (),
946
+ "basin_bottom_vertical_rate_of_change__start_time",
811
947
  ]
812
948
  self._save_var_list["meta"]["sigma"] = [
813
949
  "sigma",
814
950
  "meters per timestep",
815
951
  "f4",
816
952
  self._netcdf_coords[1:],
953
+ "basin_bottom__vertical_rate_of_change",
817
954
  ]
818
955
  # time-varying metadata
819
956
  self._save_var_list["meta"]["H_SL"] = [
820
- None,
957
+ "H_SL",
821
958
  "meters",
822
959
  "f4",
823
960
  (self._netcdf_coords[0]),
961
+ "basin_water_surface__elevation",
824
962
  ]
825
963
  self._save_var_list["meta"]["f_bedload"] = [
826
- None,
964
+ "f_bedload",
827
965
  "fraction",
828
966
  "f4",
829
967
  (self._netcdf_coords[0]),
968
+ "channel_entrance_water_sediment_sand__volume_fraction",
830
969
  ]
831
970
  self._save_var_list["meta"]["C0_percent"] = [
832
- None,
971
+ "C0_percent",
833
972
  "percent",
834
973
  "f4",
835
974
  (self._netcdf_coords[0]),
975
+ "channel_entrance__water_sediment__volume_percent",
836
976
  ]
837
977
  self._save_var_list["meta"]["u0"] = [
838
- None,
978
+ "u0",
839
979
  "meters per second",
840
980
  "f4",
841
981
  (self._netcdf_coords[0]),
982
+ "channel_entrance__speed",
842
983
  ]
843
984
 
844
985
  def _load_past_etas(self, checkpoint):
@@ -1031,6 +1172,14 @@ class init_tools(abc.ABC):
1031
1172
  # set object attribute for model
1032
1173
  self.output_netcdf = Dataset(file_path, "r+", format="NETCDF4")
1033
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
+
1034
1183
  # synch netcdf file
1035
1184
  self.output_netcdf.sync()
1036
1185