From f48fe9bbbf378da60e2dd2da8cff6f9dcd25e1fa Mon Sep 17 00:00:00 2001 From: Jeremy Lilly Date: Fri, 8 Dec 2023 11:10:11 -0800 Subject: [PATCH 1/3] Rewrite for LTS region labeling, cells with label 5 now only exist in the requested fine region --- .../tests/hurricane/lts/mesh/lts_regions.py | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/compass/ocean/tests/hurricane/lts/mesh/lts_regions.py b/compass/ocean/tests/hurricane/lts/mesh/lts_regions.py index 87e7025946..22cdf4cd6c 100644 --- a/compass/ocean/tests/hurricane/lts/mesh/lts_regions.py +++ b/compass/ocean/tests/hurricane/lts/mesh/lts_regions.py @@ -90,11 +90,12 @@ def run(self): use_progress_bar = self.log_filename is None label_mesh(fine_region, mesh='culled_mesh.nc', graph_info='culled_graph.info', num_interface=2, + num_interface_adjacent=2, logger=self.logger, use_progress_bar=use_progress_bar) def label_mesh(fine_region, mesh, graph_info, num_interface, # noqa: C901 - logger, use_progress_bar): + num_interface_adjacent, logger, use_progress_bar): # read in mesh data ds = xr.open_dataset(mesh) @@ -118,6 +119,7 @@ def label_mesh(fine_region, mesh, graph_info, num_interface, # noqa: C901 # first layer of cells with label 5 changed_cells = [[], []] + border_cells = [] for iedge in range(0, n_edges): cell1 = cells_on_edge[iedge, 0] - 1 cell2 = cells_on_edge[iedge, 1] - 1 @@ -125,20 +127,20 @@ def label_mesh(fine_region, mesh, graph_info, num_interface, # noqa: C901 if (cell1 != -1 and cell2 != -1): if (lts_rgn[cell1] == 1 and lts_rgn[cell2] == 2): - lts_rgn[cell2] = 5 - changed_cells[0].append(cell2) + lts_rgn[cell1] = 5 + changed_cells[0].append(cell1) elif (lts_rgn[cell1] == 2 and lts_rgn[cell2] == 1): - lts_rgn[cell1] = 5 - changed_cells[0].append(cell1) + lts_rgn[cell2] = 5 + changed_cells[0].append(cell2) + + border_cells = changed_cells[0] - # second and third layer of cells with label 5 + # num_interface_adjacent - 1 layers of cells with label 5 # only looping over cells changed during loop for previous layer - # at the end of this loop, changed_cells[0] will have the list of cells - # sharing edegs with the coarse cells logger.info('Labeling interface-adjacent fine cells...') - for i in range(0, 2): # this loop creates 2 layers + for i in range(0, num_interface_adjacent - 1): changed_cells[(i + 1) % 2] = [] for icell in changed_cells[i % 2]: @@ -149,17 +151,19 @@ def label_mesh(fine_region, mesh, graph_info, num_interface, # noqa: C901 cell2 = cells_on_edge[iedge - 1, 1] - 1 if (cell1 != -1 and cell2 != -1): - if (lts_rgn[cell1] == 5 and lts_rgn[cell2] == 2): + if (lts_rgn[cell1] == 5 and lts_rgn[cell2] == 1): lts_rgn[cell2] = 5 changed_cells[(i + 1) % 2].append(cell2) - elif (lts_rgn[cell1] == 2 and lts_rgn[cell2] == 5): + elif (lts_rgn[cell1] == 1 and lts_rgn[cell2] == 5): lts_rgn[cell1] = 5 changed_cells[(i + 1) % 2].append(cell1) - # n layers of interface region with label 4 + changed_cells[0] = border_cells + + # num_interface layers of interface region with label 4 logger.info('Labeling interface cells...') for i in range(0, num_interface): changed_cells[(i + 1) % 2] = [] @@ -200,7 +204,7 @@ def label_mesh(fine_region, mesh, graph_info, num_interface, # noqa: C901 changed_cells[0] = changed_cells[num_interface % 2] - # n layers of interface region with label 3 + # num_interface layers of interface region with label 3 for i in range(0, num_interface): changed_cells[(i + 1) % 2] = [] @@ -213,9 +217,9 @@ def label_mesh(fine_region, mesh, graph_info, num_interface, # noqa: C901 if (cell1 != -1 and cell2 != -1): # for the first layer, need to check neighbors are - # 5 and 2 - # for further layers, need to check neighbors are # 3 and 2 + # for further layers, need to check neighbors are + # 4 and 2 if (i == 0): if (lts_rgn[cell1] == 3 and lts_rgn[cell2] == 2): From 8ae679d39201540b202efa0d46ff22004e075c34 Mon Sep 17 00:00:00 2001 From: Jeremy Lilly Date: Thu, 25 Jan 2024 15:42:43 -0800 Subject: [PATCH 2/3] Add a version of the hurricane sandy test case for FB_LTS --- compass/ocean/tests/hurricane/__init__.py | 2 +- .../ocean/tests/hurricane/fblts/__init_.py | 0 .../tests/hurricane/fblts/forward/__init__.py | 0 .../hurricane/fblts/forward/namelist.ocean | 39 +++++++ .../hurricane/fblts/forward/streams.ocean | 108 ++++++++++++++++++ .../ocean/tests/hurricane/forward/__init__.py | 4 +- .../ocean/tests/hurricane/forward/forward.py | 11 +- .../ocean/tests/hurricane/init/__init__.py | 4 +- .../tests/hurricane/lts/mesh/lts_regions.py | 4 +- .../ocean/tests/hurricane/mesh/__init__.py | 14 ++- 10 files changed, 177 insertions(+), 9 deletions(-) create mode 100644 compass/ocean/tests/hurricane/fblts/__init_.py create mode 100644 compass/ocean/tests/hurricane/fblts/forward/__init__.py create mode 100644 compass/ocean/tests/hurricane/fblts/forward/namelist.ocean create mode 100644 compass/ocean/tests/hurricane/fblts/forward/streams.ocean diff --git a/compass/ocean/tests/hurricane/__init__.py b/compass/ocean/tests/hurricane/__init__.py index 15b5536299..6d59f39c3e 100644 --- a/compass/ocean/tests/hurricane/__init__.py +++ b/compass/ocean/tests/hurricane/__init__.py @@ -19,7 +19,7 @@ def __init__(self, mpas_core): storm = 'sandy' mesh_name = 'DEQU120at30cr10rr2' - for use_lts in [False, True]: + for use_lts in [False, 'LTS', 'FB_LTS']: mesh = Mesh(test_group=self, mesh_name=mesh_name, diff --git a/compass/ocean/tests/hurricane/fblts/__init_.py b/compass/ocean/tests/hurricane/fblts/__init_.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/compass/ocean/tests/hurricane/fblts/forward/__init__.py b/compass/ocean/tests/hurricane/fblts/forward/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/compass/ocean/tests/hurricane/fblts/forward/namelist.ocean b/compass/ocean/tests/hurricane/fblts/forward/namelist.ocean new file mode 100644 index 0000000000..3850c97f8c --- /dev/null +++ b/compass/ocean/tests/hurricane/fblts/forward/namelist.ocean @@ -0,0 +1,39 @@ +config_start_time = '2012-10-10_00:00:00' +config_stop_time = '2012-11-03_00:00:00' +config_run_duration = 'none' +config_dt = '72' +config_time_integrator = 'FB_LTS' +config_dt_scaling_LTS = 4 +config_number_of_time_levels = 5 +config_hmix_scaleWithMesh = .true. +config_use_mom_del4 = .true. +config_mom_del4 = 4.0e8 +config_use_cvmix = .false. +config_use_bulk_wind_stress = .true. +config_use_time_varying_atmospheric_forcing = .true. +config_time_varying_atmospheric_forcing_start_time = '2012-10-10_00:00:00' +config_time_varying_atmospheric_forcing_reference_time = '2012-10-10_00:00:00' +config_time_varying_atmospheric_forcing_cycle_start = 'none' +config_time_varying_atmospheric_forcing_cycle_duration = '2-00-00_00:00:00' +config_use_tidal_potential_forcing = .true. +config_tidal_potential_reference_time = '2012-10-10_00:00:00' +config_bottom_drag_mode = 'explicit' +config_use_topographic_wave_drag = .true. +config_topographic_wave_drag_coeff = 5.0e-3 +config_pressure_gradient_type = 'ssh_gradient' +config_vert_coord_movement = 'impermeable_interfaces' +config_ALE_thickness_proportionality = 'weights_only' +config_disable_thick_vadv = .true. +config_disable_thick_sflux = .true. +config_disable_vel_hmix = .true. +config_disable_vel_vmix = .true. +config_disable_vel_vadv = .true. +config_disable_tr_adv = .true. +config_disable_tr_hmix = .true. +config_disable_tr_vmix = .true. +config_disable_tr_sflux = .true. +config_disable_tr_nonlocalflux = .true. +config_disable_redi_k33 = .true. +config_open_ocean_freezing_temperature_coeff_0 = -1.8 +config_disable_tr_all_tend = .true. +config_AM_pointwiseStats_enable = .true. diff --git a/compass/ocean/tests/hurricane/fblts/forward/streams.ocean b/compass/ocean/tests/hurricane/fblts/forward/streams.ocean new file mode 100644 index 0000000000..deb78f154b --- /dev/null +++ b/compass/ocean/tests/hurricane/fblts/forward/streams.ocean @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/compass/ocean/tests/hurricane/forward/__init__.py b/compass/ocean/tests/hurricane/forward/__init__.py index 289b9292e7..6654e467a4 100644 --- a/compass/ocean/tests/hurricane/forward/__init__.py +++ b/compass/ocean/tests/hurricane/forward/__init__.py @@ -41,8 +41,10 @@ def __init__(self, test_group, mesh, storm, init, use_lts): """ mesh_name = mesh.mesh_name - if use_lts: + if use_lts == 'LTS': name = f'{storm}_lts' + elif use_lts == 'FB_LTS': + name = f'{storm}_fblts' else: name = storm subdir = os.path.join(mesh_name, name) diff --git a/compass/ocean/tests/hurricane/forward/forward.py b/compass/ocean/tests/hurricane/forward/forward.py index 1d2d392d33..8ce12580e9 100644 --- a/compass/ocean/tests/hurricane/forward/forward.py +++ b/compass/ocean/tests/hurricane/forward/forward.py @@ -49,13 +49,22 @@ def __init__(self, test_case, mesh, init, use_lts, super().__init__(test_case=test_case, name=name) - if use_lts: + if use_lts == 'LTS': self.add_namelist_file( 'compass.ocean.tests.hurricane.lts.forward', 'namelist.ocean') self.add_streams_file( 'compass.ocean.tests.hurricane.lts.forward', 'streams.ocean') + elif use_lts == 'FB_LTS': + + self.add_namelist_file( + 'compass.ocean.tests.hurricane.fblts.forward', + 'namelist.ocean') + self.add_streams_file( + 'compass.ocean.tests.hurricane.fblts.forward', + 'streams.ocean') + else: self.add_namelist_file( diff --git a/compass/ocean/tests/hurricane/init/__init__.py b/compass/ocean/tests/hurricane/init/__init__.py index cc24063ae1..1c14fc59fa 100644 --- a/compass/ocean/tests/hurricane/init/__init__.py +++ b/compass/ocean/tests/hurricane/init/__init__.py @@ -45,8 +45,10 @@ def __init__(self, test_group, mesh, storm, use_lts): self.mesh = mesh self.use_lts = use_lts - if use_lts: + if use_lts == 'LTS': name = 'init_lts' + elif use_lts == 'FB_LTS': + name = 'init_fblts' else: name = 'init' mesh_name = mesh.mesh_name diff --git a/compass/ocean/tests/hurricane/lts/mesh/lts_regions.py b/compass/ocean/tests/hurricane/lts/mesh/lts_regions.py index 22cdf4cd6c..fbb95b0cb6 100644 --- a/compass/ocean/tests/hurricane/lts/mesh/lts_regions.py +++ b/compass/ocean/tests/hurricane/lts/mesh/lts_regions.py @@ -22,6 +22,7 @@ class LTSRegionsStep(Step): The culled mesh step containing input files to this step """ def __init__(self, test_case, cull_mesh_step, + num_interface_adjacent, name='lts_regions', subdir='lts_regions'): """ Create a new step @@ -46,6 +47,7 @@ def __init__(self, test_case, cull_mesh_step, self.add_output_file(filename=file) self.cull_mesh_step = cull_mesh_step + self.num_interface_adjacent = num_interface_adjacent def setup(self): """ @@ -90,7 +92,7 @@ def run(self): use_progress_bar = self.log_filename is None label_mesh(fine_region, mesh='culled_mesh.nc', graph_info='culled_graph.info', num_interface=2, - num_interface_adjacent=2, + num_interface_adjacent=self.num_interface_adjacent, logger=self.logger, use_progress_bar=use_progress_bar) diff --git a/compass/ocean/tests/hurricane/mesh/__init__.py b/compass/ocean/tests/hurricane/mesh/__init__.py index 23f7964604..94f8188d53 100644 --- a/compass/ocean/tests/hurricane/mesh/__init__.py +++ b/compass/ocean/tests/hurricane/mesh/__init__.py @@ -29,8 +29,10 @@ def __init__(self, test_group, mesh_name, use_lts): self.mesh_name = mesh_name self.use_lts = use_lts - if use_lts: + if use_lts == 'LTS': name = 'mesh_lts' + elif use_lts == 'FB_LTS': + name = 'mesh_fblts' else: name = 'mesh' subdir = '{}/{}'.format(mesh_name, name) @@ -60,10 +62,14 @@ def __init__(self, test_group, mesh_name, use_lts): self.add_step(cull_mesh_step) - if use_lts: - + if use_lts == 'LTS': + self.add_step(LTSRegionsStep( + test_case=self, cull_mesh_step=cull_mesh_step, + num_interface_adjacent=2)) + elif use_lts == 'FB_LTS': self.add_step(LTSRegionsStep( - test_case=self, cull_mesh_step=cull_mesh_step)) + test_case=self, cull_mesh_step=cull_mesh_step, + num_interface_adjacent=10)) def configure(self): """ From f7002a853f5ee3436f323547261af876cac72730 Mon Sep 17 00:00:00 2001 From: Jeremy Lilly Date: Wed, 13 Mar 2024 09:40:47 -0700 Subject: [PATCH 3/3] Update docs for FB-LTS --- .../ocean/test_groups/hurricane.rst | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/docs/users_guide/ocean/test_groups/hurricane.rst b/docs/users_guide/ocean/test_groups/hurricane.rst index be50d7e36e..b9976022d7 100644 --- a/docs/users_guide/ocean/test_groups/hurricane.rst +++ b/docs/users_guide/ocean/test_groups/hurricane.rst @@ -19,13 +19,16 @@ which can be used to simulate coastal inundation using MPAS-Ocean's wetting and drying scheme. The time stepping options to run the simulations include the fourth -order Runge-Kutta scheme (RK4), which is the default, and a local -time-stepping (LTS) scheme, see +order Runge-Kutta scheme (RK4), and two local time-stepping schemes. +The first LTS scheme is based on a strong stability preserving Runge-Kutta +scheme of order three and is called LTS3, see `Lilly et al. (2023) `_ -for details. Each test case in the ``ocean/hurricane`` test group has an -LTS counterpart which is identified by the ``_lts`` appendix in the test case name. -Note that the executable to be used with LTS has to be compiled with -the following options: ``USE_LTS=true OPENMP=false``. +for details. +The second LTS scheme is based on a forward-backward Runge-Kutta scheme +of order two and is called FB-LTS. +Each test case in the ``ocean/hurricane`` test group has a counterpart +for each LTS scheme which is identified by appending the test case name +with ``_lts`` for LTS3 and ``_fblts`` for FB-LTS. Shared config options --------------------- @@ -96,7 +99,7 @@ since this data is not carried over from the cell culling process. .. _hurricane_mesh_lts: -If the LTS option is selected for the mesh test case, an additional step +If either LTS option is selected for the mesh test case, an additional step is carried out after the mesh culling. This step appropriately flags the cells of the mesh according to a user defined criterion in order to use time-steps of different sizes on different regions of the mesh. @@ -136,7 +139,7 @@ pointWiseStats analysis member for the forward run. compute topographic wave drag step ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This step is carried out only if the LTS option is selected for the init test case. +This step is carried out only if either LTS option is selected for the init test case. The reciprocal of the e-folding time, ``r_inv``, from the HyCOM model, is computed in this step. See @@ -165,6 +168,6 @@ is used for the validation. .. _hurricane_sandy_lts: -If the LTS option is selected for the sandy test case, the LTS scheme +If either LTS option is selected for the sandy test case, the LTS scheme is used to advance the solution in time rather than the default RK4 scheme.