roms-tools 2.3.0__py3-none-any.whl → 2.5.0__py3-none-any.whl

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 (303) hide show
  1. ci/environment.yml +1 -0
  2. roms_tools/__init__.py +2 -1
  3. roms_tools/analysis/roms_output.py +81 -98
  4. roms_tools/plot.py +4 -2
  5. roms_tools/setup/boundary_forcing.py +207 -208
  6. roms_tools/setup/datasets.py +149 -33
  7. roms_tools/setup/grid.py +35 -102
  8. roms_tools/setup/initial_conditions.py +179 -132
  9. roms_tools/setup/nesting.py +239 -86
  10. roms_tools/setup/river_forcing.py +266 -128
  11. roms_tools/setup/surface_forcing.py +137 -76
  12. roms_tools/setup/tides.py +10 -36
  13. roms_tools/setup/topography.py +25 -2
  14. roms_tools/setup/utils.py +52 -82
  15. roms_tools/tests/test_analysis/test_roms_output.py +233 -70
  16. roms_tools/tests/test_setup/test_boundary_forcing.py +283 -57
  17. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zattrs +3 -1
  18. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zmetadata +3 -1
  19. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_east/0.0.0 +0 -0
  20. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_south/0.0.0 +0 -0
  21. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/0.0.0 +0 -0
  22. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_east/0.0.0 +0 -0
  23. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_south/0.0.0 +0 -0
  24. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/0.0.0 +0 -0
  25. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_east/0.0.0 +0 -0
  26. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_south/0.0.0 +0 -0
  27. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/0.0.0 +0 -0
  28. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_east/0.0.0 +0 -0
  29. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_south/0.0.0 +0 -0
  30. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/0.0.0 +0 -0
  31. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_east/0.0.0 +0 -0
  32. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_south/0.0.0 +0 -0
  33. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/0.0.0 +0 -0
  34. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_east/0.0.0 +0 -0
  35. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_south/0.0.0 +0 -0
  36. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/0.0.0 +0 -0
  37. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_east/0.0.0 +0 -0
  38. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_south/0.0.0 +0 -0
  39. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/0.0.0 +0 -0
  40. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_east/0.0.0 +0 -0
  41. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_south/0.0.0 +0 -0
  42. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/0.0.0 +0 -0
  43. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_east/0.0.0 +0 -0
  44. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_south/0.0.0 +0 -0
  45. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/0.0.0 +0 -0
  46. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_east/0.0.0 +0 -0
  47. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_south/0.0.0 +0 -0
  48. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/0.0.0 +0 -0
  49. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_east/0.0.0 +0 -0
  50. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_south/0.0.0 +0 -0
  51. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/0.0.0 +0 -0
  52. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_east/0.0.0 +0 -0
  53. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_south/0.0.0 +0 -0
  54. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/0.0.0 +0 -0
  55. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_east/0.0.0 +0 -0
  56. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_north/0.0.0 +0 -0
  57. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_south/0.0.0 +0 -0
  58. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/0.0.0 +0 -0
  59. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_east/0.0.0 +0 -0
  60. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_south/0.0.0 +0 -0
  61. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/0.0.0 +0 -0
  62. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_east/0.0.0 +0 -0
  63. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_south/0.0.0 +0 -0
  64. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/0.0.0 +0 -0
  65. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_east/0.0.0 +0 -0
  66. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_south/0.0.0 +0 -0
  67. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/0.0.0 +0 -0
  68. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_east/0.0.0 +0 -0
  69. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_south/0.0.0 +0 -0
  70. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/0.0.0 +0 -0
  71. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_east/0.0.0 +0 -0
  72. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_north/0.0.0 +0 -0
  73. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_south/0.0.0 +0 -0
  74. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/0.0.0 +0 -0
  75. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_east/0.0.0 +0 -0
  76. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_north/0.0.0 +0 -0
  77. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_south/0.0.0 +0 -0
  78. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/0.0.0 +0 -0
  79. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_east/0.0.0 +0 -0
  80. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_north/0.0.0 +0 -0
  81. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_south/0.0.0 +0 -0
  82. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/0.0.0 +0 -0
  83. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_east/0.0.0 +0 -0
  84. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_north/0.0.0 +0 -0
  85. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_south/0.0.0 +0 -0
  86. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/0.0.0 +0 -0
  87. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_east/0.0.0 +0 -0
  88. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_north/0.0.0 +0 -0
  89. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_south/0.0.0 +0 -0
  90. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/0.0.0 +0 -0
  91. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_east/0.0.0 +0 -0
  92. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_north/0.0.0 +0 -0
  93. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_south/0.0.0 +0 -0
  94. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/0.0.0 +0 -0
  95. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_east/0.0.0 +0 -0
  96. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_north/0.0.0 +0 -0
  97. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_south/0.0.0 +0 -0
  98. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/0.0.0 +0 -0
  99. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_east/0.0.0 +0 -0
  100. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_north/0.0.0 +0 -0
  101. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_south/0.0.0 +0 -0
  102. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/0.0.0 +0 -0
  103. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_east/0.0.0 +0 -0
  104. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_north/0.0.0 +0 -0
  105. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_south/0.0.0 +0 -0
  106. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/0.0.0 +0 -0
  107. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_east/0.0.0 +0 -0
  108. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_north/0.0.0 +0 -0
  109. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_south/0.0.0 +0 -0
  110. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/0.0.0 +0 -0
  111. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_east/0.0.0 +0 -0
  112. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_north/0.0.0 +0 -0
  113. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_south/0.0.0 +0 -0
  114. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/0.0.0 +0 -0
  115. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_east/0.0.0 +0 -0
  116. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_north/0.0.0 +0 -0
  117. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_south/0.0.0 +0 -0
  118. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/0.0.0 +0 -0
  119. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_east/0.0.0 +0 -0
  120. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_north/0.0.0 +0 -0
  121. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_south/0.0.0 +0 -0
  122. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/0.0.0 +0 -0
  123. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_east/0.0.0 +0 -0
  124. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_north/0.0.0 +0 -0
  125. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_south/0.0.0 +0 -0
  126. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/0.0.0 +0 -0
  127. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/0.0.0 +0 -0
  128. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_north/0.0.0 +0 -0
  129. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_south/0.0.0 +0 -0
  130. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/0.0.0 +0 -0
  131. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zattrs +2 -2
  132. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zmetadata +8 -7
  133. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/abs_time/.zattrs +1 -0
  134. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/dust/0.0.0 +0 -0
  135. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/dust_time/.zattrs +1 -1
  136. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/iron/0.0.0 +0 -0
  137. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/iron_time/.zattrs +1 -1
  138. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nhy/0.0.0 +0 -0
  139. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nhy_time/.zattrs +1 -1
  140. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nox/0.0.0 +0 -0
  141. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nox_time/.zattrs +1 -1
  142. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air/0.0.0 +0 -0
  143. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air_alt/0.0.0 +0 -0
  144. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_time/.zattrs +1 -1
  145. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zattrs +2 -2
  146. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zmetadata +2 -2
  147. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/dust/0.0.0 +0 -0
  148. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/iron/0.0.0 +0 -0
  149. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nhy/0.0.0 +0 -0
  150. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nox/0.0.0 +0 -0
  151. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air/0.0.0 +0 -0
  152. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air_alt/0.0.0 +0 -0
  153. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zattrs +5 -3
  154. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zmetadata +156 -121
  155. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/.zarray +2 -2
  156. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/.zattrs +2 -1
  157. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/0 +0 -0
  158. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/bry_time/.zarray +2 -2
  159. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/bry_time/.zattrs +1 -1
  160. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/bry_time/0 +0 -0
  161. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_east/.zarray +4 -4
  162. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_east/0.0.0 +0 -0
  163. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_north/.zarray +4 -4
  164. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_north/0.0.0 +0 -0
  165. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/.zarray +4 -4
  166. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/0.0.0 +0 -0
  167. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_west/.zarray +4 -4
  168. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_west/0.0.0 +0 -0
  169. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/.zarray +4 -4
  170. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/0.0.0 +0 -0
  171. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_north/.zarray +4 -4
  172. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_north/0.0.0 +0 -0
  173. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/.zarray +4 -4
  174. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/0.0.0 +0 -0
  175. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_west/.zarray +4 -4
  176. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_west/0.0.0 +0 -0
  177. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/.zarray +4 -4
  178. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/0.0.0 +0 -0
  179. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_north/.zarray +4 -4
  180. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_north/0.0.0 +0 -0
  181. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_south/.zarray +4 -4
  182. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_south/0.0.0 +0 -0
  183. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/.zarray +4 -4
  184. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/0.0.0 +0 -0
  185. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/.zarray +4 -4
  186. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/0.0 +0 -0
  187. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_north/.zarray +4 -4
  188. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_north/0.0 +0 -0
  189. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_south/.zarray +4 -4
  190. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_south/0.0 +0 -0
  191. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/.zarray +4 -4
  192. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/0.0 +0 -0
  193. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/.zarray +4 -4
  194. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/0.0.0 +0 -0
  195. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/.zarray +4 -4
  196. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/0.0.0 +0 -0
  197. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/.zarray +4 -4
  198. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/0.0.0 +0 -0
  199. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/.zarray +4 -4
  200. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/0.0.0 +0 -0
  201. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/.zarray +4 -4
  202. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/0.0 +0 -0
  203. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/.zarray +4 -4
  204. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/0.0 +0 -0
  205. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/.zarray +4 -4
  206. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/0.0 +0 -0
  207. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/.zarray +4 -4
  208. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/0.0 +0 -0
  209. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/.zarray +4 -4
  210. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/.zattrs +8 -0
  211. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/0.0 +0 -0
  212. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_north/.zarray +4 -4
  213. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_north/.zattrs +8 -0
  214. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_north/0.0 +0 -0
  215. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/.zarray +4 -4
  216. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/.zattrs +8 -0
  217. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/0.0 +0 -0
  218. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_west/.zarray +4 -4
  219. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_west/.zattrs +8 -0
  220. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_west/0.0 +0 -0
  221. roms_tools/tests/test_setup/test_data/grid.zarr/.zattrs +1 -1
  222. roms_tools/tests/test_setup/test_data/grid.zarr/.zmetadata +2 -2
  223. roms_tools/tests/test_setup/test_data/grid.zarr/angle/0.0 +0 -0
  224. roms_tools/tests/test_setup/test_data/grid.zarr/angle_coarse/0.0 +0 -0
  225. roms_tools/tests/test_setup/test_data/grid.zarr/f/0.0 +0 -0
  226. roms_tools/tests/test_setup/test_data/grid.zarr/h/.zattrs +1 -1
  227. roms_tools/tests/test_setup/test_data/grid.zarr/h/0.0 +0 -0
  228. roms_tools/tests/test_setup/test_data/grid.zarr/lat_coarse/0.0 +0 -0
  229. roms_tools/tests/test_setup/test_data/grid.zarr/lat_rho/0.0 +0 -0
  230. roms_tools/tests/test_setup/test_data/grid.zarr/lat_u/0.0 +0 -0
  231. roms_tools/tests/test_setup/test_data/grid.zarr/lat_v/0.0 +0 -0
  232. roms_tools/tests/test_setup/test_data/grid.zarr/pm/0.0 +0 -0
  233. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zattrs +4 -4
  234. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zmetadata +4 -4
  235. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/angle/0.0 +0 -0
  236. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/angle_coarse/0.0 +0 -0
  237. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/f/0.0 +0 -0
  238. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/h/0.0 +0 -0
  239. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_coarse/0.0 +0 -0
  240. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_rho/0.0 +0 -0
  241. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_u/0.0 +0 -0
  242. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_v/0.0 +0 -0
  243. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_coarse/0.0 +0 -0
  244. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_rho/0.0 +0 -0
  245. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_u/0.0 +0 -0
  246. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_v/0.0 +0 -0
  247. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_coarse/0.0 +0 -0
  248. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_rho/0.0 +0 -0
  249. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_u/0.0 +0 -0
  250. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_v/0.0 +0 -0
  251. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/pm/0.0 +0 -0
  252. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/pn/0.0 +0 -0
  253. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zattrs +2 -1
  254. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zmetadata +6 -4
  255. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Cs_r/.zattrs +1 -1
  256. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Cs_w/.zattrs +1 -1
  257. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NH4/0.0.0.0 +0 -0
  258. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NO3/0.0.0.0 +0 -0
  259. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/PO4/0.0.0.0 +0 -0
  260. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/abs_time/.zattrs +1 -0
  261. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatSi/0.0.0.0 +0 -0
  262. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ocean_time/.zattrs +1 -1
  263. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/salt/0.0.0.0 +0 -0
  264. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spC/0.0.0.0 +0 -0
  265. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spCaCO3/0.0.0.0 +0 -0
  266. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spFe/0.0.0.0 +0 -0
  267. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/temp/0.0.0.0 +0 -0
  268. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/u/0.0.0.0 +0 -0
  269. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ubar/0.0.0 +0 -0
  270. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/v/0.0.0.0 +0 -0
  271. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/vbar/0.0.0 +0 -0
  272. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zeta/0.0.0 +0 -0
  273. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zmetadata +56 -0
  274. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/nriver/.zarray +20 -0
  275. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/nriver/.zattrs +6 -0
  276. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/nriver/0 +0 -0
  277. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_location/.zarray +22 -0
  278. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_location/.zattrs +8 -0
  279. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_location/0.0 +0 -0
  280. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/.zmetadata +56 -0
  281. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/nriver/.zarray +20 -0
  282. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/nriver/.zattrs +6 -0
  283. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/nriver/0 +0 -0
  284. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_location/.zarray +22 -0
  285. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_location/.zattrs +8 -0
  286. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_location/0.0 +0 -0
  287. roms_tools/tests/test_setup/test_grid.py +0 -13
  288. roms_tools/tests/test_setup/test_initial_conditions.py +220 -66
  289. roms_tools/tests/test_setup/test_nesting.py +139 -118
  290. roms_tools/tests/test_setup/test_river_forcing.py +583 -293
  291. roms_tools/tests/test_setup/test_surface_forcing.py +149 -73
  292. roms_tools/tests/test_setup/test_tides.py +4 -16
  293. roms_tools/tests/test_setup/test_utils.py +1 -0
  294. roms_tools/tests/test_setup/test_validation.py +34 -2
  295. roms_tools/tests/{test_utils.py → test_tiling/test_partition.py} +1 -1
  296. roms_tools/tiling/partition.py +338 -0
  297. roms_tools/utils.py +66 -333
  298. roms_tools/vertical_coordinate.py +54 -133
  299. {roms_tools-2.3.0.dist-info → roms_tools-2.5.0.dist-info}/METADATA +1 -1
  300. {roms_tools-2.3.0.dist-info → roms_tools-2.5.0.dist-info}/RECORD +303 -290
  301. {roms_tools-2.3.0.dist-info → roms_tools-2.5.0.dist-info}/WHEEL +1 -1
  302. {roms_tools-2.3.0.dist-info → roms_tools-2.5.0.dist-info}/LICENSE +0 -0
  303. {roms_tools-2.3.0.dist-info → roms_tools-2.5.0.dist-info}/top_level.txt +0 -0
