Skip to content

Commit

Permalink
Merge pull request #352 from cbegeman/add-drying-slope-case
Browse files Browse the repository at this point in the history
Add drying slope case
  • Loading branch information
xylar authored May 3, 2022
2 parents 6ab6483 + 98ec328 commit e829ea1
Show file tree
Hide file tree
Showing 20 changed files with 878 additions and 0 deletions.
2 changes: 2 additions & 0 deletions compass/ocean/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from compass.mpas_core import MpasCore
from compass.ocean.tests.baroclinic_channel import BaroclinicChannel
from compass.ocean.tests.drying_slope import DryingSlope
from compass.ocean.tests.global_convergence import GlobalConvergence
from compass.ocean.tests.global_ocean import GlobalOcean
from compass.ocean.tests.gotm import Gotm
Expand All @@ -24,6 +25,7 @@ def __init__(self):
super().__init__(name='ocean')

self.add_test_group(BaroclinicChannel(mpas_core=self))
self.add_test_group(DryingSlope(mpas_core=self))
self.add_test_group(GlobalConvergence(mpas_core=self))
self.add_test_group(GlobalOcean(mpas_core=self))
self.add_test_group(Gotm(mpas_core=self))
Expand Down
21 changes: 21 additions & 0 deletions compass/ocean/tests/drying_slope/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from compass.testgroup import TestGroup
from compass.ocean.tests.drying_slope.default import Default


class DryingSlope(TestGroup):
"""
A test group for drying slope (wetting-and-drying) test cases
"""

def __init__(self, mpas_core):
"""
mpas_core : compass.MpasCore
the MPAS core that this test group belongs to
"""
super().__init__(mpas_core=mpas_core, name='drying_slope')

for resolution in [0.25, 1]:
for coord_type in ['sigma']:
self.add_test_case(
Default(test_group=self, resolution=resolution,
coord_type=coord_type))
69 changes: 69 additions & 0 deletions compass/ocean/tests/drying_slope/default/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from compass.testcase import TestCase
from compass.ocean.tests.drying_slope.initial_state import InitialState
from compass.ocean.tests.drying_slope.forward import Forward
from compass.ocean.tests.drying_slope.viz import Viz


class Default(TestCase):
"""
The default drying_slope test case
Attributes
----------
resolution : float
The resolution of the test case in km
coord_type : str
The type of vertical coordinate (``sigma``, ``single_layer``, etc.)
"""

def __init__(self, test_group, resolution, coord_type):
"""
Create the test case
Parameters
----------
test_group : compass.ocean.tests.drying_slope.DryingSlope
The test group that this test case belongs to
resolution : float
The resolution of the test case in km
coord_type : str
The type of vertical coordinate (``sigma``, ``single_layer``)
"""
name = 'default'

self.resolution = resolution
self.coord_type = coord_type
if resolution < 1.:
res_name = f'{int(resolution*1e3)}m'
else:
res_name = f'{int(resolution)}km'
subdir = f'{res_name}/{coord_type}/{name}'
super().__init__(test_group=test_group, name=name,
subdir=subdir)

self.add_step(InitialState(test_case=self))
for damping_coeff in [0.0025, 0.01]:
self.add_step(Forward(test_case=self, resolution=resolution,
cores=4, threads=1,
damping_coeff=damping_coeff))
self.add_step(Viz(test_case=self))

def configure(self):
"""
Modify the configuration options for this test case.
"""

resolution = self.resolution
config = self.config
ny = round(28 / resolution)
if resolution < 1.:
ny += 2
dc = 1e3 * resolution

config.set('drying_slope', 'ny', f'{ny}', comment='the number of '
'mesh cells in the y direction')
config.set('drying_slope', 'dc', f'{dc}', comment='the distance '
'between adjacent cell centers')
26 changes: 26 additions & 0 deletions compass/ocean/tests/drying_slope/drying_slope.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Options related to the vertical grid
[vertical_grid]

# Number of vertical levels
vert_levels = 10

# The type of vertical coordinate (e.g. z-level, z-star)
coord_type = sigma

# config options for drying slope test cases
[drying_slope]

# the number of grid cells in x
nx = 6

# 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

# movie format
movie_format = mp4
93 changes: 93 additions & 0 deletions compass/ocean/tests/drying_slope/forward.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
from compass.model import run_model
from compass.step import Step


class Forward(Step):
"""
A step for performing forward MPAS-Ocean runs as part of drying slope
test cases.
"""
def __init__(self, test_case, resolution, name='forward', subdir=None,
cores=1, min_cores=None, threads=1, damping_coeff=None):
"""
Create a new test case
Parameters
----------
test_case : compass.TestCase
The test case this step belongs to
resolution : str
The resolution of the test case
name : str
the name of the test case
subdir : str, optional
the subdirectory for the step. The default is ``name``
cores : int, optional
the number of cores the step would ideally use. If fewer cores
are available on the system, the step will run on all available
cores as long as this is not below ``min_cores``
min_cores : int, optional
the number of cores the step requires. If the system has fewer
than this number of cores, the step will fail
threads : int, optional
the number of threads the step will use
damping_coeff: float, optional
the value of the rayleigh damping coefficient
"""
if min_cores is None:
min_cores = cores
if damping_coeff is not None:
name = f'{name}_{damping_coeff}'

super().__init__(test_case=test_case, name=name, subdir=subdir,
cores=cores, min_cores=min_cores, threads=threads)

