From 2c85a1c96b7474c273c6762dbd26abaf1bcfba26 Mon Sep 17 00:00:00 2001 From: Xylar Asay-Davis Date: Wed, 3 Jan 2024 05:32:33 -0600 Subject: [PATCH 1/7] Update to SOwISC12to30E3r3 Switch SO12to60 to SO12to30 with a base resolution that is now uniformly 30 km. --- compass/ocean/suites/so12to30.txt | 5 + compass/ocean/suites/so12to60.txt | 5 - compass/ocean/suites/sowisc12to30.txt | 5 + compass/ocean/suites/sowisc12to60.txt | 5 - compass/ocean/tests/global_ocean/__init__.py | 2 +- .../ocean/tests/global_ocean/mesh/__init__.py | 6 +- .../global_ocean/mesh/so12to30/__init__.py | 70 +++++++++++ .../dynamic_adjustment.yaml | 0 .../high_res_region.geojson | 2 +- .../namelist.split_explicit_ab2 | 0 .../so12to60.cfg => so12to30/so12to30.cfg} | 11 +- .../global_ocean/mesh/so12to60/__init__.py | 118 ------------------ .../mesh/so12to60/atlantic.geojson | 97 -------------- 13 files changed, 89 insertions(+), 237 deletions(-) create mode 100644 compass/ocean/suites/so12to30.txt delete mode 100644 compass/ocean/suites/so12to60.txt create mode 100644 compass/ocean/suites/sowisc12to30.txt delete mode 100644 compass/ocean/suites/sowisc12to60.txt create mode 100644 compass/ocean/tests/global_ocean/mesh/so12to30/__init__.py rename compass/ocean/tests/global_ocean/mesh/{so12to60 => so12to30}/dynamic_adjustment.yaml (100%) rename compass/ocean/tests/global_ocean/mesh/{so12to60 => so12to30}/high_res_region.geojson (96%) rename compass/ocean/tests/global_ocean/mesh/{so12to60 => so12to30}/namelist.split_explicit_ab2 (100%) rename compass/ocean/tests/global_ocean/mesh/{so12to60/so12to60.cfg => so12to30/so12to30.cfg} (78%) delete mode 100644 compass/ocean/tests/global_ocean/mesh/so12to60/__init__.py delete mode 100644 compass/ocean/tests/global_ocean/mesh/so12to60/atlantic.geojson diff --git a/compass/ocean/suites/so12to30.txt b/compass/ocean/suites/so12to30.txt new file mode 100644 index 0000000000..d9fb27d8c0 --- /dev/null +++ b/compass/ocean/suites/so12to30.txt @@ -0,0 +1,5 @@ +ocean/global_ocean/SO12to30/mesh +ocean/global_ocean/SO12to30/WOA23/init +ocean/global_ocean/SO12to30/WOA23/performance_test +ocean/global_ocean/SO12to30/WOA23/dynamic_adjustment +ocean/global_ocean/SO12to30/WOA23/files_for_e3sm diff --git a/compass/ocean/suites/so12to60.txt b/compass/ocean/suites/so12to60.txt deleted file mode 100644 index 42c0943056..0000000000 --- a/compass/ocean/suites/so12to60.txt +++ /dev/null @@ -1,5 +0,0 @@ -ocean/global_ocean/SO12to60/mesh -ocean/global_ocean/SO12to60/WOA23/init -ocean/global_ocean/SO12to60/WOA23/performance_test -ocean/global_ocean/SO12to60/WOA23/dynamic_adjustment -ocean/global_ocean/SO12to60/WOA23/files_for_e3sm diff --git a/compass/ocean/suites/sowisc12to30.txt b/compass/ocean/suites/sowisc12to30.txt new file mode 100644 index 0000000000..377f440bb6 --- /dev/null +++ b/compass/ocean/suites/sowisc12to30.txt @@ -0,0 +1,5 @@ +ocean/global_ocean/SOwISC12to30/mesh +ocean/global_ocean/SOwISC12to30/WOA23/init +ocean/global_ocean/SOwISC12to30/WOA23/performance_test +ocean/global_ocean/SOwISC12to30/WOA23/dynamic_adjustment +ocean/global_ocean/SOwISC12to30/WOA23/files_for_e3sm diff --git a/compass/ocean/suites/sowisc12to60.txt b/compass/ocean/suites/sowisc12to60.txt deleted file mode 100644 index 6d638a1859..0000000000 --- a/compass/ocean/suites/sowisc12to60.txt +++ /dev/null @@ -1,5 +0,0 @@ -ocean/global_ocean/SOwISC12to60/mesh -ocean/global_ocean/SOwISC12to60/WOA23/init -ocean/global_ocean/SOwISC12to60/WOA23/performance_test -ocean/global_ocean/SOwISC12to60/WOA23/dynamic_adjustment -ocean/global_ocean/SOwISC12to60/WOA23/files_for_e3sm diff --git a/compass/ocean/tests/global_ocean/__init__.py b/compass/ocean/tests/global_ocean/__init__.py index 3d266a9cc9..69f3e96669 100644 --- a/compass/ocean/tests/global_ocean/__init__.py +++ b/compass/ocean/tests/global_ocean/__init__.py @@ -44,7 +44,7 @@ def __init__(self, mpas_core): self._add_tests(mesh_names=['ARRM10to60', 'ARRMwISC10to60']) - self._add_tests(mesh_names=['SO12to60', 'SOwISC12to60']) + self._add_tests(mesh_names=['SO12to30', 'SOwISC12to30']) self._add_tests(mesh_names=['WC14', 'WCwISC14']) diff --git a/compass/ocean/tests/global_ocean/mesh/__init__.py b/compass/ocean/tests/global_ocean/mesh/__init__.py index 280bf49b9d..e88a96d612 100644 --- a/compass/ocean/tests/global_ocean/mesh/__init__.py +++ b/compass/ocean/tests/global_ocean/mesh/__init__.py @@ -16,7 +16,7 @@ QUMeshFromConfigStep, ) from compass.ocean.tests.global_ocean.mesh.rrs6to18 import RRS6to18BaseMesh -from compass.ocean.tests.global_ocean.mesh.so12to60 import SO12to60BaseMesh +from compass.ocean.tests.global_ocean.mesh.so12to30 import SO12to30BaseMesh from compass.ocean.tests.global_ocean.mesh.wc14 import WC14BaseMesh from compass.ocean.tests.global_ocean.metadata import ( get_author_and_email_from_git, @@ -98,8 +98,8 @@ def __init__(self, test_group, mesh_name, high_res_topography): base_mesh_step = ARRM10to60BaseMesh(self, name=name, subdir=subdir) elif mesh_name in ['RRS6to18', 'RRSwISC6to18']: base_mesh_step = RRS6to18BaseMesh(self, name=name, subdir=subdir) - elif mesh_name in ['SO12to60', 'SOwISC12to60']: - base_mesh_step = SO12to60BaseMesh(self, name=name, subdir=subdir) + elif mesh_name in ['SO12to30', 'SOwISC12to30']: + base_mesh_step = SO12to30BaseMesh(self, name=name, subdir=subdir) elif mesh_name in ['FRIS01to60', 'FRISwISC01to60']: base_mesh_step = FRIS01to60BaseMesh(self, name=name, subdir=subdir) elif mesh_name in ['FRIS02to60', 'FRISwISC02to60']: diff --git a/compass/ocean/tests/global_ocean/mesh/so12to30/__init__.py b/compass/ocean/tests/global_ocean/mesh/so12to30/__init__.py new file mode 100644 index 0000000000..2f05894fb4 --- /dev/null +++ b/compass/ocean/tests/global_ocean/mesh/so12to30/__init__.py @@ -0,0 +1,70 @@ +import numpy as np +from geometric_features import read_feature_collection +from mpas_tools.cime.constants import constants +from mpas_tools.mesh.creation.signed_distance import ( + signed_distance_from_geojson, +) + +from compass.mesh import QuasiUniformSphericalMeshStep + + +class SO12to30BaseMesh(QuasiUniformSphericalMeshStep): + """ + A step for creating SO12to30 meshes + """ + def setup(self): + """ + Add some input files + """ + + self.add_input_file(filename='high_res_region.geojson', + package=self.__module__) + + super().setup() + + def build_cell_width_lat_lon(self): + """ + Create cell width array for this mesh on a regular latitude-longitude + grid + + Returns + ------- + cellWidth : numpy.array + m x n array of cell width in km + + lon : numpy.array + longitude in degrees (length n and between -180 and 180) + + lat : numpy.array + longitude in degrees (length m and between -90 and 90) + """ + + dlon = 0.1 + dlat = dlon + earth_radius = constants['SHR_CONST_REARTH'] + nlon = int(360. / dlon) + 1 + nlat = int(180. / dlat) + 1 + lon = np.linspace(-180., 180., nlon) + lat = np.linspace(-90., 90., nlat) + + # start with a uniform 30 km background resolution + dx_max = 30. + cell_width = dx_max * np.ones((nlat, nlon)) + + fc = read_feature_collection('high_res_region.geojson') + + so_signed_distance = signed_distance_from_geojson(fc, lon, lat, + earth_radius, + max_length=0.25) + + # Equivalent to 20 degrees latitude + trans_width = 1600e3 + trans_start = 500e3 + dx_min = 12. + + weights = 0.5 * (1 + np.tanh((so_signed_distance - trans_start) / + trans_width)) + + cell_width = dx_min * (1 - weights) + cell_width * weights + + return cell_width, lon, lat diff --git a/compass/ocean/tests/global_ocean/mesh/so12to60/dynamic_adjustment.yaml b/compass/ocean/tests/global_ocean/mesh/so12to30/dynamic_adjustment.yaml similarity index 100% rename from compass/ocean/tests/global_ocean/mesh/so12to60/dynamic_adjustment.yaml rename to compass/ocean/tests/global_ocean/mesh/so12to30/dynamic_adjustment.yaml diff --git a/compass/ocean/tests/global_ocean/mesh/so12to60/high_res_region.geojson b/compass/ocean/tests/global_ocean/mesh/so12to30/high_res_region.geojson similarity index 96% rename from compass/ocean/tests/global_ocean/mesh/so12to60/high_res_region.geojson rename to compass/ocean/tests/global_ocean/mesh/so12to30/high_res_region.geojson index a536ebaba9..4b8b7202c6 100644 --- a/compass/ocean/tests/global_ocean/mesh/so12to60/high_res_region.geojson +++ b/compass/ocean/tests/global_ocean/mesh/so12to30/high_res_region.geojson @@ -4,7 +4,7 @@ { "type": "Feature", "properties": { - "name": "SO12to60 high res region", + "name": "SO12to30 high res region", "component": "ocean", "object": "region", "author": "Xylar Asay-Davis" diff --git a/compass/ocean/tests/global_ocean/mesh/so12to60/namelist.split_explicit_ab2 b/compass/ocean/tests/global_ocean/mesh/so12to30/namelist.split_explicit_ab2 similarity index 100% rename from compass/ocean/tests/global_ocean/mesh/so12to60/namelist.split_explicit_ab2 rename to compass/ocean/tests/global_ocean/mesh/so12to30/namelist.split_explicit_ab2 diff --git a/compass/ocean/tests/global_ocean/mesh/so12to60/so12to60.cfg b/compass/ocean/tests/global_ocean/mesh/so12to30/so12to30.cfg similarity index 78% rename from compass/ocean/tests/global_ocean/mesh/so12to60/so12to60.cfg rename to compass/ocean/tests/global_ocean/mesh/so12to30/so12to30.cfg index 541b71e917..d0bdfa0351 100644 --- a/compass/ocean/tests/global_ocean/mesh/so12to60/so12to60.cfg +++ b/compass/ocean/tests/global_ocean/mesh/so12to30/so12to30.cfg @@ -33,23 +33,20 @@ prefix = SO # a description of the mesh and initial condition mesh_description = MPAS Southern Ocean regionally refined mesh for E3SM version ${e3sm_version} with enhanced resolution (${min_res} km) around - Antarctica, 45-km resolution in the mid southern latitudes, - 30-km resolution in a 15-degree band around the equator, 60-km - resolution in northern mid latitudes, 30 km in the north - Atlantic and 35 km in the Arctic. This mesh has <<>> + Antarctica and ${max_res} km elsewhere. This mesh has <<>> vertical levels and includes cavities under the ice shelves around Antarctica. # E3SM version that the mesh is intended for e3sm_version = 3 # The revision number of the mesh, which should be incremented each time the # mesh is revised -mesh_revision = 1 +mesh_revision = 3 # the minimum (finest) resolution in the mesh min_res = 12 # the maximum (coarsest) resolution in the mesh, can be the same as min_res -max_res = 60 +max_res = 30 # The URL of the pull request documenting the creation of the mesh -pull_request = https://github.com/MPAS-Dev/compass/pull/669 +pull_request = https://github.com/MPAS-Dev/compass/pull/807 # config options related to initial condition and diagnostics support files diff --git a/compass/ocean/tests/global_ocean/mesh/so12to60/__init__.py b/compass/ocean/tests/global_ocean/mesh/so12to60/__init__.py deleted file mode 100644 index c7edd16a57..0000000000 --- a/compass/ocean/tests/global_ocean/mesh/so12to60/__init__.py +++ /dev/null @@ -1,118 +0,0 @@ -import mpas_tools.mesh.creation.mesh_definition_tools as mdt -import numpy as np -from geometric_features import read_feature_collection -from mpas_tools.cime.constants import constants -from mpas_tools.mesh.creation.signed_distance import ( - signed_distance_from_geojson, -) - -from compass.mesh import QuasiUniformSphericalMeshStep - - -class SO12to60BaseMesh(QuasiUniformSphericalMeshStep): - """ - A step for creating SO12to60 meshes - """ - def setup(self): - """ - Add some input files - """ - - self.add_input_file(filename='atlantic.geojson', - package=self.__module__) - - self.add_input_file(filename='high_res_region.geojson', - package=self.__module__) - - super().setup() - - def build_cell_width_lat_lon(self): - """ - Create cell width array for this mesh on a regular latitude-longitude - grid - - Returns - ------- - cellWidth : numpy.array - m x n array of cell width in km - - lon : numpy.array - longitude in degrees (length n and between -180 and 180) - - lat : numpy.array - longitude in degrees (length m and between -90 and 90) - """ - - dlon = 0.1 - dlat = dlon - earth_radius = constants['SHR_CONST_REARTH'] - nlon = int(360. / dlon) + 1 - nlat = int(180. / dlat) + 1 - lon = np.linspace(-180., 180., nlon) - lat = np.linspace(-90., 90., nlat) - - cellWidthSouth = mdt.EC_CellWidthVsLat(lat, cellWidthEq=30., - cellWidthMidLat=45., - cellWidthPole=45., - latPosEq=7.5, latWidthEq=3.0) - - cellWidthNorth = mdt.EC_CellWidthVsLat(lat, cellWidthEq=30., - cellWidthMidLat=60., - cellWidthPole=35., - latPosEq=7.5, latWidthEq=3.0) - - # Transition at Equator - latTransition = 0.0 - latWidthTransition = 2.5 - cellWidthVsLat = mdt.mergeCellWidthVsLat( - lat, - cellWidthSouth, - cellWidthNorth, - latTransition, - latWidthTransition) - - _, cellWidth = np.meshgrid(lon, cellWidthVsLat) - - cellWidthAtlantic = mdt.EC_CellWidthVsLat(lat, cellWidthEq=30., - cellWidthMidLat=30., - cellWidthPole=35., - latPosEq=7.5, latWidthEq=3.0) - - cellWidthAtlantic = mdt.mergeCellWidthVsLat( - lat, - cellWidthSouth, - cellWidthAtlantic, - latTransition, - latWidthTransition) - - _, cellWidthAtlantic = np.meshgrid(lon, cellWidthAtlantic) - - fc = read_feature_collection('atlantic.geojson') - - atlantic_signed_distance = signed_distance_from_geojson( - fc, lon, lat, earth_radius, max_length=0.25) - - trans_width = 400e3 - trans_start = 0. - weights = 0.5 * (1 + np.tanh((atlantic_signed_distance - trans_start) / - trans_width)) - - cellWidth = cellWidthAtlantic * (1 - weights) + cellWidth * weights - - fc = read_feature_collection('high_res_region.geojson') - - so_signed_distance = signed_distance_from_geojson(fc, lon, lat, - earth_radius, - max_length=0.25) - - # Equivalent to 20 degrees latitude - trans_width = 1600e3 - trans_start = 500e3 - dx_min = 12. - - weights = 0.5 * (1 + np.tanh((so_signed_distance - trans_start) / - trans_width)) - - cellWidth = dx_min * (1 - weights) + cellWidth * weights - - return cellWidth, lon, lat diff --git a/compass/ocean/tests/global_ocean/mesh/so12to60/atlantic.geojson b/compass/ocean/tests/global_ocean/mesh/so12to60/atlantic.geojson deleted file mode 100644 index 1df1af372d..0000000000 --- a/compass/ocean/tests/global_ocean/mesh/so12to60/atlantic.geojson +++ /dev/null @@ -1,97 +0,0 @@ -{ - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "properties": { - "name": "Atlantic region", - "component": "ocean", - "object": "region", - "author": "Xylar Asay-Davis" - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - -97.3828125, - 85.05112877979998 - ], - [ - -102.3046875, - 40.17887331434696 - ], - [ - -102.3046875, - 23.241346102386135 - ], - [ - -93.1640625, - 15.623036831528264 - ], - [ - -85.78125, - 13.581920900545844 - ], - [ - -83.583984375, - 9.535748998133627 - ], - [ - -81.2109375, - 8.059229627200192 - ], - [ - -79.013671875, - 9.795677582829743 - ], - [ - -75.9375, - 5.61598581915534 - ], - [ - -77.6953125, - 0 - ], - [ - 16.171875, - 0 - ], - [ - 27.773437499999996, - 26.745610382199022 - ], - [ - 37.96875, - 32.24997445586331 - ], - [ - 39.7265625, - 39.36827914916014 - ], - [ - 32.6953125, - 53.9560855309879 - ], - [ - 37.6171875, - 61.438767493682825 - ], - [ - 25.664062500000004, - 68.26938680456564 - ], - [ - 24.609375, - 85.05112877979998 - ], - [ - -97.3828125, - 85.05112877979998 - ] - ] - ] - } - } - ] -} \ No newline at end of file From 074c7ea3cdfe4339648b5cf9c6ba104d7749bc2b Mon Sep 17 00:00:00 2001 From: Xylar Asay-Davis Date: Wed, 3 Jan 2024 07:58:37 -0600 Subject: [PATCH 2/7] Update the docs for SO12to30 --- docs/developers_guide/ocean/api.rst | 4 +-- .../ocean/test_groups/global_ocean.rst | 34 ++++++++----------- docs/developers_guide/organization.rst | 2 +- docs/tutorials/dev_add_rrm.rst | 4 +-- .../ocean/test_groups/global_ocean.rst | 17 +++++----- docs/users_guide/quick_start.rst | 4 +-- docs/users_guide/test_suites.rst | 4 +-- 7 files changed, 32 insertions(+), 37 deletions(-) diff --git a/docs/developers_guide/ocean/api.rst b/docs/developers_guide/ocean/api.rst index bd94c3cac1..d7f0d3e05d 100644 --- a/docs/developers_guide/ocean/api.rst +++ b/docs/developers_guide/ocean/api.rst @@ -295,8 +295,8 @@ test cases and steps mesh.rrs6to18.RRS6to18BaseMesh mesh.rrs6to18.RRS6to18BaseMesh.build_cell_width_lat_lon - mesh.so12to60.SO12to60BaseMesh - mesh.so12to60.SO12to60BaseMesh.build_cell_width_lat_lon + mesh.so12to30.SO12to30BaseMesh + mesh.so12to30.SO12to30BaseMesh.build_cell_width_lat_lon mesh.wc14.WC14BaseMesh mesh.wc14.WC14BaseMesh.build_cell_width_lat_lon diff --git a/docs/developers_guide/ocean/test_groups/global_ocean.rst b/docs/developers_guide/ocean/test_groups/global_ocean.rst index 2dd28ffc74..dccd5abdd7 100644 --- a/docs/developers_guide/ocean/test_groups/global_ocean.rst +++ b/docs/developers_guide/ocean/test_groups/global_ocean.rst @@ -791,20 +791,18 @@ the higher surface resolution of the 80-layer RRS vertical coordinate. config_rx1_min_layer_thickness = 0.1 -.. _dev_ocean_global_ocean_sowisc12to60: +.. _dev_ocean_global_ocean_sowisc12to30: -SO12to60 and SOwISC12to60 +SO12to30 and SOwISC12to30 +++++++++++++++++++++++++ -The ``SO12to60`` and ``SOwISC12to60`` meshes are Southern Ocean regionally -refined meshes with 12-km resolution around the Southern Ocean and Antarctica, -45-km at southern mid-latitudes, 30-km at the equator and in the North -Atlantic, 60-km resolution in the North Pacific, and 35-km resolution in the -Arctic. +The ``SO12to30`` and ``SOwISC12to30`` meshes are Southern Ocean regionally +refined meshes with 12-km resolution around the Southern Ocean and Antarctica +and have 30-km resoltuion elsewhere. The class -:py:class:`compass.ocean.tests.global_ocean.mesh.so12to60.SO12to60BaseMesh` defines -the resolution for the meshes. The ``compass.ocean.tests.global_ocean.mesh.so12to60`` +:py:class:`compass.ocean.tests.global_ocean.mesh.so12to30.SO12to30BaseMesh` defines +the resolution for the meshes. The ``compass.ocean.tests.global_ocean.mesh.so12to30`` module includes namelist options appropriate for forward simulations with split-explicit (but not RK4) time integration on these meshes. These set the time step and default run duration for short runs with these meshes. @@ -847,24 +845,21 @@ The default config options for these meshes are: prefix = SO # a description of the mesh and initial condition mesh_description = MPAS Southern Ocean regionally refined mesh for E3SM version - ${e3sm_version} with enhanced resolution (${min_res} km) around - Antarctica, 45-km resolution in the mid southern latitudes, - 30-km resolution in a 15-degree band around the equator, 60-km - resolution in northern mid latitudes, 30 km in the north - Atlantic and 35 km in the Arctic. This mesh has <<>> - vertical levels and includes cavities under the ice shelves - around Antarctica. + ${e3sm_version} with enhanced resolution (${min_res} km) around + Antarctica and 30 km elsewhere. This mesh has <<>> + vertical levels and includes cavities under the ice shelves + around Antarctica. # E3SM version that the mesh is intended for e3sm_version = 3 # The revision number of the mesh, which should be incremented each time the # mesh is revised - mesh_revision = 1 + mesh_revision = 2 # the minimum (finest) resolution in the mesh min_res = 12 # the maximum (coarsest) resolution in the mesh, can be the same as min_res - max_res = 60 + max_res = 30 # The URL of the pull request documenting the creation of the mesh - pull_request = https://github.com/MPAS-Dev/compass/pull/460 + pull_request = https://github.com/MPAS-Dev/compass/pull/752 # config options related to initial condition and diagnostics support files @@ -874,6 +869,7 @@ The default config options for these meshes are: # CMIP6 grid resolution cmip6_grid_res = 180x360 + The vertical grid is an ``index_tanh_dz`` profile (see :ref:`dev_ocean_framework_vertical`) with 64 vertical levels ranging in thickness from 10 to 250 m. diff --git a/docs/developers_guide/organization.rst b/docs/developers_guide/organization.rst index f4e478bdd1..c41c421f5a 100644 --- a/docs/developers_guide/organization.rst +++ b/docs/developers_guide/organization.rst @@ -1675,7 +1675,7 @@ should have cached outputs, the suffix ``c`` can be added to the test number: compass setup -n 90c 91c 92 ... In this example, test cases 90 and 91 (``mesh`` and ``init`` test cases from -the ``SOwISC12to60`` global ocean mesh, in this case) are set up with cached +the ``SOwISC12to30`` global ocean mesh, in this case) are set up with cached outputs in all steps and 92 (``performance_test``) is not. This approach is efficient but does not provide any control of which steps use cached outputs and which do not. diff --git a/docs/tutorials/dev_add_rrm.rst b/docs/tutorials/dev_add_rrm.rst index 840666ab14..701c6e9e50 100644 --- a/docs/tutorials/dev_add_rrm.rst +++ b/docs/tutorials/dev_add_rrm.rst @@ -7,7 +7,7 @@ This tutorial presents a step-by-step guide to adding a new mesh to the ``global_ocean`` test group in ``compass`` (see the :ref:`glossary` for definitions of some relevant terms). In this tutorial, I will add a new mesh called YAM ("yet another mesh") that is based on techniques used to build -the existing :ref:`dev_ocean_global_ocean_sowisc12to60` as well as +the existing :ref:`dev_ocean_global_ocean_sowisc12to30` as well as :ref:`dev_ocean_global_ocean_wc14` meshes. .. _dev_tutorial_add_rrm_getting_started: @@ -164,7 +164,7 @@ Next, we need to add this mesh to the list of known meshes: ... - from compass.ocean.tests.global_ocean.mesh.so12to60 import SO12to60BaseMesh + from compass.ocean.tests.global_ocean.mesh.so12to30 import SO12to30BaseMesh from compass.ocean.tests.global_ocean.mesh.wc14 import WC14BaseMesh from compass.ocean.tests.global_ocean.mesh.yam10to60 import YAM10to60BaseMesh from compass.ocean.tests.global_ocean.metadata import ( diff --git a/docs/users_guide/ocean/test_groups/global_ocean.rst b/docs/users_guide/ocean/test_groups/global_ocean.rst index b86063163d..7ca1785b9d 100644 --- a/docs/users_guide/ocean/test_groups/global_ocean.rst +++ b/docs/users_guide/ocean/test_groups/global_ocean.rst @@ -460,24 +460,23 @@ ice-shelf cavities around Antarctica, whereas the RRS6to18 mesh does not. :width: 500 px :align: center -.. _global_ocean_mesh_sowisc12to60: +.. _global_ocean_mesh_sowisc12to30: -SO12to60 and SOwISC12to60 +SO12to30 and SOwISC12to30 ^^^^^^^^^^^^^^^^^^^^^^^^^ -The Southern Ocean 12- to 60-km mesh with ice-shelf cavities (SOwISC12to60), +The Southern Ocean 12- to 30-km mesh with ice-shelf cavities (SOwISC12to30), sometimes called the Southern Ocean regionally refined mesh (SORRM), is the main simulation mesh for the `E3SM v2 Cryosphere Science Campaign `_ and E3SM v3 Polar Processes, Sea-Level Rise, and Coastal Impacts Campaign. -The SO12to60 is the same mesh but without ice-shelf cavities. -The mesh has 12 km resolution around Antarctica, tapering to 45 km in mid -Southern latitudes, 30 km at the equator and in the North Atlantic, 60 km -in the North Pacific, and 35 km in the Arctic. The mesh includes the -:ref:`global_ocean_ice_shelf_cavities` around Antarctica in the ocean domain. +The SO12to30 is the same mesh but without ice-shelf cavities. +The mesh has 12-km resolution around Antarctica and 30-km resolution elsewhere. +The mesh includes the :ref:`global_ocean_ice_shelf_cavities` around Antarctica +in the ocean domain. -.. image:: images/sowisc12to60.png +.. image:: images/sowisc12to30.png :width: 500 px :align: center diff --git a/docs/users_guide/quick_start.rst b/docs/users_guide/quick_start.rst index 2f875ad713..ed3f5f01fc 100644 --- a/docs/users_guide/quick_start.rst +++ b/docs/users_guide/quick_start.rst @@ -428,8 +428,8 @@ The output is: -c ocean -t qu240_for_e3sm -c ocean -t quwisc240 -c ocean -t quwisc240_for_e3sm - -c ocean -t so12to60 - -c ocean -t sowisc12to60 + -c ocean -t so12to30 + -c ocean -t sowisc12to30 -c ocean -t wc14 -c ocean -t wcwisc14 -c ocean -t wetdry diff --git a/docs/users_guide/test_suites.rst b/docs/users_guide/test_suites.rst index bea5dd7582..94943129bb 100644 --- a/docs/users_guide/test_suites.rst +++ b/docs/users_guide/test_suites.rst @@ -41,8 +41,8 @@ the current set of available test suites is: -c ocean -t qu240_for_e3sm -c ocean -t quwisc240 -c ocean -t quwisc240_for_e3sm - -c ocean -t so12to60 - -c ocean -t sowisc12to60 + -c ocean -t so12to30 + -c ocean -t sowisc12to30 -c ocean -t wc14 -c ocean -t wcwisc14 -c ocean -t wetdry From 028fe16d42f7f0b65de972ea11663acc12151436 Mon Sep 17 00:00:00 2001 From: Xylar Asay-Davis Date: Wed, 10 Apr 2024 06:02:40 -0500 Subject: [PATCH 3/7] Switch to 80 vertical levels --- .../global_ocean/mesh/so12to30/so12to30.cfg | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/compass/ocean/tests/global_ocean/mesh/so12to30/so12to30.cfg b/compass/ocean/tests/global_ocean/mesh/so12to30/so12to30.cfg index d0bdfa0351..d7450979bb 100644 --- a/compass/ocean/tests/global_ocean/mesh/so12to30/so12to30.cfg +++ b/compass/ocean/tests/global_ocean/mesh/so12to30/so12to30.cfg @@ -2,28 +2,47 @@ [vertical_grid] # the type of vertical grid -grid_type = index_tanh_dz +grid_type = tanh_dz # Number of vertical levels -vert_levels = 64 +vert_levels = 80 # Depth of the bottom of the ocean bottom_depth = 5500.0 # The minimum layer thickness -min_layer_thickness = 10.0 +min_layer_thickness = 2.0 # The maximum layer thickness -max_layer_thickness = 250.0 +max_layer_thickness = 150.0 -# The characteristic number of levels over which the transition between -# the min and max occurs -transition_levels = 28 +# Options relate to adjusting the sea-surface height or land-ice pressure +# below ice shelves to they are dynamically consistent with one another +[ssh_adjustment] + +# the number of iterations of ssh adjustment to perform +iterations = 4 # options for global ocean testcases [global_ocean] +## config options related to the initial_state step + +# minimum number of vertical levels, both in the open ocean and in ice-shelf +# cavities +min_levels = 5 +cavity_min_levels = ${min_levels} + +# minimum thickness of layers in ice-shelf cavities at the beginning and end +# of iterative ssh init +cavity_min_layer_thickness_initial = 2.0 +cavity_min_layer_thickness_final = 1.0 + +# Maximum allowed Haney number for configurations with ice-shelf cavities +rx1_max = 20.0 + + # the approximate number of cells in the mesh approx_cell_count = 570000 From 0e3ed26bbff9caa8107f5487a837044066f9a2da Mon Sep 17 00:00:00 2001 From: Xylar Asay-Davis Date: Tue, 21 May 2024 08:39:36 -0500 Subject: [PATCH 4/7] Add namelist options for haney-number vert. coord. --- .../ocean/tests/global_ocean/mesh/so12to30/namelist.init | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 compass/ocean/tests/global_ocean/mesh/so12to30/namelist.init diff --git a/compass/ocean/tests/global_ocean/mesh/so12to30/namelist.init b/compass/ocean/tests/global_ocean/mesh/so12to30/namelist.init new file mode 100644 index 0000000000..16185cf866 --- /dev/null +++ b/compass/ocean/tests/global_ocean/mesh/so12to30/namelist.init @@ -0,0 +1,8 @@ +config_rx1_inner_iter_count = 20 +config_rx1_horiz_smooth_weight = 1.0 +config_rx1_vert_smooth_weight = 1.0 +config_rx1_slope_weight = 1e-2 +config_rx1_zstar_weight = 1.0 +config_rx1_min_levels = 5 +config_rx1_min_layer_thickness = 2.0 +config_global_ocean_minimum_depth = 10.0 From 23c773b21e1e00b73703b9fc498f467a533e2c1d Mon Sep 17 00:00:00 2001 From: Xylar Asay-Davis Date: Thu, 11 Jul 2024 01:30:10 -0500 Subject: [PATCH 5/7] Increase min cavity layer thickness to 2 m --- compass/ocean/tests/global_ocean/mesh/so12to30/so12to30.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compass/ocean/tests/global_ocean/mesh/so12to30/so12to30.cfg b/compass/ocean/tests/global_ocean/mesh/so12to30/so12to30.cfg index d7450979bb..3f7551ae34 100644 --- a/compass/ocean/tests/global_ocean/mesh/so12to30/so12to30.cfg +++ b/compass/ocean/tests/global_ocean/mesh/so12to30/so12to30.cfg @@ -37,7 +37,7 @@ cavity_min_levels = ${min_levels} # minimum thickness of layers in ice-shelf cavities at the beginning and end # of iterative ssh init cavity_min_layer_thickness_initial = 2.0 -cavity_min_layer_thickness_final = 1.0 +cavity_min_layer_thickness_final = 2.0 # Maximum allowed Haney number for configurations with ice-shelf cavities rx1_max = 20.0 From 84244688dd8152cf7ea2f484c1f4b7a01d276eb6 Mon Sep 17 00:00:00 2001 From: Xylar Asay-Davis Date: Thu, 11 Jul 2024 01:56:51 -0500 Subject: [PATCH 6/7] Add water-column thickness to init plots When we plot histograms of the initial condition, now plot histograms of the water-column thickness in the open ocean and in cavities. --- compass/ocean/plot.py | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/compass/ocean/plot.py b/compass/ocean/plot.py index 21b9abd75e..ae5eb91408 100644 --- a/compass/ocean/plot.py +++ b/compass/ocean/plot.py @@ -29,7 +29,7 @@ def plot_initial_state(input_file_name='initial_state.nc', nVertLevels = ds.sizes['nVertLevels'] fig = plt.figure() - fig.set_size_inches(16.0, 12.0) + fig.set_size_inches(16.0, 16.0) plt.clf() print('plotting histograms of the initial condition') @@ -43,7 +43,7 @@ def plot_initial_state(input_file_name='initial_state.nc', 'number layers: {}\n\n'.format(nVertLevels) + \ ' min val max val variable name\n' - plt.subplot(3, 3, 2) + plt.subplot(4, 3, 2) varName = 'maxLevelCell' var = ds[varName] maxLevelCell = var.values - 1 @@ -53,7 +53,7 @@ def plot_initial_state(input_file_name='initial_state.nc', txt = '{}{:9.2e} {:9.2e} {}\n'.format(txt, var.min().values, var.max().values, varName) - plt.subplot(3, 3, 3) + plt.subplot(4, 3, 3) varName = 'bottomDepth' var = ds[varName] xarray.plot.hist(var, bins=nVertLevels - 4) @@ -75,7 +75,7 @@ def plot_initial_state(input_file_name='initial_state.nc', cellMask = xarray.DataArray(data=cellMask, dims=('nCells', 'nVertLevels')) edgeMask = xarray.DataArray(data=edgeMask, dims=('nEdges', 'nVertLevels')) - plt.subplot(3, 3, 4) + plt.subplot(4, 3, 4) varName = 'temperature' var = ds[varName].isel(Time=0).where(cellMask) xarray.plot.hist(var, bins=100, log=True) @@ -84,7 +84,7 @@ def plot_initial_state(input_file_name='initial_state.nc', txt = '{}{:9.2e} {:9.2e} {}\n'.format(txt, var.min().values, var.max().values, varName) - plt.subplot(3, 3, 5) + plt.subplot(4, 3, 5) varName = 'salinity' var = ds[varName].isel(Time=0).where(cellMask) xarray.plot.hist(var, bins=100, log=True) @@ -92,7 +92,7 @@ def plot_initial_state(input_file_name='initial_state.nc', txt = '{}{:9.2e} {:9.2e} {}\n'.format(txt, var.min().values, var.max().values, varName) - plt.subplot(3, 3, 6) + plt.subplot(4, 3, 6) varName = 'layerThickness' var = ds[varName].isel(Time=0).where(cellMask) xarray.plot.hist(var, bins=100, log=True) @@ -100,7 +100,7 @@ def plot_initial_state(input_file_name='initial_state.nc', txt = '{}{:9.2e} {:9.2e} {}\n'.format(txt, var.min().values, var.max().values, varName) - plt.subplot(3, 3, 7) + plt.subplot(4, 3, 7) varName = 'rx1Edge' var = ds[varName].isel(Time=0).where(edgeMask) maxRx1Edge = var.max().values @@ -110,7 +110,7 @@ def plot_initial_state(input_file_name='initial_state.nc', txt = '{}{:9.2e} {:9.2e} {}\n'.format(txt, var.min().values, var.max().values, varName) - plt.subplot(3, 3, 8) + plt.subplot(4, 3, 8) varName = 'areaCell' var = ds[varName] xarray.plot.hist(1e-6 * var, bins=100, log=True) @@ -119,7 +119,7 @@ def plot_initial_state(input_file_name='initial_state.nc', txt = '{}{:9.2e} {:9.2e} {}\n'.format(txt, var.min().values, var.max().values, varName) - plt.subplot(3, 3, 9) + plt.subplot(4, 3, 9) varName = 'dcEdge' var = ds[varName] xarray.plot.hist(1e-3 * var, bins=100, log=True) @@ -128,6 +128,26 @@ def plot_initial_state(input_file_name='initial_state.nc', txt = '{}{:9.2e} {:9.2e} {}\n'.format(txt, var.min().values, var.max().values, varName) + plt.subplot(4, 3, 10) + var = ds.ssh - (-ds.bottomDepth) + if 'landIceMask' in ds: + mask = ds.landIceMask == 0 + var = var.where(mask) + xarray.plot.hist(var, bins=100, log=True) + plt.ylabel('frequency') + plt.xlabel(r'open ocean water-column thickness (m)') + txt = '{}{:9.2e} {:9.2e} {}\n'.format(txt, var.min().values, + var.max().values, 'open ocean wc') + + if 'landIceMask' in ds: + plt.subplot(4, 3, 11) + var = (ds.ssh - (-ds.bottomDepth)).where(ds.landIceMask == 1) + xarray.plot.hist(var, bins=100, log=True) + plt.ylabel('frequency') + plt.xlabel(r'ice-shelf cavity water-column thickness (m)') + txt = '{}{:9.2e} {:9.2e} {}\n'.format(txt, var.min().values, + var.max().values, 'cavity wc') + font = FontProperties() font.set_family('monospace') font.set_size(12) From 3412c81f8247095659e1ed980a51a2aab7b692ef Mon Sep 17 00:00:00 2001 From: Xylar Asay-Davis Date: Thu, 1 Aug 2024 14:40:50 -0500 Subject: [PATCH 7/7] Enforce minimum column thickness in initial_state In cavities, we thicken the water column to make sure it has the minimum thickness. The hope is that this makes the vertical coorinate converge more quickly and smoothly to its final result. --- .../tests/global_ocean/init/initial_state.py | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/compass/ocean/tests/global_ocean/init/initial_state.py b/compass/ocean/tests/global_ocean/init/initial_state.py index 71f47e94c6..5b6e511bd7 100644 --- a/compass/ocean/tests/global_ocean/init/initial_state.py +++ b/compass/ocean/tests/global_ocean/init/initial_state.py @@ -1,6 +1,7 @@ import os from importlib.resources import contents, read_text +import numpy as np import xarray as xr from jinja2 import Template from mpas_tools.io import write_netcdf @@ -194,7 +195,7 @@ def run(self): """ config = self.config section = config['global_ocean'] - self._smooth_topography() + topo_filename = self._smooth_topography() interfaces = generate_1d_grid(config=config) @@ -223,8 +224,16 @@ def run(self): namelist['config_rx1_min_layer_thickness'] = \ f'{cavity_min_layer_thickness}' + min_water_column_thickness = \ + cavity_min_layer_thickness * cavity_min_levels + + topo_filename = self._dig_cavity_bed_elevation( + topo_filename, min_water_column_thickness) + self.update_namelist_at_runtime(namelist) + symlink(target=topo_filename, link_name='topography.nc') + update_pio = config.getboolean('global_ocean', 'init_update_pio') run_model(self, update_pio=update_pio) @@ -250,10 +259,8 @@ def _smooth_topography(self): section = config['global_ocean'] num_passes = section.getint('topo_smooth_num_passes') if num_passes == 0: - # just symlink the culled topography to be the topography used for - # the initial condition - symlink(target='topography_culled.nc', link_name='topography.nc') - return + # just return the culled topography file name + return 'topography_culled.nc' distance_limit = section.getfloat('topo_smooth_distance_limit') std_deviation = section.getfloat('topo_smooth_std_deviation') @@ -274,7 +281,8 @@ def _smooth_topography(self): check_call(args=['ocean_smooth_topo_before_init'], logger=self.logger) - with (xr.open_dataset('topography_culled.nc') as ds_topo): + out_filename = 'topography_smoothed.nc' + with xr.open_dataset('topography_culled.nc') as ds_topo: with xr.open_dataset('topography_orig_and_smooth.nc') as ds_smooth: for field in ['bed_elevation', 'landIceDraftObserved', 'landIceThkObserved']: @@ -282,4 +290,23 @@ def _smooth_topography(self): ds_topo[field] = ds_smooth[f'{field}New'] ds_topo[field].attrs = attrs - write_netcdf(ds_topo, 'topography.nc') + write_netcdf(ds_topo, out_filename) + return out_filename + + def _dig_cavity_bed_elevation(self, in_filename, + min_water_column_thickness): + """ Dig bed elevation to preserve minimum water-column thickness """ + + out_filename = 'topography_dig_bed.nc' + with xr.open_dataset(in_filename) as ds_topo: + bed = ds_topo.bed_elevation + attrs = bed.attrs + draft = ds_topo.landIceDraftObserved + max_bed = draft - min_water_column_thickness + mask = np.logical_or(draft == 0., bed < max_bed) + bed = xr.where(mask, bed, max_bed) + ds_topo['bed_elevation'] = bed + ds_topo['bed_elevation'].attrs = attrs + + write_netcdf(ds_topo, out_filename) + return out_filename