Skip to content

Commit

Permalink
Merge pull request #452 from cbegeman/port-merrygoround-from-legacy
Browse files Browse the repository at this point in the history
Port merry-go-round test group from legacy
  • Loading branch information
xylar authored Nov 18, 2022
2 parents d4c0c3c + 5fda332 commit 2a96263
Show file tree
Hide file tree
Showing 18 changed files with 901 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 @@ -9,6 +9,7 @@
from compass.ocean.tests.internal_wave import InternalWave
from compass.ocean.tests.ice_shelf_2d import IceShelf2d
from compass.ocean.tests.isomip_plus import IsomipPlus
from compass.ocean.tests.merry_go_round import MerryGoRound
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 @@ -38,6 +39,7 @@ def __init__(self):
self.add_test_group(InternalWave(mpas_core=self))
self.add_test_group(IceShelf2d(mpas_core=self))
self.add_test_group(IsomipPlus(mpas_core=self))
self.add_test_group(MerryGoRound(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
19 changes: 19 additions & 0 deletions compass/ocean/tests/merry_go_round/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from compass.testgroup import TestGroup
from compass.ocean.tests.merry_go_round.default import Default
from compass.ocean.tests.merry_go_round.convergence_test import ConvergenceTest


class MerryGoRound(TestGroup):
"""
A test group for tracer advection test cases "merry-go-round"
"""

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='merry_go_round')

self.add_test_case(Default(test_group=self))
self.add_test_case(ConvergenceTest(test_group=self))
35 changes: 35 additions & 0 deletions compass/ocean/tests/merry_go_round/convergence_test/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from compass.testcase import TestCase
from compass.ocean.tests.merry_go_round.initial_state import InitialState
from compass.ocean.tests.merry_go_round.forward import Forward
from compass.ocean.tests.merry_go_round.viz import Viz
from compass.ocean.tests.merry_go_round.convergence_test.analysis \
import Analysis
from compass.ocean.tests import merry_go_round
from compass.validate import compare_variables


class ConvergenceTest(TestCase):
"""
The convergence test case for the merry-go-round test
"""

def __init__(self, test_group):
"""
Create the test case
Parameters
----------
test_group : compass.ocean.tests.merry_go_round.MerryGoRound
The test group that this test case belongs to
"""
super().__init__(test_group=test_group, name='convergence_test')
resolutions = ['1.25m', '2.5m', '5m']
for resolution in resolutions:
self.add_step(InitialState(test_case=self, resolution=resolution,
name=f'initial_state_{resolution}'))
self.add_step(Forward(test_case=self, resolution=resolution,
ntasks=4, openmp_threads=1,
name=f'forward_{resolution}'))
self.add_step(Viz(test_case=self, resolution=resolution,
name=f'viz_{resolution}'))
self.add_step(Analysis(test_case=self, resolutions=resolutions))
101 changes: 101 additions & 0 deletions compass/ocean/tests/merry_go_round/convergence_test/analysis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import math
import numpy
import xarray
import matplotlib
import matplotlib.pyplot as plt
import cmocean

from compass.step import Step


class Analysis(Step):
"""
A step for plotting the convergence of the solution with resolution and
time step in the merry-go-round test group
Attributes
----------
resolution : str
The resolution of the test case
"""
def __init__(self, test_case, resolutions, name='analysis'):
"""
Create the step
Parameters
----------
test_case : compass.TestCase
The test case this step belongs to
resolutions : list of str
The resolutions of the test case
name: str
The name of the step
"""
super().__init__(test_case=test_case, name=name)

self.resolutions = resolutions

self.add_output_file(filename='convergence_plot.png')

def run(self):
"""
Run this step of the test case
"""
_plot(self.outputs[0], self.resolutions)


def _plot(filename, resolutions):
"""
Plot section of the merry-go-round TODO
Parameters
----------
filename : str
The output file name
resolutions : list of str
The resolutions of the test case
"""
plt.switch_backend('Agg')
fig = plt.gcf()
dt = [3, 6, 12]
order2 = [0.01, 0.04, 0.16]
fields = ['tracer1']

L2 = numpy.zeros((len(resolutions)))

for k, field in enumerate(fields):
for i, resolution in enumerate(resolutions):
ds = xarray.open_dataset(f'../forward_{resolution}/output.nc')

areaCell = ds.areaCell.values
final_field = ds[field].isel(Time=1, nVertLevels=0).values
initial_field = ds[field].isel(Time=0, nVertLevels=0).values

diff = abs(final_field - initial_field)
multDen = (initial_field**2)*areaCell
multNum = (diff**2)*areaCell
denL2 = numpy.sum(multDen)/numpy.sum(areaCell)
numL2 = numpy.sum(multNum)/numpy.sum(areaCell)

L2[i] = numpy.sqrt(numL2)/numpy.sqrt(denL2)

print(f'Order of convergence from dt 6 min to 3 min: ',
f'{math.log2(L2[0]/L2[1])}')
print(f'Order of convergence from dt 12 min to 6 min: ',
f'{math.log2(L2[1]/L2[2])}')

plt.loglog(dt, L2[:], '-x', label=f'Simulated {field}')

plt.loglog(dt, order2, 'k', label='Order 2 convergence')
plt.title('Convergence to the exact solution')
plt.ylabel('l_2 error norm')
plt.legend()
plt.grid()
plt.xticks(dt, dt)
plt.xlabel('time step (min)')

plt.savefig(filename)
39 changes: 39 additions & 0 deletions compass/ocean/tests/merry_go_round/default/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from compass.testcase import TestCase
from compass.ocean.tests.merry_go_round.initial_state import InitialState
from compass.ocean.tests.merry_go_round.forward import Forward
from compass.ocean.tests.merry_go_round.viz import Viz
from compass.ocean.tests import merry_go_round
from compass.validate import compare_variables


class Default(TestCase):
"""
The default test case for the merry-go-round test
"""

def __init__(self, test_group):
"""
Create the test case
Parameters
----------
test_group : compass.ocean.tests.merry_go_round.MerryGoRound
The test group that this test case belongs to
"""
super().__init__(test_group=test_group, name='default')
self.resolution = '5m'
self.add_step(InitialState(test_case=self, resolution=self.resolution,
name=f'initial_state_{self.resolution}'))
self.add_step(Forward(test_case=self, resolution=self.resolution,
ntasks=4, openmp_threads=1,
name=f'forward_{self.resolution}'))
self.add_step(Viz(test_case=self, resolution=self.resolution,
name=f'viz_{self.resolution}'))

def validate(self):
"""
Validate variables against a baseline
"""
compare_variables(test_case=self,
variables=['normalVelocity', 'tracer1'],
filename1=f'forward_{self.resolution}/output.nc')
81 changes: 81 additions & 0 deletions compass/ocean/tests/merry_go_round/forward.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
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 merry-go-round
test cases.
Attributes
----------
resolution : str
The resolution of the test case
"""
def __init__(self, test_case, resolution='5m', name='forward', subdir=None,
ntasks=1, min_tasks=None, openmp_threads=1):
"""
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``
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
"""
self.resolution = resolution
if min_tasks is None:
min_tasks = ntasks

run_params = {'5m': {'config_dt': '00:12:00'},
'2.5m': {'config_dt': '00:06:00'},
'1.25m': {'config_dt': '00:03:00'}}

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.merry_go_round',
'namelist.forward')
self.add_namelist_options(options=run_params[self.resolution])

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

self.add_input_file(filename='init.nc',
target=f'../initial_state_{resolution}/init.nc')
self.add_input_file(filename='graph.info',
target=f'../initial_state_{resolution}/'
'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)
Loading

0 comments on commit 2a96263

Please sign in to comment.