Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port overflow test group #501

Merged
merged 20 commits into from
Feb 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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