Skip to content

Commit

Permalink
Remove resolution configuration option for SmokeTest.
Browse files Browse the repository at this point in the history
    - Removed the resolution option, and the configuration file as
      a whole for the `SmokeTest`. Instead supported resolutions
      are added as different test cases, with a different `subdir`
      for each resolution. Per Xylar, this is more standard practice
      for actual "test". (c.f. SpinUp which is more meant to set up
      files for longer run outside of `compass`, where arbitary
      resolution is fine.

    - Added comment about equilateral trinagles, per Trevor request.

    - Minor stylistic changes based on a limited review with Xylar.
  • Loading branch information
andrewdnolan committed Feb 1, 2024
1 parent 7025f22 commit c6d5cef
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 129 deletions.
62 changes: 3 additions & 59 deletions compass/landice/tests/mismipplus/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import os

from compass.landice.tests.mismipplus.smoke_test import SmokeTest
from compass.landice.tests.mismipplus.spin_up import SpinUp
from compass.testgroup import TestGroup
Expand All @@ -16,62 +14,8 @@ def __init__(self, mpas_core):
"""
super().__init__(mpas_core=mpas_core, name='mismipplus')

self.add_test_case(SmokeTest(test_group=self))

self.add_test_case(SpinUp(test_group=self))


def configure(step, config, resolution):
"""
This function will create a common and consitent directory structure
for all test cases within this test group. The direcotry structure will
based on the requested resolution, enabling the user to run the testcases
multiple times at different resolutions. ``compass setup`` will need to be
run for each desired resolution.
Note: this function does not return anything. Instead it modifies the
``step`` and ``config``, which are passed to it.
Parameters
----------
step : compass.step
config : compass.config.CompassConfigParser
Configuration options for the test case, including custom configuration
options passed via the ``-f`` flag at the time of ``compass setup``
resolution : float
The requested (nominal) resolution. Directory strcture will include
this value in it. See comment in configuration file for more details
about what "nominal" resolution means.
"""

# format resolution for creating subdirectory structure
resolution_key = f'{resolution:4.0f}m'
step.subdir = f'{resolution_key}/{step.name}'

# set the path attribute, based on the subdir attribute set above.
step.path = os.path.join(step.mpas_core.name,
step.test_group.name,
step.test_case.subdir,
step.subdir)

# NOTE: we do not set the `step.work_dir` attribute, since it will be set
# by `compass setup`` by joining the work dir provided through the command
# line interface and the `step.path` set above.

# store the resolution (at the time of `compass setup`) as an attribute.
# This is needed to prevent the changing of resolution between
# `compass setup` and `compas run`, which could result in a mesh having
# a different resolution than the direcotry it sits in.
step.resolution = resolution

comment = ("Nominal cell spacing (m) at the time of `compass setup`. \n"
"NOTE: the resolution can not be changed after this point. \n"
"To run another resolution, rerun `compass setup` with the \n"
"desired nominal resolution. Resolution is \"nominal\" since \n"
"the true cell spacing will be determined such that the cell \n"
"center to cell center length of the entire domain in the y \n"
"direction is exactly the required y domain length (80 km).")

config.set('mesh', 'resolution', str(resolution), comment=comment)
for resolution in [2000]:
self.add_test_case(SmokeTest(test_group=self,
resolution=resolution))
24 changes: 17 additions & 7 deletions compass/landice/tests/mismipplus/run_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ class RunModel(Step):
twice, the second time with ``namelist.landice.rst`` and
``streams.landice.rst``
resolution : int
The nominal distance [m] between horizontal grid points (dcEdge) at
the time of ``compass setup``
resolution : float
The nominal distance [m] between horizontal grid points (dcEdge).
"""
def __init__(self, test_case, name, subdir=None, ntasks=1,
min_tasks=None, openmp_threads=1, suffixes=None):
def __init__(self, test_case, name, subdir=None, resolution=None,
ntasks=1, min_tasks=None, openmp_threads=1, suffixes=None):
"""
Create a new test case
Expand All @@ -43,6 +42,12 @@ def __init__(self, test_case, name, subdir=None, ntasks=1,
subdir : str, optional
the subdirectory for the step. The default is ``name``
resolution : float, optional
The nominal distance [m] between horizontal grid points (dcEdge).
For the ``SpinUp`` testcase no value should be passed. Instead the
value will be parsed from the configuration options at the
time of ``compass setup``.
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
Expand All @@ -67,6 +72,11 @@ def __init__(self, test_case, name, subdir=None, ntasks=1,
if suffixes is None:
suffixes = ['landice']
self.suffixes = suffixes

if resolution is None:
resolution = 0.0
self.resolution = resolution

if min_tasks is None:
min_tasks = ntasks

Expand Down Expand Up @@ -102,8 +112,8 @@ def setup(self):
"""

config = self.config
# get the resolution from the parsed config file(s)
resolution = config.getfloat('mesh', 'resolution')
# use the resolution at the time of ``compass setup``
resolution = self.resolution

# default gutter_length is 0. This encompasses `SmokeTest`, which does
# not use the gutter_length option.
Expand Down
23 changes: 13 additions & 10 deletions compass/landice/tests/mismipplus/setup_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,15 @@ def run(self):
# check if the resolution has been changed since the `compass setup`
# command was run
if self.resolution != resolution:
raise Exception(f'Resolution was set at {self.resolution:4.0f}m'
f' when `compass setup` was called. Since then,'
f' the resolution in the configuration file has'
f' been changed to {resolution:4.0f}m. Changing'
f' resolution at runtime is not supported. Change'
f' the resolution value in the configuration file'
f' within the python module and rerun the `compass'
f' setup` command in order to create a mesh at a'
f' resolution of {resolution:4.0f}m')
raise ValueError(f'Resolution was set at {self.resolution:4.0f}m'
f' when `compass setup` was called. Since then,'
f' the resolution in the configuration file has'
f' been changed to {resolution:4.0f}m. Changing'
f' resolution at runtime is not supported. Change'
f' the resolution value in the configuration file'
f' within the python module and rerun the'
f' `compass setup` command in order to create'
f' a mesh at a resolution of {resolution:4.0f}m')

nx, ny, dc = calculate_mesh_params(nominal_resolution=resolution,
Lx=Lx,
Expand Down Expand Up @@ -331,7 +331,10 @@ def center_trough(ds_mesh):
if ds_mesh.dcEdge.all():
dc = float(ds_mesh.dcEdge[0])

# get the distance between edges
# get the distance between edges. Since all meshes are generated with the
# `make_planar_hex_mesh` function, all triangles (in the dual mesh) will
# be equilateral, which makes our use of `3` in the denominator below
# a valid assumption.
de = 0.5 * dc * np.sin(np.pi / 3)
# find the min and max (i.e. N/S boundary) edges
y_min = ds_mesh.yEdge.min()
Expand Down
53 changes: 15 additions & 38 deletions compass/landice/tests/mismipplus/smoke_test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class SmokeTest(TestCase):
spin-up that has previously been run to steady state
"""

def __init__(self, test_group):
def __init__(self, test_group, resolution):
"""
Create the test case
Expand All @@ -22,54 +22,31 @@ def __init__(self, test_group):
test_group : compass.landice.tests.mismipplus.MISMIPplus
The test group that this test case belongs to
resolution : float
The resolution of the test case. Valid options are defined in the
test group constructor.
"""
name = 'smoke_test'
super().__init__(test_group=test_group, name=name)
subdir = f"{name}/{resolution:4.0f}m"

step = RunModel(test_case=self, name=name, openmp_threads=1)
super().__init__(test_group=test_group, name=name, subdir=subdir)

# download and link the mesh
step_name = 'run_model'
step = RunModel(test_case=self, name=step_name, resolution=resolution)

# download and link the mesh, eventually this will need to be
# resolution aware. ``configure`` method is probably a better place
# for parsing and adding the correct IC file based on resolution.
step.mesh_file = 'landice_grid.nc'
step.add_input_file(filename=step.mesh_file,
target='MISMIP_2km_20220502.nc',
database='')

self.add_step(step)

# no run() method is needed

def configure(self):
"""
Set up the directory structure, based on the requested resolution.
Also ensure the requested resolution is supported (i.e. that a spun-up
restart file exists for the resoltion).
"""
# list of currently supported resolutions
supported_resolutions = [2000]
# no configure() method is needed (for now)

# make a formatted list (of floats) for the supported resolutions.
# this will displayed by the `ValueError` if an unsupported
# resolution is requested.
supp_res_str = ", ".join([f"{x:4.0f}" for x in supported_resolutions])

# get the config options from the TestCase, which
config = self.config
# get the resolution from the parsed config file(s)
resolution = config.getfloat('mesh', 'resolution')

# make sure the requested resolution is one that supported.
# i.e. a resolution for which a spun-up initial condition file exists.
if resolution not in supported_resolutions:
raise ValueError(f'The requested resolution of {resolution:4.0f}'
f' (m) is not supported for the `SmokeTest`'
f' Supported resolutions are {supp_res_str} (m).'
)

# loop over the steps of the `TestCase` and create a consitent
# directory structure based on the value of `resolution` at the time
# of compass setup.
for step in self.steps.values():
mismipplus.configure(step, config, resolution)
# no run() method is needed

def validate(self):
"""
Expand All @@ -82,7 +59,7 @@ def validate(self):

# access the work_dir for the step, even though validation
# operates at the case level
output_path = self.steps["smoke_test"].work_dir
output_path = self.steps["run_model"].work_dir

compare_variables(test_case=self, variables=variables,
filename1=f'{output_path}/output.nc',
Expand Down
6 changes: 0 additions & 6 deletions compass/landice/tests/mismipplus/smoke_test/smoke_test.cfg

This file was deleted.

24 changes: 22 additions & 2 deletions compass/landice/tests/mismipplus/spin_up/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

from compass.config import CompassConfigParser
from compass.landice.tests import mismipplus
from compass.landice.tests.mismipplus.run_model import RunModel
Expand Down Expand Up @@ -59,8 +61,26 @@ def configure(self):
# of compass setup.
for step_name, step in self.steps.items():

# set up the directory structure
mismipplus.configure(step, config, resolution)
# format resolution for creating subdirectory structure
resolution_key = f'{resolution:4.0f}m'
step.subdir = f'{resolution_key}/{step.name}'

# set the path attribute, based on the subdir attribute set above.
step.path = os.path.join(step.mpas_core.name,
step.test_group.name,
step.test_case.subdir,
step.subdir)

# NOTE: we do not set the `step.work_dir` attribute, since it
# will be set by `compass setup`` by joining the work dir
# provided through the command line interface and the
# `step.path` set above.

# store the resolution (at the time of `compass setup`) as an
# attribute. This is needed to prevent the changing of resolution
# between `compass setup` and `compas run`, which could result
# in a mesh having a different resolution than the dir it sits in.
step.resolution = resolution

# read the density value from config file and update the namelist
if step_name == "run_model":
Expand Down
7 changes: 0 additions & 7 deletions compass/landice/tests/mismipplus/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,6 @@ def get_ntasks_from_cell_count(config, cell_count):
Number of horizontal cells in the mesh. The value of this parameter is
caclulated (or approximated) using the functions below.
resolution: float
Nominal resolution (m) requested at the time of ``compass setup``.
gutter_length: float
Lenght (m) to extend the eastern edge of the domain by. See config
file for more info.
Returns
-------
ntasks : int
Expand Down

0 comments on commit c6d5cef

Please sign in to comment.