Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch global_ocean and hurricane to framework base and culled mesh #429

Merged
merged 8 commits into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions compass/ocean/cached_files.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,40 @@
"ocean/global_convergence/qu/cosine_bell/QU60/init/namelist.ocean": "global_convergence/qu/cosine_bell/QU60/init/namelist.220528.ocean",
"ocean/global_convergence/qu/cosine_bell/QU60/init/initial_state.nc": "global_convergence/qu/cosine_bell/QU60/init/initial_state.220528.nc",
"ocean/global_convergence/qu/cosine_bell/QU90/init/namelist.ocean": "global_convergence/qu/cosine_bell/QU90/init/namelist.220528.ocean",
"ocean/global_convergence/qu/cosine_bell/QU90/init/initial_state.nc": "global_convergence/qu/cosine_bell/QU90/init/initial_state.220528.nc"
}
"ocean/global_convergence/qu/cosine_bell/QU90/init/initial_state.nc": "global_convergence/qu/cosine_bell/QU90/init/initial_state.220528.nc",
"ocean/global_ocean/Icos240/mesh/base_mesh/mesh.msh": "global_ocean/Icos240/mesh/base_mesh/mesh.220814.msh",
"ocean/global_ocean/Icos240/mesh/base_mesh/base_mesh.nc": "global_ocean/Icos240/mesh/base_mesh/base_mesh.220814.nc",
"ocean/global_ocean/Icos240/mesh/base_mesh/cellWidthVsLatLon.nc": "global_ocean/Icos240/mesh/base_mesh/cellWidthVsLatLon.220814.nc",
"ocean/global_ocean/Icos240/mesh/base_mesh/graph.info": "global_ocean/Icos240/mesh/base_mesh/graph.220814.info",
"ocean/global_ocean/Icos240/mesh/cull_mesh/culled_mesh.nc": "global_ocean/Icos240/mesh/cull_mesh/culled_mesh.220814.nc",
"ocean/global_ocean/Icos240/mesh/cull_mesh/culled_graph.info": "global_ocean/Icos240/mesh/cull_mesh/culled_graph.220814.info",
"ocean/global_ocean/Icos240/mesh/cull_mesh/critical_passages_mask_final.nc": "global_ocean/Icos240/mesh/cull_mesh/critical_passages_mask_final.220814.nc",
"ocean/global_ocean/QU240/mesh/base_mesh/mesh.msh": "global_ocean/QU240/mesh/base_mesh/mesh.220814.msh",
"ocean/global_ocean/QU240/mesh/base_mesh/base_mesh.nc": "global_ocean/QU240/mesh/base_mesh/base_mesh.220814.nc",
"ocean/global_ocean/QU240/mesh/base_mesh/cellWidthVsLatLon.nc": "global_ocean/QU240/mesh/base_mesh/cellWidthVsLatLon.220814.nc",
"ocean/global_ocean/QU240/mesh/base_mesh/graph.info": "global_ocean/QU240/mesh/base_mesh/graph.220814.info",
"ocean/global_ocean/QU240/mesh/cull_mesh/culled_mesh.nc": "global_ocean/QU240/mesh/cull_mesh/culled_mesh.220814.nc",
"ocean/global_ocean/QU240/mesh/cull_mesh/culled_graph.info": "global_ocean/QU240/mesh/cull_mesh/culled_graph.220814.info",
"ocean/global_ocean/QU240/mesh/cull_mesh/critical_passages_mask_final.nc": "global_ocean/QU240/mesh/cull_mesh/critical_passages_mask_final.220814.nc",
"ocean/global_ocean/QUwISC240/mesh/base_mesh/mesh.msh": "global_ocean/QUwISC240/mesh/base_mesh/mesh.220814.msh",
"ocean/global_ocean/QUwISC240/mesh/base_mesh/base_mesh.nc": "global_ocean/QUwISC240/mesh/base_mesh/base_mesh.220814.nc",
"ocean/global_ocean/QUwISC240/mesh/base_mesh/cellWidthVsLatLon.nc": "global_ocean/QUwISC240/mesh/base_mesh/cellWidthVsLatLon.220814.nc",
"ocean/global_ocean/QUwISC240/mesh/base_mesh/graph.info": "global_ocean/QUwISC240/mesh/base_mesh/graph.220814.info",
"ocean/global_ocean/QUwISC240/mesh/cull_mesh/culled_mesh.nc": "global_ocean/QUwISC240/mesh/cull_mesh/culled_mesh.220814.nc",
"ocean/global_ocean/QUwISC240/mesh/cull_mesh/culled_graph.info": "global_ocean/QUwISC240/mesh/cull_mesh/culled_graph.220814.info",
"ocean/global_ocean/QUwISC240/mesh/cull_mesh/critical_passages_mask_final.nc": "global_ocean/QUwISC240/mesh/cull_mesh/critical_passages_mask_final.220814.nc",
"ocean/global_ocean/EC30to60/mesh/base_mesh/mesh.msh": "global_ocean/EC30to60/mesh/base_mesh/mesh.220814.msh",
"ocean/global_ocean/EC30to60/mesh/base_mesh/base_mesh.nc": "global_ocean/EC30to60/mesh/base_mesh/base_mesh.220814.nc",
"ocean/global_ocean/EC30to60/mesh/base_mesh/cellWidthVsLatLon.nc": "global_ocean/EC30to60/mesh/base_mesh/cellWidthVsLatLon.220814.nc",
"ocean/global_ocean/EC30to60/mesh/base_mesh/graph.info": "global_ocean/EC30to60/mesh/base_mesh/graph.220814.info",
"ocean/global_ocean/EC30to60/mesh/cull_mesh/culled_mesh.nc": "global_ocean/EC30to60/mesh/cull_mesh/culled_mesh.220814.nc",
"ocean/global_ocean/EC30to60/mesh/cull_mesh/culled_graph.info": "global_ocean/EC30to60/mesh/cull_mesh/culled_graph.220814.info",
"ocean/global_ocean/EC30to60/mesh/cull_mesh/critical_passages_mask_final.nc": "global_ocean/EC30to60/mesh/cull_mesh/critical_passages_mask_final.220814.nc",
"ocean/global_ocean/ECwISC30to60/mesh/base_mesh/mesh.msh": "global_ocean/ECwISC30to60/mesh/base_mesh/mesh.220814.msh",
"ocean/global_ocean/ECwISC30to60/mesh/base_mesh/base_mesh.nc": "global_ocean/ECwISC30to60/mesh/base_mesh/base_mesh.220814.nc",
"ocean/global_ocean/ECwISC30to60/mesh/base_mesh/cellWidthVsLatLon.nc": "global_ocean/ECwISC30to60/mesh/base_mesh/cellWidthVsLatLon.220814.nc",
"ocean/global_ocean/ECwISC30to60/mesh/base_mesh/graph.info": "global_ocean/ECwISC30to60/mesh/base_mesh/graph.220814.info",
"ocean/global_ocean/ECwISC30to60/mesh/cull_mesh/culled_mesh.nc": "global_ocean/ECwISC30to60/mesh/cull_mesh/culled_mesh.220814.nc",
"ocean/global_ocean/ECwISC30to60/mesh/cull_mesh/culled_graph.info": "global_ocean/ECwISC30to60/mesh/cull_mesh/culled_graph.220814.info",
"ocean/global_ocean/ECwISC30to60/mesh/cull_mesh/critical_passages_mask_final.nc": "global_ocean/ECwISC30to60/mesh/cull_mesh/critical_passages_mask_final.220814.nc"
}
Empty file added compass/ocean/mesh/__init__.py
Empty file.
117 changes: 117 additions & 0 deletions ...ass/ocean/tests/global_ocean/mesh/cull.py → compass/ocean/mesh/cull.py
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,16 +1,133 @@
import xarray
import os