self.add_namelist_file('compass.ocean.tests.drying_slope',
'namelist.forward')
if resolution < 1.:
res_name = f'{int(resolution*1e3)}m'
else:
res_name = f'{int(resolution)}km'
self.add_namelist_file('compass.ocean.tests.drying_slope',
f'namelist.{res_name}.forward')
if damping_coeff is not None:
# update the Rayleigh damping coeff to the requested value
options = {'config_Rayleigh_damping_coeff': f'{damping_coeff}'}
self.add_namelist_options(options)

self.add_streams_file('compass.ocean.tests.drying_slope',
'streams.forward')

input_path = '../initial_state'
self.add_input_file(filename='mesh.nc',
target=f'{input_path}/culled_mesh.nc')

self.add_input_file(filename='init.nc',
target=f'{input_path}/ocean.nc')

self.add_input_file(filename='forcing.nc',
target=f'{input_path}/init_mode_forcing_data.nc')

self.add_input_file(filename='graph.info',
target=f'{input_path}/culled_graph.info')

self.add_model_as_input()

self.add_output_file(filename='output.nc')

# no setup() is needed

def run(self):
"""
Run this step of the test case
"""

run_model(self)
67 changes: 67 additions & 0 deletions compass/ocean/tests/drying_slope/initial_state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import xarray
import numpy

from mpas_tools.planar_hex import make_planar_hex_mesh
from mpas_tools.io import write_netcdf
from mpas_tools.mesh.conversion import convert, cull

from compass.step import Step
from compass.model import run_model


class InitialState(Step):
"""
A step for creating a mesh and initial condition for drying slope test
cases
"""
def __init__(self, test_case):
"""
Create the step
Parameters
----------
test_case : compass.ocean.tests.drying_slope.default.Default
The test case this step belongs to
"""
super().__init__(test_case=test_case, name='initial_state', cores=1,
min_cores=1, threads=1)

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']:
self.add_output_file(file)

self.add_model_as_input()

def run(self):
"""
Run this step of the test case
"""
config = self.config
logger = self.logger

section = config['drying_slope']
nx = section.getint('nx')
ny = section.getint('ny')
dc = section.getfloat('dc')

logger.info(' * Make planar hex mesh')
dsMesh = 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')

logger.info(' * Cull mesh')
dsMesh = cull(dsMesh, logger=logger)
logger.info(' * Convert mesh')
dsMesh = convert(dsMesh, 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')
1 change: 1 addition & 0 deletions compass/ocean/tests/drying_slope/namelist.1km.forward
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
config_dt='0000_00:00:30'
1 change: 1 addition & 0 deletions compass/ocean/tests/drying_slope/namelist.250m.forward
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
config_dt='0000_00:00:08'
26 changes: 26 additions & 0 deletions compass/ocean/tests/drying_slope/namelist.forward
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
config_run_duration='0000_12:00:01'
config_time_integrator='RK4'
config_use_tidal_forcing=.true.
config_use_tidal_forcing_tau=60.0
config_tidal_forcing_type='direct'
config_tidal_forcing_model='monochromatic'
config_tidal_forcing_monochromatic_amp=10.0
config_tidal_forcing_monochromatic_period=1.0
config_tidal_forcing_monochromatic_baseline=10.0
config_eos_linear_alpha=0.0
config_eos_linear_beta=0.0
config_vert_coord_movement='impermeable_interfaces'
config_ALE_thickness_proportionality='weights_only'
config_use_wetting_drying=.true.
config_prevent_drying=.true.
config_drying_min_cell_height=1.0e-3
config_zero_drying_velocity=.true.
config_verify_not_dry=.true.
config_thickness_flux_type='upwind'
config_use_cvmix=.false.
config_Rayleigh_friction=.true.
config_Rayleigh_damping_depth_variable=.true.
config_Rayleigh_damping_coeff=0.0025
config_use_implicit_bottom_drag=.false.
config_use_debugTracers=.true.
config_check_ssh_consistency=.true.
12 changes: 12 additions & 0 deletions compass/ocean/tests/drying_slope/namelist.init
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
config_init_configuration='tidal_boundary'
config_ocean_run_mode = 'init'
config_tidal_boundary_vert_levels=10
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_drying_min_cell_height=1.000001e-3
config_use_tidal_forcing=.true.
config_write_cull_cell_mask=.false.
41 changes: 41 additions & 0 deletions compass/ocean/tests/drying_slope/streams.forward
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<streams>

<immutable_stream name="mesh"
filename_template="mesh.nc"/>

<immutable_stream name="input"
filename_template="init.nc"/>

<immutable_stream name="restart"
type="input;output"
filename_template="restarts/restart.$Y-$M-$D_$h.$m.$s.nc"
filename_interval="output_interval"
reference_time="0001-01-01_00:00:00"
clobber_mode="truncate"
input_interval="initial_only"
output_interval="0005_00:00:00"/>

<stream name="forcing"
filename_template="forcing.nc"
input_interval="initial_only"
type="input">
<var name="tidalInputMask"/>
</stream>

<stream name="output"
type="output"
filename_template="output.nc"
output_interval="0000-00-00_00:12:00"
clobber_mode="truncate">

<stream name="mesh"/>
<var_struct name="tracers"/>
<var name="layerThickness"/>
<var name="ssh"/>
<var name="normalVelocity"/>
<var name="xtime"/>
<var name="zMid"/>
<var name="tidalInputMask"/>
</stream>

</streams>
Loading

0 comments on commit e829ea1

Please sign in to comment.