From 06969ab0d4e5f0ed6e4bf45d3f8fd7161d189932 Mon Sep 17 00:00:00 2001 From: Carolyn Begeman Date: Wed, 11 Oct 2023 15:26:31 -0500 Subject: [PATCH 1/9] Migrate initial state from init mode --- .../drying_slope/convergence/__init__.py | 9 +- .../tests/drying_slope/default/__init__.py | 9 +- .../ocean/tests/drying_slope/drying_slope.cfg | 36 ++++++ compass/ocean/tests/drying_slope/forward.py | 4 +- .../ocean/tests/drying_slope/initial_state.py | 110 ++++++++++++------ .../tests/drying_slope/loglaw/__init__.py | 9 +- .../ocean/tests/drying_slope/namelist.init | 10 -- compass/ocean/tests/drying_slope/streams.init | 40 ------- .../ocean/tests/drying_slope/viz/__init__.py | 7 +- 9 files changed, 137 insertions(+), 97 deletions(-) delete mode 100644 compass/ocean/tests/drying_slope/namelist.init delete mode 100644 compass/ocean/tests/drying_slope/streams.init diff --git a/compass/ocean/tests/drying_slope/convergence/__init__.py b/compass/ocean/tests/drying_slope/convergence/__init__.py index 5e09e7c8f0..be3ad046a9 100644 --- a/compass/ocean/tests/drying_slope/convergence/__init__.py +++ b/compass/ocean/tests/drying_slope/convergence/__init__.py @@ -92,8 +92,7 @@ def _setup_steps(self, config, subdir, method): init_name = f'initial_state_{res_name}' self.add_step(InitialState(test_case=self, name=init_name, - resolution=resolution, - coord_type=self.coord_type)) + resolution=resolution)) ntasks = max(min_tasks, int(ceil(ntasks_baseline / resolution**2.))) forward_step = Forward(test_case=self, resolution=resolution, @@ -124,3 +123,9 @@ def validate(self): res_name = f'{int(resolution)}km' compare_variables(test_case=self, variables=variables, filename1=f'forward_{res_name}/output.nc') + + def configure(self): + """ + Change config options as needed + """ + self.config.set('vertical_grid', 'coord_type', self.coord_type) diff --git a/compass/ocean/tests/drying_slope/default/__init__.py b/compass/ocean/tests/drying_slope/default/__init__.py index 3af74a6bba..a78a96e383 100644 --- a/compass/ocean/tests/drying_slope/default/__init__.py +++ b/compass/ocean/tests/drying_slope/default/__init__.py @@ -50,8 +50,7 @@ def __init__(self, test_group, resolution, coord_type, method): subdir = f'{coord_type}/{method}/{res_name}/{name}' super().__init__(test_group=test_group, name=name, subdir=subdir) - self.add_step(InitialState(test_case=self, resolution=resolution, - coord_type=coord_type)) + self.add_step(InitialState(test_case=self, resolution=resolution)) damping_coeffs = None config = CompassConfigParser() config.add_from_package('compass.ocean.tests.drying_slope', @@ -99,3 +98,9 @@ def validate(self): else: compare_variables(test_case=self, variables=variables, filename1='forward/output.nc') + + def configure(self): + """ + Change config options as needed + """ + self.config.set('vertical_grid', 'coord_type', self.coord_type) diff --git a/compass/ocean/tests/drying_slope/drying_slope.cfg b/compass/ocean/tests/drying_slope/drying_slope.cfg index a9d4c58c9d..d8d4178852 100644 --- a/compass/ocean/tests/drying_slope/drying_slope.cfg +++ b/compass/ocean/tests/drying_slope/drying_slope.cfg @@ -1,18 +1,54 @@ # Options related to the vertical grid [vertical_grid] +# the type of vertical grid +grid_type = uniform + +# Number of vertical levels +bottom_depth = 10. + # Number of vertical levels vert_levels = 10 # Thickness of each layer in the thin film region thin_film_thickness = 1.0e-3 +# Whether to use "partial" or "full", or "None" to not alter the topography +partial_cell_type = None + +# The minimum fraction of a layer for partial cells +min_pc_fraction = 0.1 + # config options for drying slope test cases [drying_slope] # the number of grid cells in x nx = 6 +# Length over which wetting and drying actually occur +Ly_analysis = 25. + +# Domain length +Ly = 30. + +# Bottom depth at the right side of the domain +right_bottom_depth = 10. + +# Bottom depth at the left side of the domain +left_bottom_depth = 0. + +# Plug width as a fraction of the domain +plug_width_frac = 0.0 + +# Plug temperature +plug_temperature = 20.0 + +# Background temperature +background_temperature = 20.0 + +# Background salinity +background_salinity = 35.0 + # time step in s per km of horizontal resolution dt_per_km = 30 diff --git a/compass/ocean/tests/drying_slope/forward.py b/compass/ocean/tests/drying_slope/forward.py index 36c9c23527..e218c2dc8f 100644 --- a/compass/ocean/tests/drying_slope/forward.py +++ b/compass/ocean/tests/drying_slope/forward.py @@ -74,10 +74,10 @@ def __init__(self, test_case, resolution, name='forward', subdir=None, target=f'{input_path}/culled_mesh.nc') self.add_input_file(filename='init.nc', - target=f'{input_path}/ocean.nc') + target=f'{input_path}/initial_state.nc') self.add_input_file(filename='forcing.nc', - target=f'{input_path}/init_mode_forcing_data.nc') + target=f'{input_path}/forcing.nc') self.add_input_file(filename='graph.info', target=f'{input_path}/culled_graph.info') diff --git a/compass/ocean/tests/drying_slope/initial_state.py b/compass/ocean/tests/drying_slope/initial_state.py index 97d312af42..8849a7dd16 100644 --- a/compass/ocean/tests/drying_slope/initial_state.py +++ b/compass/ocean/tests/drying_slope/initial_state.py @@ -1,8 +1,9 @@ +import xarray as xr from mpas_tools.io import write_netcdf from mpas_tools.mesh.conversion import convert, cull from mpas_tools.planar_hex import make_planar_hex_mesh -from compass.model import run_model +from compass.ocean.vertical import init_vertical_coord from compass.step import Step @@ -12,7 +13,7 @@ class InitialState(Step): cases """ def __init__(self, test_case, resolution, name='initial_state', - coord_type='sigma'): + baroclinic=False): """ Create the step @@ -24,18 +25,10 @@ def __init__(self, test_case, resolution, name='initial_state', super().__init__(test_case=test_case, name=name, ntasks=1, min_tasks=1, openmp_threads=1) - self.coord_type = coord_type - self.resolution = resolution - self.add_namelist_file('compass.ocean.tests.drying_slope', - 'namelist.init', mode='init') - - self.add_streams_file('compass.ocean.tests.drying_slope', - 'streams.init', mode='init') - for file in ['base_mesh.nc', 'culled_mesh.nc', 'culled_graph.info', - 'ocean.nc']: + 'initial_state.nc', 'forcing.nc']: self.add_output_file(file) self.add_model_as_input() @@ -46,42 +39,85 @@ def run(self): """ config = self.config logger = self.logger + resolution = self.resolution + # Fetch config options section = config['vertical_grid'] - coord_type = self.coord_type thin_film_thickness = section.getfloat('thin_film_thickness') + 1.0e-9 - if coord_type == 'single_layer': - options = {'config_tidal_boundary_vert_levels': '1', - 'config_drying_min_cell_height': - f'{thin_film_thickness}'} - self.update_namelist_at_runtime(options) - else: - vert_levels = section.getint('vert_levels') - options = {'config_tidal_boundary_vert_levels': f'{vert_levels}', - 'config_tidal_boundary_layer_type': f"'{coord_type}'", - 'config_drying_min_cell_height': - f'{thin_film_thickness}'} - self.update_namelist_at_runtime(options) + vert_levels = section.getint('vert_levels') + + section = config['drying_slope'] + nx = section.getint('nx') + domain_length = section.getfloat('Ly') * 1e3 + drying_length = section.getfloat('Ly_analysis') * 1e3 + plug_width_frac = section.getfloat('plug_width_frac') + right_bottom_depth = section.getfloat('right_bottom_depth') + left_bottom_depth = section.getfloat('left_bottom_depth') + plug_temperature = section.getfloat('plug_temperature') + background_temperature = section.getfloat('background_temperature') + background_salinity = section.getfloat('background_salinity') + + # Check config options + if domain_length < drying_length: + raise ValueError('Domain is not long enough to capture wetting ' + 'front') + if right_bottom_depth < left_bottom_depth: + raise ValueError('Right boundary must be deeper than left ' + 'boundary') # Determine mesh parameters - nx = config.getint('drying_slope', 'nx') - ny = round(28 / self.resolution) - if self.resolution < 1.: + dc = 1e3 * resolution + ny = round(domain_length / dc) + # This is just for consistency with previous implementations and could + # be removed + if resolution < 1.: ny += 2 - dc = 1e3 * self.resolution logger.info(' * Make planar hex mesh') - dsMesh = make_planar_hex_mesh(nx=nx, ny=ny, dc=dc, nonperiodic_x=False, - nonperiodic_y=True) + ds_mesh = make_planar_hex_mesh(nx=nx, ny=ny, dc=dc, + nonperiodic_x=False, + nonperiodic_y=True) logger.info(' * Completed Make planar hex mesh') - write_netcdf(dsMesh, 'base_mesh.nc') + write_netcdf(ds_mesh, 'base_mesh.nc') logger.info(' * Cull mesh') - dsMesh = cull(dsMesh, logger=logger) + ds_mesh = cull(ds_mesh, logger=logger) logger.info(' * Convert mesh') - dsMesh = convert(dsMesh, graphInfoFileName='culled_graph.info', - logger=logger) + ds_mesh = convert(ds_mesh, graphInfoFileName='culled_graph.info', + logger=logger) logger.info(' * Completed Convert mesh') - write_netcdf(dsMesh, 'culled_mesh.nc') - run_model(self, namelist='namelist.ocean', - streams='streams.ocean') + write_netcdf(ds_mesh, 'culled_mesh.nc') + + ds = ds_mesh.copy() + ds_forcing = ds_mesh.copy() + + y_min = ds_mesh.yCell.min() + y_max = ds_mesh.yCell.max() + dc_edge_min = ds_mesh.dcEdge.min() + + y_cell = ds.yCell + max_level_cell = vert_levels + bottom_depth = (right_bottom_depth - (y_max - y_cell) / drying_length * + (right_bottom_depth - left_bottom_depth)) + ds['bottomDepth'] = bottom_depth + # Set the water column to dry everywhere + ds['ssh'] = -bottom_depth + thin_film_thickness * max_level_cell + # We don't use config_tidal_forcing_monochromatic_baseline because the + # default value doesn't alter the initial state + init_vertical_coord(config, ds) + + plug_width = domain_length * plug_width_frac + y_plug_boundary = y_min + plug_width + ds['temperature'] = xr.where(y_cell < y_plug_boundary, + plug_temperature, background_temperature) + ds['tracer1'] = xr.where(y_cell < y_plug_boundary, 1.0, 0.0) + ds['salinity'] = background_salinity * xr.ones_like(y_cell) + write_netcdf(ds, 'initial_state.nc') + + # Define the tidal boundary condition over 1-cell width + y_tidal_boundary = y_max - dc_edge_min / 2. + tidal_forcing_mask = xr.where(y_cell > y_tidal_boundary, 1.0, 0.0) + if tidal_forcing_mask.sum() <= 0: + raise ValueError('Input mask for tidal case is not set!') + ds_forcing['tidalInputMask'] = tidal_forcing_mask + write_netcdf(ds_forcing, 'forcing.nc') diff --git a/compass/ocean/tests/drying_slope/loglaw/__init__.py b/compass/ocean/tests/drying_slope/loglaw/__init__.py index 0cbd50b721..9cbafe2a94 100644 --- a/compass/ocean/tests/drying_slope/loglaw/__init__.py +++ b/compass/ocean/tests/drying_slope/loglaw/__init__.py @@ -47,8 +47,7 @@ def __init__(self, test_group, resolution, coord_type, method): subdir = f'{coord_type}/{method}/{res_name}/{name}' super().__init__(test_group=test_group, name=name, subdir=subdir) - self.add_step(InitialState(test_case=self, coord_type=coord_type, - resolution=resolution)) + self.add_step(InitialState(test_case=self, resolution=resolution)) config = CompassConfigParser() config.add_from_package('compass.ocean.tests.drying_slope', 'drying_slope.cfg') @@ -72,3 +71,9 @@ def validate(self): variables = ['layerThickness', 'normalVelocity'] compare_variables(test_case=self, variables=variables, filename1='forward/output.nc') + + def configure(self): + """ + Change config options as needed + """ + self.config.set('vertical_grid', 'coord_type', self.coord_type) diff --git a/compass/ocean/tests/drying_slope/namelist.init b/compass/ocean/tests/drying_slope/namelist.init deleted file mode 100644 index a15464bd7c..0000000000 --- a/compass/ocean/tests/drying_slope/namelist.init +++ /dev/null @@ -1,10 +0,0 @@ -config_init_configuration='tidal_boundary' -config_ocean_run_mode = 'init' -config_tidal_boundary_layer_type='sigma' -config_tidal_start_dry=.true. -config_tidal_boundary_left_bottom_depth=0.0 -config_tidal_boundary_use_distances=.true. -config_tidal_forcing_monochromatic_baseline=10.0 -config_use_wetting_drying=.true. -config_use_tidal_forcing=.true. -config_write_cull_cell_mask=.false. diff --git a/compass/ocean/tests/drying_slope/streams.init b/compass/ocean/tests/drying_slope/streams.init deleted file mode 100644 index 12f64570bd..0000000000 --- a/compass/ocean/tests/drying_slope/streams.init +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - type="output" - output_interval="0000_00:00:01" - clobber_mode="truncate" - filename_template="forcing.nc"> - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/compass/ocean/tests/drying_slope/viz/__init__.py b/compass/ocean/tests/drying_slope/viz/__init__.py index 875859d94f..7b21d642c7 100644 --- a/compass/ocean/tests/drying_slope/viz/__init__.py +++ b/compass/ocean/tests/drying_slope/viz/__init__.py @@ -45,7 +45,7 @@ def __init__(self, test_case, damping_coeffs=None): self.datatypes = datatypes self.add_input_file(filename='init.nc', - target='../initial_state/ocean.nc') + target='../initial_state/initial_state.nc') if damping_coeffs is None: self.add_input_file(filename='output.nc', target='../forward/output.nc') @@ -160,7 +160,10 @@ def _plot_ssh_validation(self, times, tidx=None, outFolder='.'): mesh_ymean = ds_mesh.isel(Time=0).groupby('yCell').mean( dim=xr.ALL_DIMS) bottom_depth = mesh_ymean.bottomDepth.values - x = mesh_ymean.yCell.values / 1000.0 + drying_length = self.config.getfloat('drying_slope', 'Ly_analysis') + drying_length = drying_length * 1e3 + x_offset = np.max(mesh_ymean.yCell.values) - drying_length + x = (mesh_ymean.yCell.values - x_offset) / 1000.0 xBed = np.linspace(0, 25, 100) yBed = 10.0 / 25.0 * xBed From 5b673d62f2416528b064486db59fe200dbb22248 Mon Sep 17 00:00:00 2001 From: Carolyn Begeman Date: Thu, 21 Sep 2023 14:27:04 -0500 Subject: [PATCH 2/9] fixup namelist options --- compass/ocean/tests/drying_slope/namelist.forward | 1 + 1 file changed, 1 insertion(+) diff --git a/compass/ocean/tests/drying_slope/namelist.forward b/compass/ocean/tests/drying_slope/namelist.forward index 3fcac6b181..d8d04061a4 100644 --- a/compass/ocean/tests/drying_slope/namelist.forward +++ b/compass/ocean/tests/drying_slope/namelist.forward @@ -20,3 +20,4 @@ config_thickness_flux_type='upwind' config_use_cvmix=.false. config_use_debugTracers=.false. config_check_ssh_consistency=.true. +config_disable_tr_all_tend=.true. From 54e424df6cfce8d08689a2e663277e0decfc660e Mon Sep 17 00:00:00 2001 From: Carolyn Begeman Date: Tue, 17 Oct 2023 12:13:31 -0500 Subject: [PATCH 3/9] Make cfg options lowercase --- compass/ocean/tests/drying_slope/decomp/__init__.py | 3 +-- compass/ocean/tests/drying_slope/drying_slope.cfg | 4 ++-- compass/ocean/tests/drying_slope/initial_state.py | 4 ++-- compass/ocean/tests/drying_slope/viz/__init__.py | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/compass/ocean/tests/drying_slope/decomp/__init__.py b/compass/ocean/tests/drying_slope/decomp/__init__.py index 5b99b7c170..5069337f1a 100644 --- a/compass/ocean/tests/drying_slope/decomp/__init__.py +++ b/compass/ocean/tests/drying_slope/decomp/__init__.py @@ -46,8 +46,7 @@ def __init__(self, test_group, resolution, coord_type, method): subdir = f'{coord_type}/{method}/{res_name}/{name}' super().__init__(test_group=test_group, name=name, subdir=subdir) - self.add_step(InitialState(test_case=self, resolution=resolution, - coord_type=coord_type)) + self.add_step(InitialState(test_case=self, resolution=resolution)) if coord_type == 'single_layer': damping_coeff = None diff --git a/compass/ocean/tests/drying_slope/drying_slope.cfg b/compass/ocean/tests/drying_slope/drying_slope.cfg index d8d4178852..698e8cbb71 100644 --- a/compass/ocean/tests/drying_slope/drying_slope.cfg +++ b/compass/ocean/tests/drying_slope/drying_slope.cfg @@ -26,10 +26,10 @@ min_pc_fraction = 0.1 nx = 6 # Length over which wetting and drying actually occur -Ly_analysis = 25. +ly_analysis = 25. # Domain length -Ly = 30. +ly = 30. # Bottom depth at the right side of the domain right_bottom_depth = 10. diff --git a/compass/ocean/tests/drying_slope/initial_state.py b/compass/ocean/tests/drying_slope/initial_state.py index 8849a7dd16..7fbda8502e 100644 --- a/compass/ocean/tests/drying_slope/initial_state.py +++ b/compass/ocean/tests/drying_slope/initial_state.py @@ -48,8 +48,8 @@ def run(self): section = config['drying_slope'] nx = section.getint('nx') - domain_length = section.getfloat('Ly') * 1e3 - drying_length = section.getfloat('Ly_analysis') * 1e3 + domain_length = section.getfloat('ly') * 1e3 + drying_length = section.getfloat('ly_analysis') * 1e3 plug_width_frac = section.getfloat('plug_width_frac') right_bottom_depth = section.getfloat('right_bottom_depth') left_bottom_depth = section.getfloat('left_bottom_depth') diff --git a/compass/ocean/tests/drying_slope/viz/__init__.py b/compass/ocean/tests/drying_slope/viz/__init__.py index 7b21d642c7..8a1e8e2045 100644 --- a/compass/ocean/tests/drying_slope/viz/__init__.py +++ b/compass/ocean/tests/drying_slope/viz/__init__.py @@ -160,7 +160,7 @@ def _plot_ssh_validation(self, times, tidx=None, outFolder='.'): mesh_ymean = ds_mesh.isel(Time=0).groupby('yCell').mean( dim=xr.ALL_DIMS) bottom_depth = mesh_ymean.bottomDepth.values - drying_length = self.config.getfloat('drying_slope', 'Ly_analysis') + drying_length = self.config.getfloat('drying_slope', 'ly_analysis') drying_length = drying_length * 1e3 x_offset = np.max(mesh_ymean.yCell.values) - drying_length x = (mesh_ymean.yCell.values - x_offset) / 1000.0 From 010295fe2a8d5dbdb45314a022967a8be831bf63 Mon Sep 17 00:00:00 2001 From: Carolyn Begeman Date: Mon, 16 Oct 2023 15:56:19 -0500 Subject: [PATCH 4/9] Update docs --- .../ocean/test_groups/drying_slope.rst | 32 +++++----- .../ocean/test_groups/drying_slope.rst | 61 ++++++++++++++----- 2 files changed, 61 insertions(+), 32 deletions(-) diff --git a/docs/developers_guide/ocean/test_groups/drying_slope.rst b/docs/developers_guide/ocean/test_groups/drying_slope.rst index aef6c4cd42..3b7667d914 100644 --- a/docs/developers_guide/ocean/test_groups/drying_slope.rst +++ b/docs/developers_guide/ocean/test_groups/drying_slope.rst @@ -34,13 +34,17 @@ defines a step for setting up the initial state for each test case. First, a mesh appropriate for the resolution is generated using :py:func:`mpas_tools.planar_hex.make_planar_hex_mesh()`. Then, the mesh is -culled to remove periodicity in the y direction. MPAS-Ocean is then run in init -mode. If the vertical coordinate is ``sigma``, the vertical grid configured -accordingly during init mode. During this init mode run, ssh is initialized -using the tidal forcing config options, and temperature and salinity are set -to constant values by default. (Namelist options may be modified to produce a -plug of different temperature values from the background, but this is not -employed in this test case.) +culled to remove periodicity in the y direction. The vertical grid is +configured according to the config options in the ``vertial_grid`` section. +The bottom depth is then set according to config options +``right_bottom_depth`` and ``left_bottom_depth``. The initial layer +thicknesses are set to the minimum thickness and the initial state is set to +a constant value by default according to the config options +``background_temperature`` and ``background_salinity``. Optionally, a mass of +warmer water can be initialized over part of the domain, a "plug," using +config options ``plug_width_frac`` and ``plug_width_temperature``. For current +configurations, tracer tendencies are off and these tracer options do not +affect the flow. forward ~~~~~~~ @@ -50,7 +54,9 @@ defines a step for running MPAS-Ocean from the initial condition produced in the ``initial_state`` step. If ``damping_coeff`` is provided as an argument to the constructor, the associate namelist option (``config_Rayleigh_damping_coeff``) will be given this value. MPAS-Ocean is run -in ``run()``. +in ``run()``. The time step is determined as a function of resolution by the +config option ``dt_per_km``. The number of tasks is determined as a function +of resolution by ``ntasks_baseline`` and ``min_tasks``. viz ~~~ @@ -112,16 +118,6 @@ Both ``sigma`` and ``single_layer`` coordinate types are supported. For runs at one value of the implicit bottom drag coefficient. -.. _dev_ocean_drying_slope_ramp: - -ramp ----- - -The :py:class:`compass.ocean.tests.drying_slope.ramp.Ramp` is identical to the -default class except it sets ``ramp`` to ``True`` for the forward step to enable -the ramp feature for wetting and drying. -.. _dev_ocean_drying_slope_log_law: - loglaw ------ diff --git a/docs/users_guide/ocean/test_groups/drying_slope.rst b/docs/users_guide/ocean/test_groups/drying_slope.rst index b3723053f2..7b0e66c165 100644 --- a/docs/users_guide/ocean/test_groups/drying_slope.rst +++ b/docs/users_guide/ocean/test_groups/drying_slope.rst @@ -52,32 +52,74 @@ The config options for this test case are: # Options related to the vertical grid [vertical_grid] + # the type of vertical grid + grid_type = uniform + + # Number of vertical levels + bottom_depth = 10. + # Number of vertical levels vert_levels = 10 - # The type of vertical coordinate (e.g. z-level, z-star) - coord_type = sigma + # Thickness of each layer in the thin film region + thin_film_thickness = 1.0e-3 + + # Whether to use "partial" or "full", or "None" to not alter the topography + partial_cell_type = None + + # The minimum fraction of a layer for partial cells + min_pc_fraction = 0.1 # config options for drying slope test cases [drying_slope] - # the number of grid cells in x and y + # the number of grid cells in x nx = 6 + # Length over which wetting and drying actually occur + Ly_analysis = 25. + + # Domain length + Ly = 30. + + # Bottom depth at the right side of the domain + right_bottom_depth = 10. + + # Bottom depth at the left side of the domain + left_bottom_depth = 0. + + # Plug width as a fraction of the domain + plug_width_frac = 0.0 + + # Plug temperature + plug_temperature = 20.0 + + # Background temperature + background_temperature = 20.0 + + # Background salinity + background_salinity = 35.0 + # time step in s per km of horizontal resolution dt_per_km = 30 + # Number of tasks at 1km resolution + ntasks_baseline = 4 + + # Minimum number of tasks + min_tasks = 1 + # config options for visualizing drying slope ouptut [drying_slope_convergence] resolutions = 0.25, 0.5, 1, 2 - + # config options for visualizing drying slope ouptut [drying_slope_viz] # whether to generate movie generate_movie = False - + # frames per second for movies frames_per_second = 30 @@ -118,15 +160,6 @@ processors and the results of each are compared. ``RES`` is either 250m or 1km. Rayleigh drag coefficient of 0.01. Rayleigh drag is not compatible with ``single_layer`` so implicit drag with a constant coefficient is used. -ramp ----- - -``ocean/drying_slope/${RES}/${COORD}/ramp`` is identical to the ``default`` -test except the factor that scales velocities and velocity tendencies is -ramped over a given layer thickness range rather than a binary switch at the -minimum thickness. ``RES`` is either 250m or 1km. ``COORD`` is either -``single_layer`` or ``sigma``. - loglaw ------ From 1b5bb72fdccfcf1536c81b7cbd4631a8dc01feb8 Mon Sep 17 00:00:00 2001 From: Carolyn Begeman Date: Tue, 17 Oct 2023 14:26:52 -0500 Subject: [PATCH 5/9] fixup initial state mesh size --- compass/ocean/tests/drying_slope/initial_state.py | 1 + 1 file changed, 1 insertion(+) diff --git a/compass/ocean/tests/drying_slope/initial_state.py b/compass/ocean/tests/drying_slope/initial_state.py index 7fbda8502e..6eb49acaac 100644 --- a/compass/ocean/tests/drying_slope/initial_state.py +++ b/compass/ocean/tests/drying_slope/initial_state.py @@ -72,6 +72,7 @@ def run(self): # be removed if resolution < 1.: ny += 2 + ny = 2 * round(ny / 2) logger.info(' * Make planar hex mesh') ds_mesh = make_planar_hex_mesh(nx=nx, ny=ny, dc=dc, From d3590df348043b204f6b72ce40c4ea4f35bc37a7 Mon Sep 17 00:00:00 2001 From: Carolyn Begeman Date: Sun, 22 Oct 2023 16:28:45 -0500 Subject: [PATCH 6/9] Explicit coriolis in initial state --- compass/ocean/tests/drying_slope/drying_slope.cfg | 3 +++ compass/ocean/tests/drying_slope/initial_state.py | 10 ++++++++++ docs/users_guide/ocean/test_groups/drying_slope.rst | 3 +++ 3 files changed, 16 insertions(+) diff --git a/compass/ocean/tests/drying_slope/drying_slope.cfg b/compass/ocean/tests/drying_slope/drying_slope.cfg index 698e8cbb71..6e592a127f 100644 --- a/compass/ocean/tests/drying_slope/drying_slope.cfg +++ b/compass/ocean/tests/drying_slope/drying_slope.cfg @@ -49,6 +49,9 @@ background_temperature = 20.0 # Background salinity background_salinity = 35.0 +# Coriolis parameter +coriolis_parameter = 0.0 + # time step in s per km of horizontal resolution dt_per_km = 30 diff --git a/compass/ocean/tests/drying_slope/initial_state.py b/compass/ocean/tests/drying_slope/initial_state.py index 6eb49acaac..3a3669717f 100644 --- a/compass/ocean/tests/drying_slope/initial_state.py +++ b/compass/ocean/tests/drying_slope/initial_state.py @@ -56,6 +56,7 @@ def run(self): plug_temperature = section.getfloat('plug_temperature') background_temperature = section.getfloat('background_temperature') background_salinity = section.getfloat('background_salinity') + coriolis_parameter = section.getfloat('coriolis_parameter') # Check config options if domain_length < drying_length: @@ -113,6 +114,15 @@ def run(self): plug_temperature, background_temperature) ds['tracer1'] = xr.where(y_cell < y_plug_boundary, 1.0, 0.0) ds['salinity'] = background_salinity * xr.ones_like(y_cell) + normalVelocity = xr.zeros_like(ds_mesh.xEdge) + normalVelocity, _ = xr.broadcast(normalVelocity, ds.refBottomDepth) + normalVelocity = normalVelocity.transpose('nEdges', 'nVertLevels') + normalVelocity = normalVelocity.expand_dims(dim='Time', axis=0) + ds['normalVelocity'] = normalVelocity + ds['fCell'] = coriolis_parameter * xr.ones_like(ds.xCell) + ds['fEdge'] = coriolis_parameter * xr.ones_like(ds.xEdge) + ds['fVertex'] = coriolis_parameter * xr.ones_like(ds.xVertex) + write_netcdf(ds, 'initial_state.nc') # Define the tidal boundary condition over 1-cell width diff --git a/docs/users_guide/ocean/test_groups/drying_slope.rst b/docs/users_guide/ocean/test_groups/drying_slope.rst index 7b0e66c165..050d3daad4 100644 --- a/docs/users_guide/ocean/test_groups/drying_slope.rst +++ b/docs/users_guide/ocean/test_groups/drying_slope.rst @@ -100,6 +100,9 @@ The config options for this test case are: # Background salinity background_salinity = 35.0 + # Coriolis parameter + coriolis_parameter = 0.0 + # time step in s per km of horizontal resolution dt_per_km = 30 From 66f203912256b3e9d5f7f0399f83f9afb1ef8c18 Mon Sep 17 00:00:00 2001 From: Carolyn Begeman Date: Mon, 27 Nov 2023 10:50:03 -0600 Subject: [PATCH 7/9] Add offest to drying_slope convergence analysis --- compass/ocean/tests/drying_slope/analysis.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compass/ocean/tests/drying_slope/analysis.py b/compass/ocean/tests/drying_slope/analysis.py index e852c11f30..cfc3f16952 100644 --- a/compass/ocean/tests/drying_slope/analysis.py +++ b/compass/ocean/tests/drying_slope/analysis.py @@ -91,7 +91,10 @@ def _compute_rmse(self, ds, t): ds = ds.drop_vars(np.setdiff1d([j for j in ds.variables], ['yCell', 'ssh'])) ds = ds.isel(Time=tidx) - x_mpas = ds.yCell.values / 1000.0 + drying_length = self.config.getfloat('drying_slope', 'ly_analysis') + drying_length = drying_length * 1e3 + x_offset = np.max(ds.yCell.values) - drying_length + x_mpas = (ds.yCell.values - x_offset) / 1000.0 ssh_mpas = ds.ssh.values # Interpolate mpas solution to the points at which we have an exact # solution From 4063b55551164063d7a5142f53bf2ed0cbd8222b Mon Sep 17 00:00:00 2001 From: Carolyn Begeman Date: Wed, 29 Nov 2023 15:53:21 -0600 Subject: [PATCH 8/9] Specify config option units --- compass/ocean/tests/drying_slope/drying_slope.cfg | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compass/ocean/tests/drying_slope/drying_slope.cfg b/compass/ocean/tests/drying_slope/drying_slope.cfg index 6e592a127f..cda6fc631b 100644 --- a/compass/ocean/tests/drying_slope/drying_slope.cfg +++ b/compass/ocean/tests/drying_slope/drying_slope.cfg @@ -10,7 +10,7 @@ bottom_depth = 10. # Number of vertical levels vert_levels = 10 -# Thickness of each layer in the thin film region +# Thickness of each layer in the thin film region in m thin_film_thickness = 1.0e-3 # Whether to use "partial" or "full", or "None" to not alter the topography @@ -25,16 +25,16 @@ min_pc_fraction = 0.1 # the number of grid cells in x nx = 6 -# Length over which wetting and drying actually occur +# Length over which wetting and drying actually occur in km ly_analysis = 25. -# Domain length +# Domain length in km ly = 30. -# Bottom depth at the right side of the domain +# Bottom depth at the right side of the domain in m right_bottom_depth = 10. -# Bottom depth at the left side of the domain +# Bottom depth at the left side of the domain in m left_bottom_depth = 0. # Plug width as a fraction of the domain @@ -64,6 +64,7 @@ min_tasks = 1 # config options for visualizing drying slope ouptut [drying_slope_convergence] +# horizontal resolutions in km resolutions = 0.25, 0.5, 1, 2 # config options for visualizing drying slope ouptut From e46fc72319ccb8a08baecdc5b7536723e5e8f962 Mon Sep 17 00:00:00 2001 From: Carolyn Begeman Date: Wed, 29 Nov 2023 15:53:36 -0600 Subject: [PATCH 9/9] fixup thin film thickness --- compass/ocean/tests/drying_slope/initial_state.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compass/ocean/tests/drying_slope/initial_state.py b/compass/ocean/tests/drying_slope/initial_state.py index 3a3669717f..09faa0d409 100644 --- a/compass/ocean/tests/drying_slope/initial_state.py +++ b/compass/ocean/tests/drying_slope/initial_state.py @@ -43,7 +43,7 @@ def run(self): # Fetch config options section = config['vertical_grid'] - thin_film_thickness = section.getfloat('thin_film_thickness') + 1.0e-9 + thin_film_thickness = section.getfloat('thin_film_thickness') vert_levels = section.getint('vert_levels') section = config['drying_slope']