Skip to content

Commit

Permalink
Merge pull request #236 from cbegeman/enhance-convergence-tasks
Browse files Browse the repository at this point in the history
Add convergence tasks for space and time only

This PR extends the convergence test framework to accommodate convergence in space, time or both. This PR also adds additional tests for space-only and time-only convergence for the cosine_bell, geostrophic, manufactured_solution, and inertial_gravity_wave groups. The convergence_time cases have not been optimized (in terms of resolution and time steps) nor have separate convergence thresholds been specified.
  • Loading branch information
cbegeman authored Nov 25, 2024
2 parents cd94c14 + 9fe597a commit a44d4b8
Show file tree
Hide file tree
Showing 39 changed files with 1,068 additions and 492 deletions.
27 changes: 15 additions & 12 deletions docs/developers_guide/ocean/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,18 +313,21 @@
.. autosummary::
:toctree: generated/
ConvergenceForward
ConvergenceForward.compute_cell_count
ConvergenceForward.dynamic_model_config
ConvergenceAnalysis
ConvergenceAnalysis.compute_error
ConvergenceAnalysis.convergence_parameters
ConvergenceAnalysis.exact_solution
ConvergenceAnalysis.get_output_field
ConvergenceAnalysis.plot_convergence
ConvergenceAnalysis.run
ConvergenceAnalysis.setup
get_resolution_for_tasks
get_timestep_for_tasks
forward.ConvergenceForward
forward.ConvergenceForward.compute_cell_count
forward.ConvergenceForward.dynamic_model_config
analysis.ConvergenceAnalysis
analysis.ConvergenceAnalysis.compute_error
analysis.ConvergenceAnalysis.convergence_parameters
analysis.ConvergenceAnalysis.exact_solution
analysis.ConvergenceAnalysis.get_output_field
analysis.ConvergenceAnalysis.plot_convergence
analysis.ConvergenceAnalysis.run
analysis.ConvergenceAnalysis.setup
```
### Spherical Convergence Tests

Expand Down
51 changes: 45 additions & 6 deletions docs/developers_guide/ocean/framework.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,16 +219,35 @@ tests on {ref}`dev-ocean-spherical-meshes` and planar meshes.
The ocean framework includes shared config options and base classes for
forward and analysis steps that are expected to be useful across these tests.

The key config options that control the convergence test are `base_resolution`
and `refinement_factors`. The `base_resolution` is multipled by the
`refinement_factors` to determine which resolutions to test when the
convergence is being tested in space (or space and time together). The
`base_resolution` is applied to all steps when convergence in time is tested.
`base_resolution` times `dt_per_km` determines the base timestep in that case
and is then multiplied by the `refinement_factors` to determine which time steps
to test. When spherical meshes are being tested, the values in the
`convergence` section are overridden by their values in the
`spherical_convergence` section with a prefix indicating the mesh type.

The shared config options are:
```cfg
# config options for spherical convergence tests
[spherical_convergence]
# The base resolution for the icosahedral mesh to which the refinement
# factors are applied
icos_base_resolution = 60.
# a list of icosahedral mesh resolutions (km) to test
icos_resolutions = 60, 120, 240, 480
icos_refinement_factors = 8., 4., 2., 1.
# The base resolution for the quasi-uniform mesh to which the refinement
# factors are applied
qu_base_resolution = 120.
# a list of quasi-uniform mesh resolutions (km) to test
qu_resolutions = 60, 90, 120, 150, 180, 210, 240
qu_refinement_factors = 0.5, 0.75, 1., 1.25, 1.5, 1.75, 2.
[convergence]
Expand All @@ -241,6 +260,15 @@ convergence_thresh = 1.0
# Type of error to compute
error_type = l2
# the base mesh resolution (km) to which refinement_factors
# are applied if refinement is 'space' or 'both' on a planar mesh
# base resolutions for spherical meshes are given in section spherical_convergence
base_resolution = 120
# refinement factors for a planar mesh applied to either space or time
# refinement factors for a spherical mesh given in section spherical_convergence
refinement_factors = 4., 2., 1., 0.5
# config options for convergence forward steps
[convergence_forward]
Expand Down Expand Up @@ -325,7 +353,8 @@ class Forward(SphericalConvergenceForward):
bell test case
"""

def __init__(self, component, name, subdir, resolution, mesh, init):
def __init__(self, component, name, subdir, mesh, init,
refinement_factor, refinement='both'):
"""
Create a new step
Expand All @@ -348,6 +377,9 @@ class Forward(SphericalConvergenceForward):
init : polaris.Step
The init step
refinement_factor : float
The factor by which to scale space, time or both
"""
package = 'polaris.ocean.tasks.cosine_bell'
validate_vars = ['normalVelocity', 'tracer1']
Expand All @@ -356,7 +388,10 @@ class Forward(SphericalConvergenceForward):
init=init, package=package,
yaml_filename='forward.yaml',
output_filename='output.nc',
validate_vars=validate_vars)
validate_vars=validate_vars,
graph_target=f'{init.path}/graph.info',
refinement_factor=refinement_factor,
refinement=refinement)
```
Each convergence test must define a YAML file with model config options, called
`forward.yaml` by default. The `package` parameter is the location of this
Expand Down Expand Up @@ -419,7 +454,7 @@ class Analysis(ConvergenceAnalysis):
"""
A step for analyzing the output from the cosine bell test case
"""
def __init__(self, component, resolutions, subdir, dependencies):
def __init__(self, component, subdir, dependencies, refinement='both'):
"""
Create the step
Expand All @@ -436,14 +471,18 @@ class Analysis(ConvergenceAnalysis):
dependencies : dict of dict of polaris.Steps
The dependencies of this step
refinement : str, optional
Whether to refine in space, time or both space and time
"""
convergence_vars = [{'name': 'tracer1',
'title': 'tracer1',
'zidx': 0}]
super().__init__(component=component, subdir=subdir,
resolutions=resolutions,
dependencies=dependencies,
convergence_vars=convergence_vars)
convergence_vars=convergence_vars,
refinement=refinement)
```

Many tasks will also need to override the
Expand Down
42 changes: 32 additions & 10 deletions docs/users_guide/ocean/tasks/cosine_bell.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,34 +33,56 @@ These tasks support only MPAS-Ocean.
(ocean-cosine-bell-mesh)=
## mesh

Two global mesh variants are tested, quasi-uniform (QU) and icosohydral. Thus,
there are 4 variants of the task:
Two global mesh variants are tested, quasi-uniform (QU) and icosohydral. There
are also variants to test convergence in space, time, or both space and time.
In addition, the tests can be set up with or without the viz step. Thus, there
are 12 variants of the task:
```
ocean/spherical/icos/cosine_bell
ocean/spherical/icos/cosine_bell/with_viz
ocean/spherical/qu/cosine_bell
ocean/spherical/qu/cosine_bell/with_viz
ocean/spherical/icos/cosine_bell/convergence_both/
ocean/spherical/icos/cosine_bell/convergence_both/with_viz
ocean/spherical/qu/cosine_bell/convergence_both/
ocean/spherical/qu/cosine_bell/convergence_both/with_viz
ocean/spherical/icos/cosine_bell/convergence_space/
ocean/spherical/icos/cosine_bell/convergence_space/with_viz
ocean/spherical/qu/cosine_bell/convergence_space/
ocean/spherical/qu/cosine_bell/convergence_space/with_viz
ocean/spherical/icos/cosine_bell/convergence_time/
ocean/spherical/icos/cosine_bell/convergence_time/with_viz
ocean/spherical/qu/cosine_bell/convergence_time/
ocean/spherical/qu/cosine_bell/convergence_time/with_viz
```
The default resolutions used in the task depends on the mesh type.

For the `icos` mesh type, the defaults are:
For the `icos` mesh type, the defaults are 60, 120, 240, 480 km, as determined
by the following config options. See {ref}`dev-ocean-convergence` for more
details.

```cfg
# config options for spherical convergence tests
[spherical_convergence]
# The base resolution for the icosahedral mesh to which the refinement
# factors are applied
icos_base_resolution = 60.
# a list of icosahedral mesh resolutions (km) to test
icos_refinement_factors = 8., 4., 2., 1.
# a list of icosahedral mesh resolutions (km) to test
icos_resolutions = 60, 120, 240, 480
```

for the `qu` mesh type, they are:
For the `qu` mesh type, they are 60, 90, 120, 150, 180, 210, 240 km as
determined by the following config options:

```cfg
# config options for spherical convergence tests
[spherical_convergence]
# The base resolution for the quasi-uniform mesh to which the refinement
# factors are applied
qu_base_resolution = 120.
# a list of quasi-uniform mesh resolutions (km) to test
qu_resolutions = 60, 90, 120, 150, 180, 210, 240
qu_refinement_factors = 0.5, 0.75, 1., 1.25, 1.5, 1.75, 2.
```

To alter the resolutions used in this task, you will need to create your own
Expand Down
15 changes: 10 additions & 5 deletions docs/users_guide/ocean/tasks/geostrophic.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,25 @@

## description

The `geostrophic` and `geostrophic/with_viz` tasks implement the "Global Steady
The `geostrophic` tasks implement the "Global Steady
State Nonlinear Zonal Geostrophic Flow" test case described in
[Williamson et al. 1992](<https://doi.org/10.1016/S0021-9991(05)80016-6>)

The task is a convergence test with time step varying proportionately to grid
size. The result of the `analysis` step of the task are plots like the
following showing convergence of water-column thickness and normal velocity as
functions of the mesh resolution:
The task `geostrophic/convergence_both` is a space-and-time convergence test
with time step varying proportionately to grid size. Convergence tests in
either space or time are also available as `convergence_space` or
`convergence_time`. The result of the `analysis` step of the task are plots
like the following showing convergence of water-column thickness and normal
velocity as functions of the mesh resolution:

```{image} images/geostrophic_convergence.png
:align: center
:width: 500 px
```

Visualizations of the fields themselves can be added in viz steps by appending
`with_viz` to the task name at setup.

## suppported models

These tasks support only MPAS-Ocean.
Expand Down
8 changes: 8 additions & 0 deletions docs/users_guide/ocean/tasks/inertial_gravity_wave.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ The implementation is from

## description

There are 3 versions of the convergence test case, `convergence_space`,
`convergence_time`, and `convergence_both` corresponding to space, time, and
space and time convergence tests. Tests involving spatial convergence run the
inertial gravity wave simulation for 4 different resolutions: 200, 100, 50,
and 25 km. Tests involving temporal convergence use the parameter `dt_per_km`
at the `base_resolution` multiplied by `refinement_factors` (see
{ref}`dev-ocean-convergence` for more details on how to change resolutions or
time steps tested).
The `inertial_gravity_wave` task runs the inertial gravity wave simulation for 4
different resolutions: 200, 100, 50, and 25 km.

Expand Down
10 changes: 8 additions & 2 deletions docs/users_guide/ocean/tasks/manufactured_solution.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ These tasks support both MPAS-Ocean and Omega.

### description

The `convergence` test case runs the manufactured solution simulation for 4
different resolutions: 200, 100, 50, and 25 km.
There are 3 versions of the convergence test case, `convergence_space`,
`convergence_time`, and `convergence_both` corresponding to space, time, and
space and time convergence tests. Tests involving spatial convergence run the
manufactured solution simulation for 4 different resolutions: 200, 100, 50,
and 25 km. Tests involving temporal convergence use the parameter `dt_per_km`
at the `base_resolution` multiplied by `refinement_factors` (see
{ref}`dev-ocean-convergence` for more details on how to change resolutions or
time steps tested).

The forward step for each resolution runs the simulation for 10 hours. The
model is configured without vertical advection and mixing. No tracers are enabled
Expand Down
108 changes: 106 additions & 2 deletions polaris/ocean/convergence/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,106 @@
from polaris.ocean.convergence.analysis import ConvergenceAnalysis
from polaris.ocean.convergence.forward import ConvergenceForward
import numpy as np


def get_resolution_for_task(config, refinement_factor,
refinement='both'):
"""
Get the resolution for a step in a convergence task
Parameters
----------
config : polaris.Config
The config options for this task
refinement_factor : float
The factor by which either resolution or time is refined for this step
refinement : str, optional
Whether to refine in space, time or both
Returns
-------
resolution : float
The resolution corresponding to the refinement_factor and convergence
test type
"""
if refinement == 'both':
option = 'refinement_factors_space'
else:
option = f'refinement_factors_{refinement}'
base_resolution = config.getfloat('convergence', 'base_resolution')
refinement_factors = config.getlist('convergence', option, dtype=float)

if refinement_factor not in refinement_factors:
raise ValueError(
'refinement_factor not found in config option refinement_factors')

if refinement == 'time':
resolution = base_resolution
else:
resolution = refinement_factor * base_resolution

return resolution


def get_timestep_for_task(config, refinement_factor,
refinement='both'):
"""
Get the time step for a forward step in a convergence task
Parameters
----------
config : polaris.Config
The config options for this task
refinement_factor : float
The factor by which either resolution or time is refined for this step
refinement : str, optional
Whether to refine in space, time or both
Returns
-------
resolution : float
The resolution corresponding to the refinement_factor and convergence
test type
"""

if refinement == 'both':
option = 'refinement_factors_space'
else:
option = f'refinement_factors_{refinement}'
base_resolution = config.getfloat('convergence', 'base_resolution')
refinement_factors = config.getlist('convergence', option, dtype=float)

if refinement_factor not in refinement_factors:
raise ValueError(
'refinement_factor not found in config option refinement_factors')

resolution = get_resolution_for_task(
config, refinement_factor, refinement=refinement)

section = config['convergence_forward']
time_integrator = section.get('time_integrator')
# dt is proportional to resolution: default 30 seconds per km
if time_integrator == 'RK4':
dt_per_km = section.getfloat('rk4_dt_per_km')
btr_timestep = 0.
else:
dt_per_km = section.getfloat('split_dt_per_km')
btr_dt_per_km = section.getfloat('btr_dt_per_km')
for idx, refinement_factor in enumerate(refinement_factors):
if refinement == 'time':
btr_timestep = btr_dt_per_km * base_resolution * \
refinement_factor
elif refinement == 'space':
btr_timestep = btr_dt_per_km * base_resolution
else:
btr_timestep = btr_dt_per_km * resolution
if refinement == 'time':
timestep = dt_per_km * refinement_factor * resolution
elif refinement == 'space':
timestep = dt_per_km * base_resolution
else:
timestep = dt_per_km * resolution

return timestep, btr_timestep
Loading

0 comments on commit a44d4b8

Please sign in to comment.