Skip to content

Commit

Permalink
Merge pull request #501 from cbegeman/port-overflow-test-group
Browse files Browse the repository at this point in the history
Port overflow test group
  • Loading branch information
xylar authored Feb 9, 2023
2 parents d9c3eae + 8dee577 commit 0e09157
Show file tree
Hide file tree
Showing 20 changed files with 767 additions and 0 deletions.
2 changes: 2 additions & 0 deletions compass/ocean/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from compass.ocean.tests.isomip_plus import IsomipPlus
from compass.ocean.tests.merry_go_round import MerryGoRound
from compass.ocean.tests.nonhydro import Nonhydro
from compass.ocean.tests.overflow import Overflow
from compass.ocean.tests.planar_convergence import PlanarConvergence
from compass.ocean.tests.soma import Soma
from compass.ocean.tests.sphere_transport import SphereTransport
Expand Down Expand Up @@ -43,6 +44,7 @@ def __init__(self):
self.add_test_group(IsomipPlus(mpas_core=self))
self.add_test_group(MerryGoRound(mpas_core=self))
self.add_test_group(Nonhydro(mpas_core=self))
self.add_test_group(Overflow(mpas_core=self))
self.add_test_group(PlanarConvergence(mpas_core=self))
self.add_test_group(Soma(mpas_core=self))
self.add_test_group(SphereTransport(mpas_core=self))
Expand Down
46 changes: 46 additions & 0 deletions compass/ocean/tests/overflow/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from compass.testgroup import TestGroup
from compass.ocean.tests.overflow.default import Default
from compass.ocean.tests.overflow.rpe_test import RpeTest


class Overflow(TestGroup):
"""
A test group for General Ocean Turbulence Model (GOTM) 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='overflow')

self.add_test_case(Default(test_group=self, resolution='10km'))
self.add_test_case(RpeTest(test_group=self, resolution='2km'))


def configure(resolution, config):
"""
Modify the configuration options for one of the overflow test cases
Parameters
----------
resolution : str
The resolution of the test case
config : compass.config.CompassConfigParser
Configuration options for this test case
"""
width = config.getint('overflow', 'width')
length = config.getint('overflow', 'length')

dc = float(resolution[:-2])
nx = int(width/dc)
ny = int(length/dc)

config.set('overflow', 'nx', str(nx),
comment='the number of mesh cells in the x direction')
config.set('overflow', 'ny', str(ny),
comment='the number of mesh cells in the y direction')
config.set('overflow', 'dc', str(dc*1e3),
comment='the distance between adjacent cell centers')
45 changes: 45 additions & 0 deletions compass/ocean/tests/overflow/default/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from compass.testcase import TestCase
from compass.ocean.tests.overflow.initial_state import InitialState
from compass.ocean.tests.overflow.forward import Forward
from compass.ocean.tests import overflow
from compass.validate import compare_variables


class Default(TestCase):
"""
The default test case for the overflow test
Attributes
----------
resolution : str
The resolution of the test case
"""

def __init__(self, test_group, resolution):
"""
Create the test case
Parameters
----------
test_group : compass.ocean.tests.overflow.Overflow
The test group that this test case belongs to
"""
super().__init__(test_group=test_group, name='default',
subdir=f'{resolution}/default')
self.resolution = resolution
self.add_step(InitialState(test_case=self))
self.add_step(Forward(test_case=self, ntasks=4, openmp_threads=1))

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

def validate(self):
"""
Validate variables against a baseline
"""
compare_variables(test_case=self,
variables=['layerThickness', 'temperature'],
filename1='forward/output.nc')
74 changes: 74 additions & 0 deletions compass/ocean/tests/overflow/forward.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
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 overflow
test cases.
"""
def __init__(self, test_case, name='forward', subdir=None,
ntasks=1, min_tasks=None, openmp_threads=1, nu=None):
"""
Create a new test case
Parameters
----------
test_case : compass.TestCase
The test case this step belongs to
name : str
the name of the test case
subdir : str, optional
the subdirectory for the step. The default is ``name``
ntasks : int, optional
the number of tasks the step would ideally use. If fewer tasks
are available on the system, the step will run on all available
tasks as long as this is not below ``min_tasks``
min_tasks : int, optional
the number of tasks the step requires. If the system has fewer
than this number of tasks, the step will fail
openmp_threads : int, optional
the number of OpenMP threads the step will use
"""
if min_tasks is None:
min_tasks = ntasks
super().__init__(test_case=test_case, name=name, subdir=subdir,
ntasks=ntasks, min_tasks=min_tasks,
openmp_threads=openmp_threads)
self.add_namelist_file('compass.ocean.tests.overflow',
'namelist.forward')
if nu is not None:
# update the viscosity to the requested value
options = {'config_mom_del2': f'{nu}'}
self.add_namelist_options(options)

# make sure output is double precision
self.add_streams_file('compass.ocean.streams', 'streams.output')

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