from geometric_features import GeometricFeatures, FeatureCollection, \
read_feature_collection
from mpas_tools.mesh.conversion import cull
from mpas_tools.mesh.mask import compute_mpas_flood_fill_mask
import mpas_tools.io
from mpas_tools.io import write_netcdf
from mpas_tools.ocean import inject_bathymetry
from mpas_tools.ocean.coastline_alteration import widen_transect_edge_masks, \
add_critical_land_blockages, add_land_locked_cells_to_mask
from mpas_tools.viz.paraview_extractor import extract_vtk
from mpas_tools.logging import LoggingContext, check_call

from compass.step import Step


class CullMeshStep(Step):
"""
A step for culling a global MPAS-Ocean mesh

Attributes
----------
base_mesh_step : compass.mesh.spherical.SphericalBaseStep
The base mesh step containing input files to this step

with_ice_shelf_cavities : bool
Whether the mesh includes ice-shelf cavities

do_inject_bathymetry : bool
Whether to interpolate bathymetry from a data file so it
can be used as a culling criteria

preserve_floodplain : bool
Whether to leave land cells in the mesh based on bathymetry
specified by do_inject_bathymetry
"""

def __init__(self, test_case, base_mesh_step, with_ice_shelf_cavities,
name='cull_mesh', subdir=None, do_inject_bathymetry=False,
preserve_floodplain=False):
"""
Create a new step

Parameters
----------
test_case : compass.ocean.tests.global_ocean.mesh.Mesh
The test case this step belongs to

base_mesh_step : compass.mesh.spherical.SphericalBaseStep
The base mesh step containing input files to this step

with_ice_shelf_cavities : bool
Whether the mesh includes ice-shelf cavities

name : str, optional
the name of the step

subdir : str, optional
the subdirectory for the step. The default is ``name``

do_inject_bathymetry : bool, optional
Whether to interpolate bathymetry from a data file so it
can be used as a culling criteria

preserve_floodplain : bool, optional
Whether to leave land cells in the mesh based on bathymetry
specified by do_inject_bathymetry
"""
super().__init__(test_case, name=name, subdir=subdir,
cpus_per_task=None, min_cpus_per_task=None)
self.base_mesh_step = base_mesh_step

