roms-tools 1.4.2__py3-none-any.whl → 1.6.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.
- roms_tools/_version.py +1 -1
- roms_tools/setup/boundary_forcing.py +448 -130
- roms_tools/setup/datasets.py +186 -52
- roms_tools/setup/fill.py +2 -2
- roms_tools/setup/initial_conditions.py +217 -70
- roms_tools/setup/regrid.py +143 -0
- roms_tools/setup/surface_forcing.py +159 -73
- roms_tools/setup/tides.py +141 -54
- roms_tools/setup/utils.py +229 -62
- roms_tools/tests/test_setup/test_boundary_forcing.py +42 -32
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zmetadata +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zmetadata +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/dust/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/iron/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nhy/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nox/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air_alt/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zmetadata +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/dust/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/iron/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nhy/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nox/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air_alt/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zmetadata +8 -1
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/.zattrs +3 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_north/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/.zattrs +1 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_north/.zattrs +1 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/.zattrs +1 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_west/.zattrs +1 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/.zmetadata +1 -1
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/Tair/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/lwrad/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/qair/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/rain/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/swrad/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/uwnd/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/vwnd/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/.zmetadata +1 -1
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/Tair/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/lwrad/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/qair/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/rain/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/swrad/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/uwnd/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/vwnd/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zmetadata +1 -1
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK_ALT_CO2/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC_ALT_CO2/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOC/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOCr/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DON/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DONr/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOP/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOPr/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Fe/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Lig/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NH4/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NO3/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/O2/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/PO4/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/SiO3/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatC/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatChl/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatFe/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatP/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatSi/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazC/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazChl/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazFe/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazP/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/salt/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spC/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spCaCO3/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spChl/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spFe/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spP/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/temp/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/u/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ubar/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/v/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/vbar/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zeta/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zooC/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/.zmetadata +1 -1
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/Tair/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/lwrad/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/qair/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/rain/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/swrad/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/uwnd/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/vwnd/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/.zmetadata +4 -2
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/omega/.zattrs +3 -1
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/pot_Im/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/pot_Re/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ssh_Im/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ssh_Re/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Im/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Re/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Im/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Re/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_datasets.py +79 -21
- roms_tools/tests/test_setup/test_fill.py +55 -113
- roms_tools/tests/test_setup/test_initial_conditions.py +21 -21
- roms_tools/tests/test_setup/test_regrid.py +53 -0
- roms_tools/tests/test_setup/test_surface_forcing.py +21 -3
- roms_tools/tests/test_setup/test_tides.py +1 -1
- {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/METADATA +13 -4
- {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/RECORD +277 -276
- {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/WHEEL +1 -1
- roms_tools/setup/mixins.py +0 -227
- {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/LICENSE +0 -0
- {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/top_level.txt +0 -0
|
@@ -3,19 +3,24 @@ import numpy as np
|
|
|
3
3
|
import pandas as pd
|
|
4
4
|
import yaml
|
|
5
5
|
import importlib.metadata
|
|
6
|
+
import warnings
|
|
6
7
|
from typing import Dict, Union, List
|
|
7
8
|
from dataclasses import dataclass, field, asdict
|
|
8
9
|
from roms_tools.setup.grid import Grid
|
|
9
|
-
from roms_tools.setup.
|
|
10
|
+
from roms_tools.setup.regrid import LateralRegrid, VerticalRegrid
|
|
10
11
|
from datetime import datetime
|
|
11
12
|
from roms_tools.setup.datasets import GLORYSDataset, CESMBGCDataset
|
|
12
13
|
from roms_tools.setup.utils import (
|
|
13
|
-
nan_check,
|
|
14
|
-
substitute_nans_by_fillvalue,
|
|
15
14
|
get_variable_metadata,
|
|
16
|
-
get_boundary_info,
|
|
17
15
|
group_dataset,
|
|
18
16
|
save_datasets,
|
|
17
|
+
get_target_coords,
|
|
18
|
+
rotate_velocities,
|
|
19
|
+
compute_barotropic_velocity,
|
|
20
|
+
transpose_dimensions,
|
|
21
|
+
one_dim_fill,
|
|
22
|
+
nan_check,
|
|
23
|
+
substitute_nans_by_fillvalue,
|
|
19
24
|
)
|
|
20
25
|
from roms_tools.setup.plot import _section_plot, _line_plot
|
|
21
26
|
import matplotlib.pyplot as plt
|
|
@@ -23,7 +28,7 @@ from pathlib import Path
|
|
|
23
28
|
|
|
24
29
|
|
|
25
30
|
@dataclass(frozen=True, kw_only=True)
|
|
26
|
-
class BoundaryForcing
|
|
31
|
+
class BoundaryForcing:
|
|
27
32
|
"""Represents boundary forcing input data for ROMS.
|
|
28
33
|
|
|
29
34
|
Parameters
|
|
@@ -55,6 +60,10 @@ class BoundaryForcing(ROMSToolsMixins):
|
|
|
55
60
|
|
|
56
61
|
model_reference_date : datetime, optional
|
|
57
62
|
Reference date for the model. Default is January 1, 2000.
|
|
63
|
+
apply_2d_horizontal_fill: bool, optional
|
|
64
|
+
Indicates whether to perform a two-dimensional horizontal fill on the source data prior to regridding to boundaries.
|
|
65
|
+
If `False`, a one-dimensional horizontal fill is performed separately on each of the four regridded boundaries.
|
|
66
|
+
Defaults to `False`.
|
|
58
67
|
use_dask: bool, optional
|
|
59
68
|
Indicates whether to use dask for processing. If True, data is processed with dask; if False, data is processed eagerly. Defaults to False.
|
|
60
69
|
|
|
@@ -84,6 +93,7 @@ class BoundaryForcing(ROMSToolsMixins):
|
|
|
84
93
|
source: Dict[str, Union[str, Path, List[Union[str, Path]]]]
|
|
85
94
|
type: str = "physics"
|
|
86
95
|
model_reference_date: datetime = datetime(2000, 1, 1)
|
|
96
|
+
apply_2d_horizontal_fill: bool = False
|
|
87
97
|
use_dask: bool = False
|
|
88
98
|
|
|
89
99
|
ds: xr.Dataset = field(init=False, repr=False)
|
|
@@ -91,52 +101,153 @@ class BoundaryForcing(ROMSToolsMixins):
|
|
|
91
101
|
def __post_init__(self):
|
|
92
102
|
|
|
93
103
|
self._input_checks()
|
|
94
|
-
|
|
104
|
+
target_coords = get_target_coords(self.grid)
|
|
95
105
|
|
|
96
106
|
data = self._get_data()
|
|
97
|
-
data.choose_subdomain(
|
|
98
|
-
latitude_range=[lat.min().values, lat.max().values],
|
|
99
|
-
longitude_range=[lon.min().values, lon.max().values],
|
|
100
|
-
margin=2,
|
|
101
|
-
straddle=straddle,
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
if self.type == "physics":
|
|
105
|
-
vars_2d = ["zeta"]
|
|
106
|
-
vars_3d = ["temp", "salt", "u", "v"]
|
|
107
|
-
elif self.type == "bgc":
|
|
108
|
-
vars_2d = []
|
|
109
|
-
vars_3d = data.var_names.keys()
|
|
110
|
-
|
|
111
|
-
data_vars = super()._regrid_data(data, vars_2d, vars_3d, lon, lat)
|
|
112
107
|
|
|
113
|
-
if self.
|
|
114
|
-
|
|
115
|
-
|
|
108
|
+
if self.apply_2d_horizontal_fill:
|
|
109
|
+
data.choose_subdomain(
|
|
110
|
+
target_coords,
|
|
111
|
+
buffer_points=20, # lateral fill needs good buffer from data margin
|
|
112
|
+
)
|
|
113
|
+
data.extrapolate_deepest_to_bottom()
|
|
114
|
+
data.apply_lateral_fill()
|
|
116
115
|
|
|
117
|
-
|
|
116
|
+
variable_info = self._set_variable_info(data)
|
|
118
117
|
bdry_coords = get_boundary_info()
|
|
118
|
+
ds = xr.Dataset()
|
|
119
119
|
|
|
120
|
-
ds = self._write_into_dataset(data, d_meta, bdry_coords)
|
|
121
|
-
|
|
122
|
-
# NaN values at wet points indicate that the raw data did not cover the domain, and the following will raise a ValueError
|
|
123
|
-
# this check works only for 2D fields because for 3D I extrapolate to bottom which eliminates NaNs
|
|
124
120
|
for direction in ["south", "east", "north", "west"]:
|
|
125
121
|
if self.boundaries[direction]:
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
122
|
+
|
|
123
|
+
bdry_target_coords = {
|
|
124
|
+
"lat": target_coords["lat"].isel(
|
|
125
|
+
**bdry_coords["vector"][direction]
|
|
126
|
+
),
|
|
127
|
+
"lon": target_coords["lon"].isel(
|
|
128
|
+
**bdry_coords["vector"][direction]
|
|
129
|
+
),
|
|
130
|
+
"straddle": target_coords["straddle"],
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
bdry_data = data.choose_subdomain(
|
|
134
|
+
bdry_target_coords,
|
|
135
|
+
buffer_points=3,
|
|
136
|
+
return_copy=True,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
if not self.apply_2d_horizontal_fill:
|
|
140
|
+
bdry_data.extrapolate_deepest_to_bottom()
|
|
141
|
+
|
|
142
|
+
processed_fields = {}
|
|
143
|
+
|
|
144
|
+
# lateral regridding of vector fields
|
|
145
|
+
vector_var_names = [
|
|
146
|
+
name for name, info in variable_info.items() if info["is_vector"]
|
|
147
|
+
]
|
|
148
|
+
if len(vector_var_names) > 0:
|
|
149
|
+
lon = target_coords["lon"].isel(**bdry_coords["vector"][direction])
|
|
150
|
+
lat = target_coords["lat"].isel(**bdry_coords["vector"][direction])
|
|
151
|
+
lateral_regrid = LateralRegrid(
|
|
152
|
+
{"lat": lat, "lon": lon}, bdry_data.dim_names
|
|
153
|
+
)
|
|
154
|
+
for var_name in vector_var_names:
|
|
155
|
+
if var_name in bdry_data.var_names.keys():
|
|
156
|
+
processed_fields[var_name] = lateral_regrid.apply(
|
|
157
|
+
bdry_data.ds[bdry_data.var_names[var_name]]
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# lateral regridding of tracer fields
|
|
161
|
+
tracer_var_names = [
|
|
162
|
+
name
|
|
163
|
+
for name, info in variable_info.items()
|
|
164
|
+
if not info["is_vector"]
|
|
165
|
+
]
|
|
166
|
+
if len(tracer_var_names) > 0:
|
|
167
|
+
lon = target_coords["lon"].isel(**bdry_coords["rho"][direction])
|
|
168
|
+
lat = target_coords["lat"].isel(**bdry_coords["rho"][direction])
|
|
169
|
+
lateral_regrid = LateralRegrid(
|
|
170
|
+
{"lat": lat, "lon": lon}, bdry_data.dim_names
|
|
171
|
+
)
|
|
172
|
+
for var_name in tracer_var_names:
|
|
173
|
+
if var_name in bdry_data.var_names.keys():
|
|
174
|
+
processed_fields[var_name] = lateral_regrid.apply(
|
|
175
|
+
bdry_data.ds[bdry_data.var_names[var_name]]
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
# rotation of velocities and interpolation to u/v points
|
|
179
|
+
if "u" in variable_info and "v" in variable_info:
|
|
180
|
+
angle = target_coords["angle"].isel(
|
|
181
|
+
**bdry_coords["vector"][direction]
|
|
130
182
|
)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
183
|
+
(processed_fields["u"], processed_fields["v"],) = rotate_velocities(
|
|
184
|
+
processed_fields["u"],
|
|
185
|
+
processed_fields["v"],
|
|
186
|
+
angle,
|
|
187
|
+
interpolate=True,
|
|
135
188
|
)
|
|
136
189
|
|
|
190
|
+
# selection of outermost margin for u/v variables
|
|
191
|
+
for var_name in variable_info.keys():
|
|
192
|
+
if var_name in processed_fields:
|
|
193
|
+
location = variable_info[var_name]["location"]
|
|
194
|
+
if location in ["u", "v"]:
|
|
195
|
+
processed_fields[var_name] = processed_fields[
|
|
196
|
+
var_name
|
|
197
|
+
].isel(**bdry_coords[location][direction])
|
|
198
|
+
|
|
199
|
+
if not self.apply_2d_horizontal_fill:
|
|
200
|
+
processed_fields = apply_1d_horizontal_fill(processed_fields)
|
|
201
|
+
|
|
202
|
+
# vertical regridding
|
|
203
|
+
for location in ["rho", "u", "v"]:
|
|
204
|
+
var_names = [
|
|
205
|
+
name
|
|
206
|
+
for name, info in variable_info.items()
|
|
207
|
+
if info["location"] == location and info["is_3d"]
|
|
208
|
+
]
|
|
209
|
+
if len(var_names) > 0:
|
|
210
|
+
vertical_regrid = VerticalRegrid(
|
|
211
|
+
self.grid.ds[f"layer_depth_{location}"].isel(
|
|
212
|
+
**bdry_coords[location][direction]
|
|
213
|
+
),
|
|
214
|
+
bdry_data.ds[bdry_data.dim_names["depth"]],
|
|
215
|
+
)
|
|
216
|
+
for var_name in var_names:
|
|
217
|
+
if var_name in processed_fields:
|
|
218
|
+
processed_fields[var_name] = vertical_regrid.apply(
|
|
219
|
+
processed_fields[var_name]
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# compute barotropic velocities
|
|
223
|
+
if "u" in variable_info and "v" in variable_info:
|
|
224
|
+
for var_name in ["u", "v"]:
|
|
225
|
+
processed_fields[
|
|
226
|
+
f"{var_name}bar"
|
|
227
|
+
] = compute_barotropic_velocity(
|
|
228
|
+
processed_fields[var_name],
|
|
229
|
+
self.grid.ds[f"interface_depth_{var_name}"].isel(
|
|
230
|
+
**bdry_coords[var_name][direction]
|
|
231
|
+
),
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# Reorder dimensions
|
|
235
|
+
for var_name in processed_fields.keys():
|
|
236
|
+
processed_fields[var_name] = transpose_dimensions(
|
|
237
|
+
processed_fields[var_name]
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
# Write the boundary data into dataset
|
|
241
|
+
ds = self._write_into_dataset(direction, processed_fields, ds)
|
|
242
|
+
|
|
243
|
+
# Add global information
|
|
244
|
+
ds = self._add_global_metadata(data, ds)
|
|
245
|
+
|
|
246
|
+
self._validate(ds, variable_info, bdry_coords)
|
|
247
|
+
|
|
137
248
|
# substitute NaNs over land by a fill value to avoid blow-up of ROMS
|
|
138
|
-
for
|
|
139
|
-
ds[
|
|
249
|
+
for var_name in ds.data_vars:
|
|
250
|
+
ds[var_name] = substitute_nans_by_fillvalue(ds[var_name])
|
|
140
251
|
|
|
141
252
|
object.__setattr__(self, "ds", ds)
|
|
142
253
|
|
|
@@ -187,37 +298,88 @@ class BoundaryForcing(ROMSToolsMixins):
|
|
|
187
298
|
|
|
188
299
|
return data
|
|
189
300
|
|
|
190
|
-
def
|
|
301
|
+
def _set_variable_info(self, data):
|
|
302
|
+
"""Sets up a dictionary with metadata for variables based on the type of data
|
|
303
|
+
(physics or BGC).
|
|
191
304
|
|
|
192
|
-
|
|
193
|
-
|
|
305
|
+
The dictionary contains the following information:
|
|
306
|
+
- `location`: Where the variable resides in the grid (e.g., rho, u, or v points).
|
|
307
|
+
- `is_vector`: Whether the variable is part of a vector (True for velocity components like 'u' and 'v').
|
|
308
|
+
- `vector_pair`: For vector variables, this indicates the associated variable that forms the vector (e.g., 'u' and 'v').
|
|
309
|
+
- `is_3d`: Indicates whether the variable is 3D (True for variables like 'temp' and 'salt') or 2D (False for 'zeta').
|
|
194
310
|
|
|
195
|
-
|
|
196
|
-
|
|
311
|
+
Returns
|
|
312
|
+
-------
|
|
313
|
+
dict
|
|
314
|
+
A dictionary where the keys are variable names and the values are dictionaries of metadata
|
|
315
|
+
about each variable, including 'location', 'is_vector', 'vector_pair', and 'is_3d'.
|
|
316
|
+
"""
|
|
317
|
+
default_info = {
|
|
318
|
+
"location": "rho",
|
|
319
|
+
"is_vector": False,
|
|
320
|
+
"vector_pair": None,
|
|
321
|
+
"is_3d": True,
|
|
322
|
+
}
|
|
197
323
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
324
|
+
# Define a dictionary for variable names and their associated information
|
|
325
|
+
if self.type == "physics":
|
|
326
|
+
variable_info = {
|
|
327
|
+
"zeta": {
|
|
328
|
+
"location": "rho",
|
|
329
|
+
"is_vector": False,
|
|
330
|
+
"vector_pair": None,
|
|
331
|
+
"is_3d": False,
|
|
332
|
+
},
|
|
333
|
+
"temp": default_info,
|
|
334
|
+
"salt": default_info,
|
|
335
|
+
"u": {
|
|
336
|
+
"location": "u",
|
|
337
|
+
"is_vector": True,
|
|
338
|
+
"vector_pair": "v",
|
|
339
|
+
"is_3d": True,
|
|
340
|
+
},
|
|
341
|
+
"v": {
|
|
342
|
+
"location": "v",
|
|
343
|
+
"is_vector": True,
|
|
344
|
+
"vector_pair": "u",
|
|
345
|
+
"is_3d": True,
|
|
346
|
+
},
|
|
347
|
+
"ubar": {
|
|
348
|
+
"location": "u",
|
|
349
|
+
"is_vector": True,
|
|
350
|
+
"vector_pair": "vbar",
|
|
351
|
+
"is_3d": False,
|
|
352
|
+
},
|
|
353
|
+
"vbar": {
|
|
354
|
+
"location": "v",
|
|
355
|
+
"is_vector": True,
|
|
356
|
+
"vector_pair": "ubar",
|
|
357
|
+
"is_3d": False,
|
|
358
|
+
},
|
|
359
|
+
}
|
|
360
|
+
elif self.type == "bgc":
|
|
361
|
+
variable_info = {}
|
|
362
|
+
for var_name in data.var_names.keys():
|
|
363
|
+
variable_info[var_name] = default_info
|
|
364
|
+
|
|
365
|
+
return variable_info
|
|
366
|
+
|
|
367
|
+
def _write_into_dataset(self, direction, processed_fields, ds=None):
|
|
368
|
+
if ds is None:
|
|
369
|
+
ds = xr.Dataset()
|
|
370
|
+
|
|
371
|
+
d_meta = get_variable_metadata()
|
|
372
|
+
|
|
373
|
+
for var_name in processed_fields.keys():
|
|
374
|
+
ds[f"{var_name}_{direction}"] = processed_fields[var_name].astype(
|
|
375
|
+
np.float32
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
ds[f"{var_name}_{direction}"].attrs[
|
|
379
|
+
"long_name"
|
|
380
|
+
] = f"{direction}ern boundary {d_meta[var_name]['long_name']}"
|
|
381
|
+
|
|
382
|
+
ds[f"{var_name}_{direction}"].attrs["units"] = d_meta[var_name]["units"]
|
|
221
383
|
|
|
222
384
|
# Gracefully handle dropping variables that might not be present
|
|
223
385
|
variables_to_drop = [
|
|
@@ -235,59 +397,9 @@ class BoundaryForcing(ROMSToolsMixins):
|
|
|
235
397
|
"lat_v",
|
|
236
398
|
"lon_v",
|
|
237
399
|
]
|
|
238
|
-
existing_vars = [
|
|
400
|
+
existing_vars = [var_name for var_name in variables_to_drop if var_name in ds]
|
|
239
401
|
ds = ds.drop_vars(existing_vars)
|
|
240
402
|
|
|
241
|
-
ds = self._add_global_metadata(ds)
|
|
242
|
-
|
|
243
|
-
# Convert the time coordinate to the format expected by ROMS
|
|
244
|
-
if data.climatology:
|
|
245
|
-
ds.attrs["climatology"] = str(True)
|
|
246
|
-
# Preserve absolute time coordinate for readability
|
|
247
|
-
ds = ds.assign_coords(
|
|
248
|
-
{"abs_time": np.datetime64(self.model_reference_date) + ds["time"]}
|
|
249
|
-
)
|
|
250
|
-
# Convert to pandas TimedeltaIndex
|
|
251
|
-
timedelta_index = pd.to_timedelta(ds["time"].values)
|
|
252
|
-
|
|
253
|
-
# Determine the start of the year for the base_datetime
|
|
254
|
-
start_of_year = datetime(self.model_reference_date.year, 1, 1)
|
|
255
|
-
|
|
256
|
-
# Calculate the offset from midnight of the new year
|
|
257
|
-
offset = self.model_reference_date - start_of_year
|
|
258
|
-
|
|
259
|
-
# Convert the timedelta to nanoseconds first, then to days
|
|
260
|
-
bry_time = xr.DataArray(
|
|
261
|
-
(timedelta_index - offset).view("int64") / 3600 / 24 * 1e-9,
|
|
262
|
-
dims="time",
|
|
263
|
-
)
|
|
264
|
-
|
|
265
|
-
else:
|
|
266
|
-
# Preserve absolute time coordinate for readability
|
|
267
|
-
ds = ds.assign_coords({"abs_time": ds["time"]})
|
|
268
|
-
# TODO: Check if we need to convert from 12:00:00 to 00:00:00 as in matlab scripts
|
|
269
|
-
bry_time = (
|
|
270
|
-
(ds["time"] - np.datetime64(self.model_reference_date)).astype(
|
|
271
|
-
"float64"
|
|
272
|
-
)
|
|
273
|
-
/ 3600
|
|
274
|
-
/ 24
|
|
275
|
-
* 1e-9
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
ds = ds.assign_coords({"bry_time": bry_time})
|
|
279
|
-
ds["bry_time"].attrs[
|
|
280
|
-
"long_name"
|
|
281
|
-
] = f"days since {str(self.model_reference_date)}"
|
|
282
|
-
ds["bry_time"].encoding["units"] = "days"
|
|
283
|
-
ds["bry_time"].attrs["units"] = "days"
|
|
284
|
-
ds = ds.swap_dims({"time": "bry_time"})
|
|
285
|
-
ds = ds.drop_vars("time")
|
|
286
|
-
ds.encoding["unlimited_dims"] = "bry_time"
|
|
287
|
-
|
|
288
|
-
if data.climatology:
|
|
289
|
-
ds["bry_time"].attrs["cycle_length"] = 365.25
|
|
290
|
-
|
|
291
403
|
return ds
|
|
292
404
|
|
|
293
405
|
def _get_coordinates(self, direction, point):
|
|
@@ -325,7 +437,7 @@ class BoundaryForcing(ROMSToolsMixins):
|
|
|
325
437
|
|
|
326
438
|
return layer_depth, interface_depth
|
|
327
439
|
|
|
328
|
-
def _add_global_metadata(self, ds=None):
|
|
440
|
+
def _add_global_metadata(self, data, ds=None):
|
|
329
441
|
|
|
330
442
|
if ds is None:
|
|
331
443
|
ds = xr.Dataset()
|
|
@@ -345,11 +457,125 @@ class BoundaryForcing(ROMSToolsMixins):
|
|
|
345
457
|
ds.attrs["theta_b"] = self.grid.ds.attrs["theta_b"]
|
|
346
458
|
ds.attrs["hc"] = self.grid.ds.attrs["hc"]
|
|
347
459
|
|
|
460
|
+
# Convert the time coordinate to the format expected by ROMS
|
|
461
|
+
if data.climatology:
|
|
462
|
+
ds.attrs["climatology"] = str(True)
|
|
463
|
+
# Preserve absolute time coordinate for readability
|
|
464
|
+
ds = ds.assign_coords(
|
|
465
|
+
{"abs_time": np.datetime64(self.model_reference_date) + ds["time"]}
|
|
466
|
+
)
|
|
467
|
+
# Convert to pandas TimedeltaIndex
|
|
468
|
+
timedelta_index = pd.to_timedelta(ds["time"].values)
|
|
469
|
+
|
|
470
|
+
# Determine the start of the year for the base_datetime
|
|
471
|
+
start_of_year = datetime(self.model_reference_date.year, 1, 1)
|
|
472
|
+
|
|
473
|
+
# Calculate the offset from midnight of the new year
|
|
474
|
+
offset = self.model_reference_date - start_of_year
|
|
475
|
+
|
|
476
|
+
# Convert the timedelta to nanoseconds first, then to days
|
|
477
|
+
bry_time = xr.DataArray(
|
|
478
|
+
(timedelta_index - offset).view("int64") / 3600 / 24 * 1e-9,
|
|
479
|
+
dims="time",
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
else:
|
|
483
|
+
# Preserve absolute time coordinate for readability
|
|
484
|
+
ds = ds.assign_coords({"abs_time": ds["time"]})
|
|
485
|
+
bry_time = (
|
|
486
|
+
(ds["time"] - np.datetime64(self.model_reference_date)).astype(
|
|
487
|
+
"float64"
|
|
488
|
+
)
|
|
489
|
+
/ 3600
|
|
490
|
+
/ 24
|
|
491
|
+
* 1e-9
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
ds = ds.assign_coords({"bry_time": bry_time})
|
|
495
|
+
ds["bry_time"].attrs[
|
|
496
|
+
"long_name"
|
|
497
|
+
] = f"days since {str(self.model_reference_date)}"
|
|
498
|
+
ds["bry_time"].encoding["units"] = "days"
|
|
499
|
+
ds["bry_time"].attrs["units"] = "days"
|
|
500
|
+
ds = ds.swap_dims({"time": "bry_time"})
|
|
501
|
+
ds = ds.drop_vars("time")
|
|
502
|
+
ds.encoding["unlimited_dims"] = "bry_time"
|
|
503
|
+
|
|
504
|
+
if data.climatology:
|
|
505
|
+
ds["bry_time"].attrs["cycle_length"] = 365.25
|
|
506
|
+
|
|
348
507
|
return ds
|
|
349
508
|
|
|
509
|
+
def _validate(self, ds, variable_info, bdry_coords):
|
|
510
|
+
"""Validate the dataset for NaN values at the first time step based on the fill
|
|
511
|
+
method used.
|
|
512
|
+
|
|
513
|
+
Parameters
|
|
514
|
+
----------
|
|
515
|
+
ds : xarray.Dataset
|
|
516
|
+
The dataset to validate.
|
|
517
|
+
|
|
518
|
+
variable_info : dict
|
|
519
|
+
A dictionary containing metadata about the variables, including their locations (e.g., 'rho', 'u', 'v').
|
|
520
|
+
|
|
521
|
+
bdry_coords : dict
|
|
522
|
+
A dictionary containing the boundary coordinates for each variable location.
|
|
523
|
+
|
|
524
|
+
Raises
|
|
525
|
+
------
|
|
526
|
+
ValueError
|
|
527
|
+
If NaN values are found in any of the specified variables at wet points,
|
|
528
|
+
indicating incomplete data coverage.
|
|
529
|
+
|
|
530
|
+
Notes
|
|
531
|
+
-----
|
|
532
|
+
Validation is performed on the initial boundary time step (`bry_time=0`) for each
|
|
533
|
+
variable in the dataset. If the `apply_2d_horizontal_fill` attribute is set to False,
|
|
534
|
+
a warning is issued instead of a strict NaN check, as the data may not be reliably validated.
|
|
535
|
+
Conversely, if `apply_2d_horizontal_fill` is True, a strict NaN check is performed, raising
|
|
536
|
+
a ValueError if any NaN values are detected.
|
|
537
|
+
"""
|
|
538
|
+
if self.apply_2d_horizontal_fill:
|
|
539
|
+
# Strict NaN check with ValueError makes sense to be applied
|
|
540
|
+
for var_name in variable_info:
|
|
541
|
+
location = variable_info[var_name]["location"]
|
|
542
|
+
|
|
543
|
+
# Select the appropriate mask based on variable location
|
|
544
|
+
if location == "rho":
|
|
545
|
+
mask = self.grid.ds.mask_rho
|
|
546
|
+
elif location == "u":
|
|
547
|
+
mask = self.grid.ds.mask_u
|
|
548
|
+
elif location == "v":
|
|
549
|
+
mask = self.grid.ds.mask_v
|
|
550
|
+
else:
|
|
551
|
+
continue # Skip if location is not recognized
|
|
552
|
+
|
|
553
|
+
for direction in ["south", "east", "north", "west"]:
|
|
554
|
+
if self.boundaries[direction]:
|
|
555
|
+
bdry_var_name = f"{var_name}_{direction}"
|
|
556
|
+
|
|
557
|
+
# Check for NaN values at the first time step using the nan_check function
|
|
558
|
+
nan_check(
|
|
559
|
+
ds[bdry_var_name].isel(bry_time=0),
|
|
560
|
+
mask.isel(**bdry_coords[location][direction]),
|
|
561
|
+
)
|
|
562
|
+
else:
|
|
563
|
+
# Can't apply strict NaN check because land values haven't been filled before regridding step; instead warn user
|
|
564
|
+
for direction in ["south", "east", "north", "west"]:
|
|
565
|
+
if self.boundaries[direction]:
|
|
566
|
+
for var_name in variable_info:
|
|
567
|
+
bdry_var_name = f"{var_name}_{direction}"
|
|
568
|
+
if ds[bdry_var_name].isel(bry_time=0).isnull().any().values:
|
|
569
|
+
warnings.warn(
|
|
570
|
+
f"NaN values detected in regridded variables along the {direction}ern boundary. This may indicate that the entire boundary is on land in the source data, or that the source data does not cover this boundary.",
|
|
571
|
+
UserWarning,
|
|
572
|
+
)
|
|
573
|
+
# Break after the first warning for this direction to avoid duplicates
|
|
574
|
+
break
|
|
575
|
+
|
|
350
576
|
def plot(
|
|
351
577
|
self,
|
|
352
|
-
|
|
578
|
+
var_name,
|
|
353
579
|
time=0,
|
|
354
580
|
layer_contours=False,
|
|
355
581
|
) -> None:
|
|
@@ -357,7 +583,7 @@ class BoundaryForcing(ROMSToolsMixins):
|
|
|
357
583
|
|
|
358
584
|
Parameters
|
|
359
585
|
----------
|
|
360
|
-
|
|
586
|
+
var_name : str
|
|
361
587
|
The name of the boundary forcing field to plot. Options include:
|
|
362
588
|
|
|
363
589
|
- "temp_{direction}": Potential temperature,
|
|
@@ -417,37 +643,37 @@ class BoundaryForcing(ROMSToolsMixins):
|
|
|
417
643
|
Raises
|
|
418
644
|
------
|
|
419
645
|
ValueError
|
|
420
|
-
If the specified
|
|
646
|
+
If the specified var_name is not one of the valid options.
|
|
421
647
|
"""
|
|
422
648
|
|
|
423
|
-
if
|
|
424
|
-
raise ValueError(f"Variable '{
|
|
649
|
+
if var_name not in self.ds:
|
|
650
|
+
raise ValueError(f"Variable '{var_name}' is not found in dataset.")
|
|
425
651
|
|
|
426
|
-
field = self.ds[
|
|
652
|
+
field = self.ds[var_name].isel(bry_time=time).load()
|
|
427
653
|
title = field.long_name
|
|
428
654
|
|
|
429
655
|
if "s_rho" in field.dims:
|
|
430
|
-
if
|
|
656
|
+
if var_name.startswith(("u_", "ubar_")):
|
|
431
657
|
point = "u"
|
|
432
|
-
elif
|
|
658
|
+
elif var_name.startswith(("v_", "vbar_")):
|
|
433
659
|
point = "v"
|
|
434
660
|
else:
|
|
435
661
|
point = "rho"
|
|
436
|
-
direction =
|
|
662
|
+
direction = var_name.split("_")[-1]
|
|
437
663
|
|
|
438
664
|
layer_depth, interface_depth = self._get_coordinates(direction, point)
|
|
439
665
|
|
|
440
666
|
field = field.assign_coords({"layer_depth": layer_depth})
|
|
441
667
|
|
|
442
668
|
# chose colorbar
|
|
443
|
-
if
|
|
669
|
+
if var_name.startswith(("u", "v", "ubar", "vbar", "zeta")):
|
|
444
670
|
vmax = max(field.max().values, -field.min().values)
|
|
445
671
|
vmin = -vmax
|
|
446
672
|
cmap = plt.colormaps.get_cmap("RdBu_r")
|
|
447
673
|
else:
|
|
448
674
|
vmax = field.max().values
|
|
449
675
|
vmin = field.min().values
|
|
450
|
-
if
|
|
676
|
+
if var_name.startswith(("temp", "salt")):
|
|
451
677
|
cmap = plt.colormaps.get_cmap("YlOrRd")
|
|
452
678
|
else:
|
|
453
679
|
cmap = plt.colormaps.get_cmap("YlGn")
|
|
@@ -621,3 +847,95 @@ class BoundaryForcing(ROMSToolsMixins):
|
|
|
621
847
|
|
|
622
848
|
# Create and return an instance of InitialConditions
|
|
623
849
|
return cls(grid=grid, **boundary_forcing_data, use_dask=use_dask)
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
def get_boundary_info():
|
|
853
|
+
"""This function provides information about the boundary points for the rho, u, and
|
|
854
|
+
v variables on the grid, specifying the indices for the south, east, north, and west
|
|
855
|
+
boundaries.
|
|
856
|
+
|
|
857
|
+
Returns
|
|
858
|
+
-------
|
|
859
|
+
dict
|
|
860
|
+
A dictionary where keys are variable types ("rho", "u", "v"), and values
|
|
861
|
+
are nested dictionaries mapping directions ("south", "east", "north", "west")
|
|
862
|
+
to the corresponding boundary coordinates.
|
|
863
|
+
"""
|
|
864
|
+
|
|
865
|
+
# Boundary coordinates
|
|
866
|
+
bdry_coords = {
|
|
867
|
+
"rho": {
|
|
868
|
+
"south": {"eta_rho": 0},
|
|
869
|
+
"east": {"xi_rho": -1},
|
|
870
|
+
"north": {"eta_rho": -1},
|
|
871
|
+
"west": {"xi_rho": 0},
|
|
872
|
+
},
|
|
873
|
+
"u": {
|
|
874
|
+
"south": {"eta_rho": 0},
|
|
875
|
+
"east": {"xi_u": -1},
|
|
876
|
+
"north": {"eta_rho": -1},
|
|
877
|
+
"west": {"xi_u": 0},
|
|
878
|
+
},
|
|
879
|
+
"v": {
|
|
880
|
+
"south": {"eta_v": 0},
|
|
881
|
+
"east": {"xi_rho": -1},
|
|
882
|
+
"north": {"eta_v": -1},
|
|
883
|
+
"west": {"xi_rho": 0},
|
|
884
|
+
},
|
|
885
|
+
"vector": {
|
|
886
|
+
"south": {"eta_rho": [0, 1]},
|
|
887
|
+
"east": {"xi_rho": [-2, -1]},
|
|
888
|
+
"north": {"eta_rho": [-2, -1]},
|
|
889
|
+
"west": {"xi_rho": [0, 1]},
|
|
890
|
+
},
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
return bdry_coords
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
def apply_1d_horizontal_fill(processed_fields: dict) -> dict:
|
|
897
|
+
"""Forward and backward fill NaN values in horizontal direction for open boundaries.
|
|
898
|
+
|
|
899
|
+
Parameters
|
|
900
|
+
----------
|
|
901
|
+
processed_fields : dict
|
|
902
|
+
A dictionary of variables to be updated, where each value is an
|
|
903
|
+
`xarray.DataArray`.
|
|
904
|
+
|
|
905
|
+
Returns
|
|
906
|
+
-------
|
|
907
|
+
dict of str : xarray.DataArray
|
|
908
|
+
The updated dictionary of variables, with NaN values filled.
|
|
909
|
+
|
|
910
|
+
Raises
|
|
911
|
+
------
|
|
912
|
+
ValueError
|
|
913
|
+
If more than one horizontal dimension is found or none at all.
|
|
914
|
+
"""
|
|
915
|
+
|
|
916
|
+
horizontal_dims = ["eta_rho", "eta_v", "xi_rho", "xi_u"]
|
|
917
|
+
|
|
918
|
+
for var_name in processed_fields.keys():
|
|
919
|
+
selected_horizontal_dim = None
|
|
920
|
+
# Determine the horizontal dimension to fill
|
|
921
|
+
for dim in horizontal_dims:
|
|
922
|
+
if dim in processed_fields[var_name].dims:
|
|
923
|
+
if selected_horizontal_dim is not None:
|
|
924
|
+
raise ValueError(
|
|
925
|
+
f"More than one horizontal dimension found in variable '{var_name}'."
|
|
926
|
+
)
|
|
927
|
+
selected_horizontal_dim = dim
|
|
928
|
+
|
|
929
|
+
if selected_horizontal_dim is None:
|
|
930
|
+
raise ValueError(
|
|
931
|
+
f"No valid horizontal dimension found for variable '{var_name}'."
|
|
932
|
+
)
|
|
933
|
+
# Forward and backward fill in the horizontal direction
|
|
934
|
+
filled = one_dim_fill(
|
|
935
|
+
processed_fields[var_name], selected_horizontal_dim, direction="forward"
|
|
936
|
+
)
|
|
937
|
+
processed_fields[var_name] = one_dim_fill(
|
|
938
|
+
filled, selected_horizontal_dim, direction="backward"
|
|
939
|
+
)
|
|
940
|
+
|
|
941
|
+
return processed_fields
|