self.add_input_file(filename='init.nc',
target='../initial_state/ocean.nc')
self.add_input_file(filename='mesh.nc',
target='../initial_state/culled_mesh.nc')
self.add_input_file(filename='graph.info',
target='../initial_state/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)
82 changes: 82 additions & 0 deletions compass/ocean/tests/overflow/initial_state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import xarray

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 overflow test
cases
"""
def __init__(self, test_case):
"""
Create the step
Parameters
----------
test_case : compass.testcase.Testcase
The test case this step belongs to
"""
super().__init__(test_case=test_case, name='initial_state', ntasks=1,
min_tasks=1, openmp_threads=1)

self.add_namelist_file('compass.ocean.tests.overflow',
'namelist.init', mode='init')

self.add_streams_file('compass.ocean.tests.overflow',
'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['overflow']
nx = section.getint('nx')
ny = section.getint('ny')
dc = section.getfloat('dc')

self.update_namelist_at_runtime(
{'config_overflow_dc': f'{dc}'})

logger.info(' * Make planar hex mesh')
ds_mesh = make_planar_hex_mesh(nx=nx, ny=ny, dc=dc, nonperiodic_x=True,
nonperiodic_y=False)
logger.info(' * Completed Make planar hex mesh')
write_netcdf(ds_mesh, 'base_mesh.nc')

logger.info(' * Cull mesh boundaries')
ds_mesh = cull(ds_mesh, logger=logger)
logger.info(' * Convert mesh')
ds_mesh = convert(ds_mesh, graphInfoFileName='culled_graph.info',
logger=logger)
logger.info(' * Completed Convert mesh')
write_netcdf(ds_mesh, 'culled_mesh.nc')

run_model(self, namelist='namelist.ocean',
streams='streams.ocean')

postrun_data = xarray.open_dataset('ocean.nc')
logger.info(' * Cull mesh dam boundaries')
postrun_data_cull = cull(postrun_data, logger=logger)
logger.info(' * Convert mesh')
postrun_data_cull = convert(postrun_data_cull,
graphInfoFileName='culled_graph.info',
logger=logger)
write_netcdf(postrun_data_cull, 'culled_mesh.nc')

run_model(self, namelist='namelist.ocean',
streams='streams.ocean')
7 changes: 7 additions & 0 deletions compass/ocean/tests/overflow/namelist.forward
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
config_dt='0000_00:01:00'
config_btr_dt='0000_00:00:09'
config_run_duration='0000_00:12:00'
config_use_cvmix_convection=.true.
config_implicit_bottom_drag_coeff=1.0e-2
config_use_mom_del2=.true.
config_mom_del2=1.0e3
4 changes: 4 additions & 0 deletions compass/ocean/tests/overflow/namelist.init
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
config_init_configuration='overflow'
config_overflow_use_distances=.true.
config_overflow_layer_type='sigma'
config_overflow_vert_levels=50
11 changes: 11 additions & 0 deletions compass/ocean/tests/overflow/overflow.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Options related to the overflow case
[overflow]

# The width of the domain in the across-slope dimension (km)
width = 40

# The length of the domain in the along-slope dimension (km)
length = 200

# Viscosity values to test for rpe test case
viscosities = 1, 5, 10, 100, 1000
71 changes: 71 additions & 0 deletions compass/ocean/tests/overflow/rpe_test/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from compass.testcase import TestCase
from compass.ocean.tests.overflow.initial_state import InitialState
from compass.ocean.tests.overflow.forward import Forward
from compass.ocean.tests.overflow.rpe_test.analysis import Analysis
from compass.ocean.tests import overflow


class RpeTest(TestCase):
"""
The reference potential energy (RPE) test case for the overflow
test group performs a 40h integration of the model forward in time at
5 different values of the viscosity at the given resolution.
Attributes
----------
resolution : str
The resolution of the test case
"""

def __init__(self, test_group, resolution='1km'):
"""
Create the test case
Parameters
----------
test_group : compass.ocean.tests.overflow.Overflow
The test group that this test case belongs to
"""
name = 'rpe_test'
subdir = f'{resolution}/{name}'
super().__init__(test_group=test_group, name=name,
subdir=subdir)

self.resolution = resolution
self.nus = None


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

overflow.configure(resolution, config)

nus = config.getlist('overflow', 'viscosities', dtype=float)
self.nus = nus

self.add_step(
InitialState(test_case=self))

for index, nu in enumerate(nus):
name = f'rpe_test_{index + 1}_nu_{int(nu)}'
step = Forward(
test_case=self, name=name, subdir=name,
ntasks=64, min_tasks=16, openmp_threads=1,
nu=float(nu))

step.add_namelist_file(
'compass.ocean.tests.overflow.rpe_test',
'namelist.forward')
step.add_streams_file(
'compass.ocean.tests.overflow.rpe_test',
'streams.forward')
self.add_step(step)

self.add_step(
Analysis(test_case=self, resolution=resolution, nus=nus))
# no run() is needed because we're doing the default: running all steps
Loading

0 comments on commit 0e09157

Please sign in to comment.