Skip to content

Commit a44d4b8

Browse files
authored
Merge pull request #236 from cbegeman/enhance-convergence-tasks
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.
2 parents cd94c14 + 9fe597a commit a44d4b8

39 files changed

+1068
-492
lines changed

docs/developers_guide/ocean/api.md

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -313,18 +313,21 @@
313313
.. autosummary::
314314
:toctree: generated/
315315
316-
ConvergenceForward
317-
ConvergenceForward.compute_cell_count
318-
ConvergenceForward.dynamic_model_config
319-
320-
ConvergenceAnalysis
321-
ConvergenceAnalysis.compute_error
322-
ConvergenceAnalysis.convergence_parameters
323-
ConvergenceAnalysis.exact_solution
324-
ConvergenceAnalysis.get_output_field
325-
ConvergenceAnalysis.plot_convergence
326-
ConvergenceAnalysis.run
327-
ConvergenceAnalysis.setup
316+
get_resolution_for_tasks
317+
get_timestep_for_tasks
318+
319+
forward.ConvergenceForward
320+
forward.ConvergenceForward.compute_cell_count
321+
forward.ConvergenceForward.dynamic_model_config
322+
323+
analysis.ConvergenceAnalysis
324+
analysis.ConvergenceAnalysis.compute_error
325+
analysis.ConvergenceAnalysis.convergence_parameters
326+
analysis.ConvergenceAnalysis.exact_solution
327+
analysis.ConvergenceAnalysis.get_output_field
328+
analysis.ConvergenceAnalysis.plot_convergence
329+
analysis.ConvergenceAnalysis.run
330+
analysis.ConvergenceAnalysis.setup
328331
```
329332
### Spherical Convergence Tests
330333

docs/developers_guide/ocean/framework.md

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,16 +219,35 @@ tests on {ref}`dev-ocean-spherical-meshes` and planar meshes.
219219
The ocean framework includes shared config options and base classes for
220220
forward and analysis steps that are expected to be useful across these tests.
221221

222+
The key config options that control the convergence test are `base_resolution`
223+
and `refinement_factors`. The `base_resolution` is multipled by the
224+
`refinement_factors` to determine which resolutions to test when the
225+
convergence is being tested in space (or space and time together). The
226+
`base_resolution` is applied to all steps when convergence in time is tested.
227+
`base_resolution` times `dt_per_km` determines the base timestep in that case
228+
and is then multiplied by the `refinement_factors` to determine which time steps
229+
to test. When spherical meshes are being tested, the values in the
230+
`convergence` section are overridden by their values in the
231+
`spherical_convergence` section with a prefix indicating the mesh type.
232+
222233
The shared config options are:
223234
```cfg
224235
# config options for spherical convergence tests
225236
[spherical_convergence]
226237
238+
# The base resolution for the icosahedral mesh to which the refinement
239+
# factors are applied
240+
icos_base_resolution = 60.
241+
227242
# a list of icosahedral mesh resolutions (km) to test
228-
icos_resolutions = 60, 120, 240, 480
243+
icos_refinement_factors = 8., 4., 2., 1.
244+
245+
# The base resolution for the quasi-uniform mesh to which the refinement
246+
# factors are applied
247+
qu_base_resolution = 120.
229248
230249
# a list of quasi-uniform mesh resolutions (km) to test
231-
qu_resolutions = 60, 90, 120, 150, 180, 210, 240
250+
qu_refinement_factors = 0.5, 0.75, 1., 1.25, 1.5, 1.75, 2.
232251
233252
[convergence]
234253
@@ -241,6 +260,15 @@ convergence_thresh = 1.0
241260
# Type of error to compute
242261
error_type = l2
243262
263+
# the base mesh resolution (km) to which refinement_factors
264+
# are applied if refinement is 'space' or 'both' on a planar mesh
265+
# base resolutions for spherical meshes are given in section spherical_convergence
266+
base_resolution = 120
267+
268+
# refinement factors for a planar mesh applied to either space or time
269+
# refinement factors for a spherical mesh given in section spherical_convergence
270+
refinement_factors = 4., 2., 1., 0.5
271+
244272
# config options for convergence forward steps
245273
[convergence_forward]
246274
@@ -325,7 +353,8 @@ class Forward(SphericalConvergenceForward):
325353
bell test case
326354
"""
327355

328-
def __init__(self, component, name, subdir, resolution, mesh, init):
356+
def __init__(self, component, name, subdir, mesh, init,
357+
refinement_factor, refinement='both'):
329358
"""
330359
Create a new step
331360
@@ -348,6 +377,9 @@ class Forward(SphericalConvergenceForward):
348377
349378
init : polaris.Step
350379
The init step
380+
381+
refinement_factor : float
382+
The factor by which to scale space, time or both
351383
"""
352384
package = 'polaris.ocean.tasks.cosine_bell'
353385
validate_vars = ['normalVelocity', 'tracer1']
@@ -356,7 +388,10 @@ class Forward(SphericalConvergenceForward):
356388
init=init, package=package,
357389
yaml_filename='forward.yaml',
358390
output_filename='output.nc',
359-
validate_vars=validate_vars)
391+
validate_vars=validate_vars,
392+
graph_target=f'{init.path}/graph.info',
393+
refinement_factor=refinement_factor,
394+
refinement=refinement)
360395
```
361396
Each convergence test must define a YAML file with model config options, called
362397
`forward.yaml` by default. The `package` parameter is the location of this
@@ -419,7 +454,7 @@ class Analysis(ConvergenceAnalysis):
419454
"""
420455
A step for analyzing the output from the cosine bell test case
421456
"""
422-
def __init__(self, component, resolutions, subdir, dependencies):
457+
def __init__(self, component, subdir, dependencies, refinement='both'):
423458
"""
424459
Create the step
425460
@@ -436,14 +471,18 @@ class Analysis(ConvergenceAnalysis):
436471
437472
dependencies : dict of dict of polaris.Steps
438473
The dependencies of this step
474+
475+
refinement : str, optional
476+
Whether to refine in space, time or both space and time
439477
"""
440478
convergence_vars = [{'name': 'tracer1',
441479
'title': 'tracer1',
442480
'zidx': 0}]
443481
super().__init__(component=component, subdir=subdir,
444482
resolutions=resolutions,
445483
dependencies=dependencies,
446-
convergence_vars=convergence_vars)
484+
convergence_vars=convergence_vars,
485+
refinement=refinement)
447486
```
448487

449488
Many tasks will also need to override the

docs/users_guide/ocean/tasks/cosine_bell.md

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,34 +33,56 @@ These tasks support only MPAS-Ocean.
3333
(ocean-cosine-bell-mesh)=
3434
## mesh
3535

36-
Two global mesh variants are tested, quasi-uniform (QU) and icosohydral. Thus,
37-
there are 4 variants of the task:
36+
Two global mesh variants are tested, quasi-uniform (QU) and icosohydral. There
37+
are also variants to test convergence in space, time, or both space and time.
38+
In addition, the tests can be set up with or without the viz step. Thus, there
39+
are 12 variants of the task:
3840
```
39-
ocean/spherical/icos/cosine_bell
40-
ocean/spherical/icos/cosine_bell/with_viz
41-
ocean/spherical/qu/cosine_bell
42-
ocean/spherical/qu/cosine_bell/with_viz
41+
ocean/spherical/icos/cosine_bell/convergence_both/
42+
ocean/spherical/icos/cosine_bell/convergence_both/with_viz
43+
ocean/spherical/qu/cosine_bell/convergence_both/
44+
ocean/spherical/qu/cosine_bell/convergence_both/with_viz
45+
ocean/spherical/icos/cosine_bell/convergence_space/
46+
ocean/spherical/icos/cosine_bell/convergence_space/with_viz
47+
ocean/spherical/qu/cosine_bell/convergence_space/
48+
ocean/spherical/qu/cosine_bell/convergence_space/with_viz
49+
ocean/spherical/icos/cosine_bell/convergence_time/
50+
ocean/spherical/icos/cosine_bell/convergence_time/with_viz
51+
ocean/spherical/qu/cosine_bell/convergence_time/
52+
ocean/spherical/qu/cosine_bell/convergence_time/with_viz
4353
```
4454
The default resolutions used in the task depends on the mesh type.
4555

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

4860
```cfg
4961
# config options for spherical convergence tests
5062
[spherical_convergence]
5163
64+
# The base resolution for the icosahedral mesh to which the refinement
65+
# factors are applied
66+
icos_base_resolution = 60.
67+
68+
# a list of icosahedral mesh resolutions (km) to test
69+
icos_refinement_factors = 8., 4., 2., 1.
5270
# a list of icosahedral mesh resolutions (km) to test
53-
icos_resolutions = 60, 120, 240, 480
5471
```
5572

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

5876
```cfg
5977
# config options for spherical convergence tests
6078
[spherical_convergence]
6179
80+
# The base resolution for the quasi-uniform mesh to which the refinement
81+
# factors are applied
82+
qu_base_resolution = 120.
83+
6284
# a list of quasi-uniform mesh resolutions (km) to test
63-
qu_resolutions = 60, 90, 120, 150, 180, 210, 240
85+
qu_refinement_factors = 0.5, 0.75, 1., 1.25, 1.5, 1.75, 2.
6486
```
6587

6688
To alter the resolutions used in this task, you will need to create your own

docs/users_guide/ocean/tasks/geostrophic.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,25 @@
44

55
## description
66

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

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

1618
```{image} images/geostrophic_convergence.png
1719
:align: center
1820
:width: 500 px
1921
```
2022

23+
Visualizations of the fields themselves can be added in viz steps by appending
24+
`with_viz` to the task name at setup.
25+
2126
## suppported models
2227

2328
These tasks support only MPAS-Ocean.

docs/users_guide/ocean/tasks/inertial_gravity_wave.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ The implementation is from
1111

1212
## description
1313

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

docs/users_guide/ocean/tasks/manufactured_solution.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,14 @@ These tasks support both MPAS-Ocean and Omega.
2222

2323
### description
2424

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

2834
The forward step for each resolution runs the simulation for 10 hours. The
2935
model is configured without vertical advection and mixing. No tracers are enabled
Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,106 @@
1-
from polaris.ocean.convergence.analysis import ConvergenceAnalysis
2-
from polaris.ocean.convergence.forward import ConvergenceForward
1+
import numpy as np
2+
3+
4+
def get_resolution_for_task(config, refinement_factor,
5+
refinement='both'):
6+
"""
7+
Get the resolution for a step in a convergence task
8+
9+
Parameters
10+
----------
11+
config : polaris.Config
12+
The config options for this task
13+
14+
refinement_factor : float
15+
The factor by which either resolution or time is refined for this step
16+
17+
refinement : str, optional
18+
Whether to refine in space, time or both
19+
20+
Returns
21+
-------
22+
resolution : float
23+
The resolution corresponding to the refinement_factor and convergence
24+
test type
25+
"""
26+
if refinement == 'both':
27+
option = 'refinement_factors_space'
28+
else:
29+
option = f'refinement_factors_{refinement}'
30+
base_resolution = config.getfloat('convergence', 'base_resolution')
31+
refinement_factors = config.getlist('convergence', option, dtype=float)
32+
33+
if refinement_factor not in refinement_factors:
34+
raise ValueError(
35+
'refinement_factor not found in config option refinement_factors')
36+
37+
if refinement == 'time':
38+
resolution = base_resolution
39+
else:
40+
resolution = refinement_factor * base_resolution
41+
42+
return resolution
43+
44+
45+
def get_timestep_for_task(config, refinement_factor,
46+
refinement='both'):
47+
"""
48+
Get the time step for a forward step in a convergence task
49+
50+
Parameters
51+
----------
52+
config : polaris.Config
53+
The config options for this task
54+
55+
refinement_factor : float
56+
The factor by which either resolution or time is refined for this step
57+
58+
refinement : str, optional
59+
Whether to refine in space, time or both
60+
61+
Returns
62+
-------
63+
resolution : float
64+
The resolution corresponding to the refinement_factor and convergence
65+
test type
66+
"""
67+
68+
if refinement == 'both':
69+
option = 'refinement_factors_space'
70+
else:
71+
option = f'refinement_factors_{refinement}'
72+
base_resolution = config.getfloat('convergence', 'base_resolution')
73+
refinement_factors = config.getlist('convergence', option, dtype=float)
74+
75+
if refinement_factor not in refinement_factors:
76+
raise ValueError(
77+
'refinement_factor not found in config option refinement_factors')
78+
79+
resolution = get_resolution_for_task(
80+
config, refinement_factor, refinement=refinement)
81+
82+
section = config['convergence_forward']
83+
time_integrator = section.get('time_integrator')
84+
# dt is proportional to resolution: default 30 seconds per km
85+
if time_integrator == 'RK4':
86+
dt_per_km = section.getfloat('rk4_dt_per_km')
87+
btr_timestep = 0.
88+
else:
89+
dt_per_km = section.getfloat('split_dt_per_km')
90+
btr_dt_per_km = section.getfloat('btr_dt_per_km')
91+
for idx, refinement_factor in enumerate(refinement_factors):
92+
if refinement == 'time':
93+
btr_timestep = btr_dt_per_km * base_resolution * \
94+
refinement_factor
95+
elif refinement == 'space':
96+
btr_timestep = btr_dt_per_km * base_resolution
97+
else:
98+
btr_timestep = btr_dt_per_km * resolution
99+
if refinement == 'time':
100+
timestep = dt_per_km * refinement_factor * resolution
101+
elif refinement == 'space':
102+
timestep = dt_per_km * base_resolution
103+
else:
104+
timestep = dt_per_km * resolution
105+
106+
return timestep, btr_timestep

0 commit comments

Comments
 (0)