for file in ['culled_mesh.nc', 'culled_graph.info',
'critical_passages_mask_final.nc']:
self.add_output_file(filename=file)

self.with_ice_shelf_cavities = with_ice_shelf_cavities
self.do_inject_bathymetry = do_inject_bathymetry
self.preserve_floodplain = preserve_floodplain

def setup(self):
"""
Set up the test case in the work directory, including downloading any
dependencies.
"""
super().setup()
if self.do_inject_bathymetry:
self.add_input_file(
filename='earth_relief_15s.nc',
target='SRTM15_plus_earth_relief_15s.nc',
database='bathymetry_database')

# get the these properties from the config options
config = self.config
# todo: move to constrain_resources()
self.cpus_per_task = config.getint('spherical_mesh',
'cull_mesh_cpus_per_task')
self.min_cpus_per_task = config.getint('spherical_mesh',
'cull_mesh_min_cpus_per_task')

base_path = self.base_mesh_step.path
base_filename = self.base_mesh_step.config.get(
'spherical_mesh', 'mpas_mesh_filename')
target = os.path.join(base_path, base_filename)
self.add_input_file(filename='base_mesh.nc', work_dir_target=target)

def run(self):
"""
Run this step of the test case
"""
with_ice_shelf_cavities = self.with_ice_shelf_cavities
logger = self.logger

# only use progress bars if we're not writing to a log file
use_progress_bar = self.log_filename is None

do_inject_bathymetry = self.do_inject_bathymetry
preserve_floodplain = self.preserve_floodplain

cull_mesh(with_critical_passages=True, logger=logger,
use_progress_bar=use_progress_bar,
preserve_floodplain=preserve_floodplain,
with_cavities=with_ice_shelf_cavities,
process_count=self.cpus_per_task)

if do_inject_bathymetry:
inject_bathymetry(mesh_file='culled_mesh.nc')