@@ -5,8 +5,10 @@ from datetime import datetime
5
5
  import numpy as np
6
6
  import matplotlib.pyplot as plt
7
7
  from pathlib import Path
8
- from typing import Dict, Union, List
8
+ import logging
9
+ from typing import Dict, Union, List, Optional
9
10
  from roms_tools import Grid
11
+ from roms_tools.utils import save_datasets
10
12
  from roms_tools.regrid import LateralRegrid
11
13
  from roms_tools.plot import _plot
12
14
  from roms_tools.setup.datasets import (
@@ -21,7 +23,6 @@ from roms_tools.setup.utils import (
21
23
  interpolate_from_climatology,
22
24
  get_variable_metadata,
23
25
  group_dataset,
24
- save_datasets,
25
26
  rotate_velocities,
26
27
  convert_to_roms_time,
27
28
  _to_yaml,
@@ -37,10 +38,14 @@ class SurfaceForcing:
37
38
  ----------
38
39
  grid : Grid
39
40
  Object representing the grid information.
40
- start_time : datetime
41
- Start time of the desired surface forcing data.
42
- end_time : datetime
43
- End time of the desired surface forcing data.
41
+ start_time : datetime, optional
42
+ The start time of the desired surface forcing data. This time is used to filter the dataset
43
+ to include only records on or after this time, with a single record at or before this time.
44
+ If no time filtering is desired, set it to None. Default is None.
45
+ end_time : datetime, optional
46
+ The end time of the desired surface forcing data. This time is used to filter the dataset
47
+ to include only records on or before this time, with a single record at or after this time.
48
+ If no time filtering is desired, set it to None. Default is None.
44
49
  source : Dict[str, Union[str, Path, List[Union[str, Path]]], bool]
45
50
  Dictionary specifying the source of the surface forcing data. Keys include:
46
51
 
@@ -59,9 +64,14 @@ class SurfaceForcing:
59
64
  - "bgc": for biogeochemical forcing.
60
65
 
61
66
  correct_radiation : bool
62
- Whether to correct shortwave radiation. Default is False.
63
- use_coarse_grid: bool
64
- Whether to interpolate to coarsened grid. Default is False.
67
+ Whether to correct shortwave radiation. Default is True.
68
+ coarse_grid_mode : str, optional
69
+ Specifies whether to interpolate onto grid coarsened by a factor of two. Options are:
70
+
71
+ - "auto" (default): Automatically decide based on the comparison of source and target spatial resolutions.
72
+ - "always": Always interpolate onto the coarse grid.
73
+ - "never": Never use the coarse grid; interpolate onto the fine grid instead.
74
+
65
75
  model_reference_date : datetime, optional
66
76
  Reference date for the model. Default is January 1, 2000.
67
77
  use_dask: bool, optional
@@ -84,12 +94,12 @@ class SurfaceForcing:
84
94
  """
85
95
 
86
96
  grid: Grid
87
- start_time: datetime
88
- end_time: datetime
97
+ start_time: Optional[datetime] = None
98
+ end_time: Optional[datetime] = None
89
99
  source: Dict[str, Union[str, Path, List[Union[str, Path]]]]
90
100
  type: str = "physics"
91
- correct_radiation: bool = False
92
- use_coarse_grid: bool = False
101
+ correct_radiation: bool = True
102
+ coarse_grid_mode: str = "auto"
93
103
  model_reference_date: datetime = datetime(2000, 1, 1)
94
104
  use_dask: bool = False
95
105
  bypass_validation: bool = False
@@ -99,14 +109,29 @@ class SurfaceForcing:
99
109
  def __post_init__(self):
100
110
 
101
111
  self._input_checks()
112
+ data = self._get_data()
113
+
114
+ if self.coarse_grid_mode == "always":
115
+ use_coarse_grid = True
116
+ elif self.coarse_grid_mode == "never":
117
+ use_coarse_grid = False
118
+ elif self.coarse_grid_mode == "auto":
119
+ use_coarse_grid = self._determine_coarse_grid_usage(data)
120
+ if use_coarse_grid:
121
+ logging.info("Data will be interpolated onto grid coarsened by factor 2.")
122
+ else:
123
+ logging.info("Data will be interpolated onto fine grid.")
124
+ object.__setattr__(self, "use_coarse_grid", use_coarse_grid)
125
+
102
126
  target_coords = get_target_coords(self.grid, self.use_coarse_grid)
103
127
  object.__setattr__(self, "target_coords", target_coords)
104
128
 
105
- data = self._get_data()
106
129
  data.choose_subdomain(
107
130
  target_coords,
108
131
  buffer_points=20, # lateral fill needs some buffer from data margin
109
132
  )
133
+ # Enforce double precision to ensure reproducibility
134
+ data.convert_to_float64()
110
135
 
111
136
  data.apply_lateral_fill()
112
137
 
@@ -149,6 +174,18 @@ class SurfaceForcing:
149
174
  object.__setattr__(self, "ds", ds)
150
175
 
151
176
  def _input_checks(self):
177
+ # Check that start_time and end_time are both None or none of them is
178
+ if (self.start_time is None) != (self.end_time is None):
179
+ raise ValueError(
180
+ "Both `start_time` and `end_time` must be provided together as datetime objects or both should be None."
181
+ )
182
+
183
+ # Trigger a warning if both are None
184
+ if self.start_time is None and self.end_time is None:
185
+ logging.warning(
186
+ "Both `start_time` and `end_time` are None. No time filtering will be applied to the source data."
187
+ )
188
+
152
189
  # Validate the 'type' parameter
153
190
  if self.type not in ["physics", "bgc"]:
154
191
  raise ValueError("`type` must be either 'physics' or 'bgc'.")
@@ -166,6 +203,47 @@ class SurfaceForcing:
166
203
  {**self.source, "climatology": self.source.get("climatology", False)},
167
204
  )
168
205
 
206
+ # Validate 'coarse_grid_mode'
207
+ valid_modes = ["auto", "always", "never"]
208
+ if self.coarse_grid_mode not in valid_modes:
209
+ raise ValueError(
210
+ f"`coarse_grid_mode` must be one of {valid_modes}, but got '{self.coarse_grid_mode}'."
211
+ )
212
+
213
+ def _determine_coarse_grid_usage(self, data):
214
+ """Determine if coarse grid interpolation should be used based on the resolution
215
+ of the dataset and the target grid.
216
+
217
+ Parameters
218
+ ----------
219
+ data : object
220
+ The dataset object containing the data to be analyzed for grid spacing.
221
+
222
+ Returns
223
+ -------
224
+ use_coarse_grid : bool
225
+ Whether to use the coarse grid or not.
226
+ """
227
+ # Get the target coordinates and select the subdomain of the data
228
+ target_coords = get_target_coords(self.grid, use_coarse_grid=False)
229
+ data_coords = data.choose_subdomain(
230
+ target_coords, buffer_points=1, return_coords_only=True
231
+ )
232
+
233
+ # Compute minimal grid spacing in the data subdomain
234
+ min_grid_spacing_data = data.compute_minimal_grid_spacing(data_coords)
235
+
236
+ # Compute the maximum grid spacing in the ROMS grid
237
+ max_grid_spacing = max((1 / self.grid.ds.pm).max(), (1 / self.grid.ds.pn).max())
238
+
239
+ # Determine whether to use coarse grid based on grid spacing comparison
240
+ if 2 * max_grid_spacing < min_grid_spacing_data:
241
+ use_coarse_grid = True
242
+ else:
243
+ use_coarse_grid = False
244
+
245
+ return use_coarse_grid
246
+
169
247
  def _get_data(self):
170
248
 
171
249
  data_dict = {
@@ -238,14 +316,14 @@ class SurfaceForcing:
238
316
  "qair": {**default_info, "validate": True},
239
317
  "rain": {**default_info, "validate": False},
240
318
  "uwnd": {
241
- "location": "u",
319
+ "location": "rho",
242
320
  "is_vector": True,
243
321
  "vector_pair": "vwnd",
244
322
  "is_3d": False,
245
323
  "validate": True,
246
324
  },
247
325
  "vwnd": {
248
- "location": "v",
326
+ "location": "rho",
249
327
  "is_vector": True,
250
328
  "vector_pair": "uwnd",
251
329
  "is_3d": False,
@@ -266,7 +344,7 @@ class SurfaceForcing:
266
344
  def _apply_correction(self, processed_fields, data):
267
345
 
268
346
  correction_data = self._get_correction_data()
269
- # choose same subdomain as forcing data so that we can use same mask
347
+ # Match subdomain to forcing data to reuse the mask
270
348
  coords_correction = {
271
349
  "lat": data.ds[data.dim_names["latitude"]],
272
350
  "lon": data.ds[data.dim_names["longitude"]],
@@ -275,23 +353,39 @@ class SurfaceForcing:
275
353
  coords_correction, straddle=self.target_coords["straddle"]
276
354
  )
277
355
  correction_data.ds["mask"] = data.ds["mask"] # use mask from ERA5 data
356
+ correction_data.ds["time"] = correction_data.ds["time"].dt.days
357
+
278
358
  correction_data.apply_lateral_fill()
279
- # regrid
280
- lateral_regrid = LateralRegrid(self.target_coords, correction_data.dim_names)
281
- corr_factor = lateral_regrid.apply(
282
- correction_data.ds[correction_data.var_names["swr_corr"]]
283
- )
284
359
 
285
- # temporal interpolation
286
- corr_factor = interpolate_from_climatology(
287
- corr_factor,
288
- correction_data.dim_names["time"],
289
- time=processed_fields["swrad"].time,
290
- )
360
+ # Temporal interpolation: Perform before spatial regridding for better performance
361
+ if self.use_dask:
362
+ # Perform temporal interpolation for each time slice to enforce chunking in time.
363
+ # This reduces memory usage by processing one time step at a time.
364
+ # The interpolated slices are then concatenated along the "time" dimension.
365
+ corr_factor = xr.concat(
366
+ [
367
+ interpolate_from_climatology(
368
+ correction_data.ds[correction_data.var_names["swr_corr"]],
369
+ correction_data.dim_names["time"],
370
+ time=time,
371
+ )
372
+ for time in processed_fields["swrad"].time
373
+ ],
374
+ dim="time",
375
+ )
376
+ else:
377
+ # Interpolate across all time steps at once
378
+ corr_factor = interpolate_from_climatology(
379
+ correction_data.ds[correction_data.var_names["swr_corr"]],
380
+ correction_data.dim_names["time"],
381
+ time=processed_fields["swrad"].time,
382
+ )
291
383
 
292
- processed_fields["swrad"] = processed_fields["swrad"] * corr_factor
384
+ # Spatial regridding
385
+ lateral_regrid = LateralRegrid(self.target_coords, correction_data.dim_names)
386
+ corr_factor = lateral_regrid.apply(corr_factor)
293
387
 
294
- del corr_factor
388
+ processed_fields["swrad"] = processed_fields["swrad"] * corr_factor
295
389
 
296
390
  return processed_fields
297
391
 
@@ -357,12 +451,8 @@ class SurfaceForcing:
357
451
 
358
452
  for var_name in ds.data_vars:
359
453
  if self.variable_info[var_name]["validate"]:
360
- if self.variable_info[var_name]["location"] == "rho":
361
- mask = self.target_coords["mask"]
362
- elif self.variable_info[var_name]["location"] == "u":
363
- mask = self.target_coords["mask_u"]
364
- elif self.variable_info[var_name]["location"] == "v":
365
- mask = self.target_coords["mask_v"]
454
+ # all variables are at rho-points
455
+ mask = self.target_coords["mask"]
366
456
  nan_check(ds[var_name].isel(time=0), mask)
367
457
 
368
458
  def _add_global_metadata(self, ds=None):
@@ -476,42 +566,26 @@ class SurfaceForcing:
476
566
  def save(
477
567
  self,
478
568
  filepath: Union[str, Path],
479
- np_eta: int = None,
480
- np_xi: int = None,
481
- group: bool = False,
569
+ group: bool = True,
482
570
  ) -> None:
483
571
  """Save the surface forcing fields to one or more netCDF4 files.
484
572
 
485
- This method saves the dataset either as a single file or as multiple files depending on the partitioning and grouping options.
486
- The dataset can be saved in two modes:
487
-
488
- 1. **Single File Mode (default)**:
489
- - If both `np_eta` and `np_xi` are `None`, the entire dataset is saved as a single netCDF4 file.
490
- - The file is named based on the `filepath`, with `.nc` automatically appended.
491
-
492
- 2. **Partitioned Mode**:
493
- - If either `np_eta` or `np_xi` is specified, the dataset is partitioned into spatial tiles along the `eta` and `xi` axes.
494
- - Each tile is saved as a separate netCDF4 file, and filenames are modified with an index (e.g., `"filepath_YYYYMM.0.nc"`, `"filepath_YYYYMM.1.nc"`).
495
-
496
- Additionally, if `group` is set to `True`, the dataset is first grouped into temporal subsets, resulting in multiple grouped files before partitioning and saving.
573
+ This method saves the dataset to disk as either a single netCDF4 file or multiple files, depending on the `group` parameter.
574
+ If `group` is `True`, the dataset is divided into subsets (e.g., monthly or yearly) based on the temporal frequency
575
+ of the data, and each subset is saved to a separate file.
497
576
 
498
577
  Parameters
499
578
  ----------
500
579
  filepath : Union[str, Path]
501
- The base path and filename for the output files. The format of the filenames depends on whether partitioning is used
502
- and the temporal range of the data. For partitioned datasets, files will be named with an additional index, e.g.,
503
- `"filepath_YYYYMM.0.nc"`, `"filepath_YYYYMM.1.nc"`, etc.
504
- np_eta : int, optional
505
- The number of partitions along the `eta` direction. If `None`, no spatial partitioning is performed.
506
- np_xi : int, optional
507
- The number of partitions along the `xi` direction. If `None`, no spatial partitioning is performed.
508
- group: bool, optional
509
- If `True`, groups the dataset into multiple files based on temporal data frequency. Defaults to `False`.
580
+ The base path and filename for the output file(s). If `group` is `True`, the filenames will include additional
581
+ time-based information (e.g., year or month) to distinguish the subsets.
582
+ group : bool, optional
583
+ Whether to divide the dataset into multiple files based on temporal frequency. Defaults to `True`.
510
584
 
511
585
  Returns
512
586
  -------
513
587
  List[Path]
514
- A list of Path objects for the filenames that were saved.
588
+ A list of `Path` objects representing the filenames of the saved file(s).
515
589
  """
516
590
 
517
591
  # Ensure filepath is a Path object
@@ -521,12 +595,6 @@ class SurfaceForcing:
521
595
  if filepath.suffix == ".nc":
522
596
  filepath = filepath.with_suffix("")
523
597
 
524
- if self.use_dask:
525
- from dask.diagnostics import ProgressBar
526
-
527
- with ProgressBar():
528
- self.ds.load()
529
-
530
598
  if group:
531
599
  dataset_list, output_filenames = group_dataset(self.ds, str(filepath))
532
600
  else:
@@ -534,7 +602,7 @@ class SurfaceForcing:
534
602
  output_filenames = [str(filepath)]
535
603
 
536
604
  saved_filenames = save_datasets(
537
- dataset_list, output_filenames, np_eta=np_eta, np_xi=np_xi
605
+ dataset_list, output_filenames, use_dask=self.use_dask
538
606
  )
539
607
 
540
608
  return saved_filenames
@@ -556,7 +624,6 @@ class SurfaceForcing:
556
624
  cls,
557
625
  filepath: Union[str, Path],
558
626
  use_dask: bool = False,
559
- bypass_validation: bool = False,
560
627
  ) -> "SurfaceForcing":
561
628
  """Create an instance of the SurfaceForcing class from a YAML file.
562
629
 
@@ -566,10 +633,6 @@ class SurfaceForcing:
566
633
  The path to the YAML file from which the parameters will be read.
567
634
  use_dask: bool, optional
568
635
  Indicates whether to use dask for processing. If True, data is processed with dask; if False, data is processed eagerly. Defaults to False.
569
- bypass_validation: bool, optional
570
- Indicates whether to skip validation checks in the processed data. When set to True,
571
- the validation process that ensures no NaN values exist at wet points
572
- in the processed dataset is bypassed. Defaults to False.
573
636
 
574
637
  Returns
575
638
  -------
@@ -581,6 +644,4 @@ class SurfaceForcing:
581
644
  grid = Grid.from_yaml(filepath)
582
645
  params = _from_yaml(cls, filepath)
583
646
 
584
- return cls(
585
- grid=grid, **params, use_dask=use_dask, bypass_validation=bypass_validation
586
- )
647
+ return cls(grid=grid, **params, use_dask=use_dask)
roms_tools/setup/tides.py CHANGED
@@ -9,6 +9,7 @@ from dataclasses import dataclass, field
9
9
  from roms_tools import Grid
10
10
  from roms_tools.plot import _plot
11
11
  from roms_tools.regrid import LateralRegrid
12
+ from roms_tools.utils import save_datasets
12
13
  from roms_tools.setup.datasets import TPXODataset
13
14
  from roms_tools.setup.utils import (
14
15
  nan_check,
@@ -16,7 +17,6 @@ from roms_tools.setup.utils import (
16
17
  interpolate_from_rho_to_u,
17
18
  interpolate_from_rho_to_v,
18
19
  get_variable_metadata,
19
- save_datasets,
20
20
  get_target_coords,
21
21
  rotate_velocities,
22
22
  get_vector_pairs,
@@ -84,6 +84,9 @@ class TidalForcing:
84
84
  target_coords,
85
85
  buffer_points=20,
86
86
  )
87
+ # Enforce double precision to ensure reproducibility
88
+ data.convert_to_float64()
89
+
87
90
  # select desired number of constituents
88
91
  object.__setattr__(data, "ds", data.ds.isel(ntides=slice(None, self.ntides)))
89
92
  self._correct_tides(data)
@@ -368,36 +371,19 @@ class TidalForcing:
368
371
  kwargs=kwargs,
369
372
  )
370
373
 
371
- def save(
372
- self, filepath: Union[str, Path], np_eta: int = None, np_xi: int = None
373
- ) -> None:
374
+ def save(self, filepath: Union[str, Path]) -> None:
374
375
  """Save the tidal forcing information to a netCDF4 file.
375
376
 
376
- This method supports saving the dataset in two modes:
377
-
378
- 1. **Single File Mode (default)**:
379
-
380
- If both `np_eta` and `np_xi` are `None`, the entire dataset is saved as a single netCDF4 file
381
- with the base filename specified by `filepath.nc`.
382
-
383
- 2. **Partitioned Mode**:
384
-
385
- - If either `np_eta` or `np_xi` is specified, the dataset is divided into spatial tiles along the eta-axis and xi-axis.
386
- - Each spatial tile is saved as a separate netCDF4 file.
387
-
388
377
  Parameters
389
378
  ----------
390
379
  filepath : Union[str, Path]
391
- The base path or filename where the dataset should be saved.
392
- np_eta : int, optional
393
- The number of partitions along the `eta` direction. If `None`, no spatial partitioning is performed.
394
- np_xi : int, optional
395
- The number of partitions along the `xi` direction. If `None`, no spatial partitioning is performed.
380
+ The path or filename where the dataset will be saved. If a directory is specified,
381
+ the file will be saved with a default name within that directory.
396
382
 
397
383
  Returns
398
384
  -------
399
- List[Path]
400
- A list of Path objects for the filenames that were saved.
385
+ Path
386
+ A `Path` object representing the location of the saved file.
401
387
  """
402
388
 
403
389
  # Ensure filepath is a Path object
@@ -407,17 +393,11 @@ class TidalForcing:
407
393
  if filepath.suffix == ".nc":
408
394
  filepath = filepath.with_suffix("")
409
395
 
410
- if self.use_dask:
411
- from dask.diagnostics import ProgressBar
412
-
413
- with ProgressBar():
414
- self.ds.load()
415
-
416
396
  dataset_list = [self.ds]
417
397
  output_filenames = [str(filepath)]
418
398
 
419
399
  saved_filenames = save_datasets(
420
- dataset_list, output_filenames, np_eta=np_eta, np_xi=np_xi
400
+ dataset_list, output_filenames, use_dask=self.use_dask
421
401
  )
422
402
 
423
403
  return saved_filenames
@@ -439,7 +419,6 @@ class TidalForcing:
439
419
  cls,
440
420
  filepath: Union[str, Path],
441
421
  use_dask: bool = False,
442
- bypass_validation: bool = False,
443
422
  ) -> "TidalForcing":
444
423
  """Create an instance of the TidalForcing class from a YAML file.
445
424
 
@@ -449,10 +428,6 @@ class TidalForcing:
449
428
  The path to the YAML file from which the parameters will be read.
450
429
  use_dask: bool, optional
451
430
  Indicates whether to use dask for processing. If True, data is processed with dask; if False, data is processed eagerly. Defaults to False.
452
- bypass_validation: bool, optional
453
- Indicates whether to skip validation checks in the processed data. When set to True,
454
- the validation process that ensures no NaN values exist at wet points
455
- in the processed dataset is bypassed. Defaults to False.
456
431
 
457
432
  Returns
458
433
  -------
@@ -467,7 +442,6 @@ class TidalForcing:
467
442
  grid=grid,
468
443
  **tidal_forcing_params,
469
444
  use_dask=use_dask,
470
- bypass_validation=bypass_validation,
471
445
  )
472
446
 
473
447
  def _correct_tides(self, data):
@@ -145,6 +145,8 @@ def _make_raw_topography(
145
145
  The regridded topography data with the sign flipped (bathymetry positive).
146
146
  """
147
147
  data.choose_subdomain(target_coords, buffer_points=3, verbose=verbose)
148
+ # Enforce double precision to ensure reproducibility
149
+ data.convert_to_float64()
148
150
 
149
151
  if verbose:
150
152
  start_time = time.time()
@@ -233,7 +235,7 @@ def _smooth_topography_locally(h, hmin=5, rmax=0.2):
233
235
  rmax_log = 0.0
234
236
 
235
237
  # Apply hmin threshold
236
- h = xr.where(h < hmin, hmin, h)
238
+ h = _clip_depth(h, hmin)
237
239
 
238
240
  # Perform logarithmic transformation of the height field
239
241
  h_log = np.log(h / hmin)
@@ -316,7 +318,7 @@ def _smooth_topography_locally(h, hmin=5, rmax=0.2):
316
318
  h = hmin * np.exp(h_log)
317
319
 
318
320
  # Apply hmin threshold again
319
- h = xr.where(h < hmin, hmin, h)
321
+ h = _clip_depth(h, hmin)
320
322
 
321
323
  # Compute maximum slope parameter r
322
324
  r_eta, r_xi = _compute_rfactor(h)
@@ -327,6 +329,27 @@ def _smooth_topography_locally(h, hmin=5, rmax=0.2):
327
329
  return h
328
330
 
329
331
 
332
+ def _clip_depth(h: xr.DataArray, hmin: float) -> xr.DataArray:
333
+ """Ensures that depth values do not fall below a minimum threshold.
334
+
335
+ This function replaces all depth values in `h` that are less than `hmin` with `hmin`,
336
+ ensuring a minimum depth constraint.
337
+
338
+ Parameters
339
+ ----------
340
+ h : xr.DataArray
341
+ The depth (bathymetry) array.
342
+ hmin : float
343
+ The minimum allowable depth value.
344
+
345
+ Returns
346
+ -------
347
+ xr.DataArray
348
+ The modified depth array with values clipped at `hmin`.
349
+ """
350
+ return xr.where(h < hmin, hmin, h)
351
+
352
+
330
353
  def _compute_rfactor(h):
331
354
  """Computes the slope parameter (r-factor) in both horizontal directions.
332
355