def cull_mesh(with_cavities=False, with_critical_passages=False,
custom_critical_passages=None, custom_land_blockages=None,
Expand Down
63 changes: 63 additions & 0 deletions compass/ocean/mesh/floodplain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from mpas_tools.ocean import inject_bathymetry, inject_preserve_floodplain

from compass.mesh.spherical import QuasiUniformSphericalMeshStep


class FloodplainMeshStep(QuasiUniformSphericalMeshStep):
"""
A step for creating a global MPAS-Ocean mesh that includes variables
needed for preserving a floodplain

preserve_floodplain : bool
Whether the mesh includes land cells
"""

def __init__(self, test_case, name='base_mesh', subdir=None,
cell_width=None, preserve_floodplain=True):
"""
Create a new step

Parameters
----------
test_case : compass.testcase.TestCase
The test case this step belongs to

name : str
the name of the step

subdir : {str, None}
the subdirectory for the step. The default is ``name``

cell_width : float, optional
The approximate cell width in km of the mesh if constant resolution

preserve_floodplain : bool, optional
Whether the mesh includes land cells
"""

super().__init__(test_case=test_case, name=name, subdir=subdir,
cell_width=cell_width)

self.preserve_floodplain = preserve_floodplain

self.add_input_file(filename='earth_relief_15s.nc',
target='SRTM15_plus_earth_relief_15s.nc',
database='bathymetry_database')

def run(self):
"""
Run this step of the test case
"""
super().run()

config = self.config

mesh_filename = config.get('spherical_mesh', 'mpas_mesh_filename')

inject_bathymetry(mesh_file=mesh_filename)
if self.preserve_floodplain:
floodplain_elevation = config.getfloat('spherical_mesh',
'floodplain_elevation')
inject_preserve_floodplain(
mesh_file=mesh_filename,
floodplain_elevation=floodplain_elevation)
2 changes: 1 addition & 1 deletion compass/ocean/tests/global_ocean/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def __init__(self, mpas_core):
super().__init__(mpas_core=mpas_core, name='global_ocean')

# we do a lot of tests for QU240/QUwISC240
for mesh_name in ['QU240', 'QUwISC240']:
for mesh_name in ['QU240', 'Icos240', 'QUwISC240']:
mesh = Mesh(test_group=self, mesh_name=mesh_name)
self.add_test_case(mesh)

Expand Down
4 changes: 2 additions & 2 deletions compass/ocean/tests/global_ocean/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ def configure_global_ocean(test_case, mesh, init=None):
The test case that produces the initial condition for this run
"""
config = test_case.config
mesh_step = mesh.mesh_step
config.add_from_package(mesh_step.package, mesh_step.mesh_config_filename,
config.add_from_package('compass.mesh', 'mesh.cfg')
config.add_from_package(mesh.package, mesh.mesh_config_filename,
exception=True)

if mesh.with_ice_shelf_cavities:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(self, test_case, mesh, restart_filename):
self.add_input_file(filename='restart.nc',
target='../{}'.format(restart_filename))

mesh_path = mesh.mesh_step.path
mesh_path = mesh.get_cull_mesh_path()
self.add_input_file(
filename='graph.info',
work_dir_target='{}/culled_graph.info'.format(mesh_path))
Expand Down
2 changes: 1 addition & 1 deletion compass/ocean/tests/global_ocean/forward.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def __init__(self, test_case, mesh, init, time_integrator, name='forward',
self.add_streams_file(
'compass.ocean.tests.global_ocean', 'streams.bgc')

mesh_package = mesh.mesh_step.package
mesh_package = mesh.package
mesh_package_contents = list(contents(mesh_package))
mesh_namelists = ['namelist.forward',
f'namelist.{time_integrator.lower()}']
Expand Down
20 changes: 12 additions & 8 deletions compass/ocean/tests/global_ocean/global_ocean.cfg
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# options for global ocean testcases
[global_ocean]
# options for spherical meshes
[spherical_mesh]

## each mesh should replace these with appropriate values in its config file

## config options related to the mesh step
## config options related to the step for culling land from the mesh
# number of cores to use
mesh_cpus_per_task = 18
cull_mesh_cpus_per_task = 18
# minimum of cores, below which the step fails
mesh_min_cpus_per_task = 1
cull_mesh_min_cpus_per_task = 1
# maximum memory usage allowed (in MB)
mesh_max_memory = 1000
cull_mesh_max_memory = 1000


# options for global ocean testcases
[global_ocean]

## each mesh should replace these with appropriate values in its config file

## config options related to the initial_state step
# number of cores to use
Expand Down
4 changes: 2 additions & 2 deletions compass/ocean/tests/global_ocean/init/initial_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def __init__(self, test_case, mesh, initial_condition, with_bgc):
'1timeLevel.nc',
database='initial_condition_database')

mesh_path = mesh.mesh_step.path
mesh_path = self.mesh.get_cull_mesh_path()

self.add_input_file(
filename='mesh.nc',
Expand All @@ -123,7 +123,7 @@ def __init__(self, test_case, mesh, initial_condition, with_bgc):
filename='graph.info',
work_dir_target=f'{mesh_path}/culled_graph.info')

if mesh.with_ice_shelf_cavities:
if self.mesh.with_ice_shelf_cavities:
self.add_input_file(
filename='land_ice_mask.nc',
work_dir_target=f'{mesh_path}/land_ice_mask.nc')
Expand Down
2 changes: 1 addition & 1 deletion compass/ocean/tests/global_ocean/init/ssh_adjustment.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def __init__(self, test_case, ntasks=None, min_tasks=None,
self.add_streams_file('compass.ocean.tests.global_ocean.init',
'streams.ssh_adjust')

mesh_path = test_case.mesh.mesh_step.path
mesh_path = test_case.mesh.get_cull_mesh_path()
init_path = test_case.steps['initial_state'].path

self.add_input_file(
Expand Down
Loading