Source code for compass.ocean.tests.utility
-from compass.ocean.tests.utility.cull_restarts import CullRestarts
+from compass.ocean.tests.utility.combine_topo import CombineTopo
+from compass.ocean.tests.utility.cull_restarts import CullRestarts
from compass.ocean.tests.utility.extrap_woa import ExtrapWoa
from compass.testgroup import TestGroup
@@ -132,6 +133,7 @@ Source code for compass.ocean.tests.utility
"""
super().__init__(mpas_core=mpas_core, name='utility')
+ self.add_test_case(CombineTopo(test_group=self))
self.add_test_case(CullRestarts(test_group=self))
self.add_test_case(ExtrapWoa(test_group=self))
Source code for compass.ocean.tests.utility.combine_topo
+import numpy as np
+import progressbar
+import pyproj
+import xarray as xr
+from pyremap import LatLonGridDescriptor, ProjectionGridDescriptor, Remapper
+
+from compass.step import Step
+from compass.testcase import TestCase
+
+
+
+[docs]
+class CombineTopo(TestCase):
+ """
+ A test case for combining GEBCO 2023 with BedMachineAntarctica topography
+ datasets
+ """
+
+
+[docs]
+ def __init__(self, test_group):
+ """
+ Create the test case
+
+ Parameters
+ ----------
+ test_group : compass.ocean.tests.utility.Utility
+ The test group that this test case belongs to
+ """
+ super().__init__(test_group=test_group, name='combine_topo')
+
+ self.add_step(Combine(test_case=self))
+
+
+
+
+
+[docs]
+class Combine(Step):
+ """
+ A step for combining GEBCO 2023 with BedMachineAntarctica topography
+ datasets
+ """
+
+
+[docs]
+ def __init__(self, test_case):
+ """
+ Create a new step
+
+ Parameters
+ ----------
+ test_case : compass.ocean.tests.utility.extrap_woa.ExtraWoa
+ The test case this step belongs to
+ """
+ super().__init__(test_case, name='combine', ntasks=None,
+ min_tasks=None)
+
+
+
+[docs]
+ def setup(self):
+ """
+ Set up the step in the work directory, including downloading any
+ dependencies.
+ """
+ super().setup()
+
+ config = self.config
+ section = config['combine_topo']
+ antarctic_filename = section.get('antarctic_filename')
+ self.add_input_file(filename=antarctic_filename,
+ target=antarctic_filename,
+ database='bathymetry_database')
+ global_filename = section.get('global_filename')
+ self.add_input_file(filename=global_filename,
+ target=global_filename,
+ database='bathymetry_database')
+
+ cobined_filename = section.get('cobined_filename')
+ self.add_output_file(filename=cobined_filename)
+
+ self.ntasks = section.getint('ntasks')
+ self.min_tasks = section.getint('min_tasks')
+
+
+
+[docs]
+ def run(self):
+ """
+ Run this step of the test case
+ """
+ self._downsample_gebco()
+ self._modify_bedmachine()
+ # we will work with bedmachine data at its original resolution
+ # self._downsample_bedmachine()
+ self._remap_bedmachine()
+ self._combine()
+
+
+ def _downsample_gebco(self):
+ """
+ Average GEBCO to 0.0125 degree grid. GEBCO is on 15" grid, so average
+ every 3x3 block of cells
+ """
+ config = self.config
+ logger = self.logger
+
+ section = config['combine_topo']
+ in_filename = section.get('global_filename')
+ out_filename = 'GEBCO_2023_0.0125_degree.nc'
+
+ gebco = xr.open_dataset(in_filename)
+
+ nlon = gebco.sizes['lon']
+ nlat = gebco.sizes['lat']
+
+ block = 3
+ norm = 1.0 / block**2
+
+ nx = nlon // block
+ ny = nlat // block
+
+ chunks = 2
+ nxchunk = nlon // chunks
+ nychunk = nlat // chunks
+
+ gebco = gebco.chunk({'lon': nxchunk, 'lat': nychunk})
+
+ bathymetry = np.zeros((ny, nx))
+
+ logger.info('Averaging GEBCO to 0.0125 degree grid')
+ widgets = [progressbar.Percentage(), ' ',
+ progressbar.Bar(), ' ', progressbar.ETA()]
+ bar = progressbar.ProgressBar(widgets=widgets,
+ maxval=chunks**2).start()
+ for ychunk in range(chunks):
+ for xchunk in range(chunks):
+ gebco_chunk = gebco.isel(
+ lon=slice(nxchunk * xchunk, nxchunk * (xchunk + 1)),
+ lat=slice(nychunk * ychunk, nychunk * (ychunk + 1)))
+ elevation = gebco_chunk.elevation.values
+ nxblock = nxchunk // block
+ nyblock = nychunk // block
+ bathy_block = np.zeros((nyblock, nxblock))
+ for y in range(block):
+ for x in range(block):
+ bathy_block += elevation[y::block, x::block]
+ bathy_block *= norm
+ xmin = xchunk * nxblock
+ xmax = (xchunk + 1) * nxblock
+ ymin = ychunk * nyblock
+ ymax = (ychunk + 1) * nyblock
+ bathymetry[ymin:ymax, xmin:xmax] = bathy_block
+ bar.update(ychunk * chunks + xchunk + 1)
+ bar.finish()
+
+ lon_corner = np.linspace(-180., 180., bathymetry.shape[1] + 1)
+ lat_corner = np.linspace(-90., 90., bathymetry.shape[0] + 1)
+ lon = 0.5 * (lon_corner[0:-1] + lon_corner[1:])
+ lat = 0.5 * (lat_corner[0:-1] + lat_corner[1:])
+ gebco_low = xr.Dataset({'bathymetry': (['lat', 'lon'], bathymetry)},
+ coords={'lon': (['lon',], lon),
+ 'lat': (['lat',], lat)})
+ gebco_low.attrs = gebco.attrs
+ gebco_low.lon.attrs = gebco.lon.attrs
+ gebco_low.lat.attrs = gebco.lat.attrs
+ gebco_low.bathymetry.attrs = gebco.elevation.attrs
+ gebco_low.to_netcdf(out_filename)
+
+ def _modify_bedmachine(self):
+ """
+ Modify BedMachineAntarctica to compute the fields needed by MPAS-Ocean
+ """
+ logger = self.logger
+ logger.info('Modifying BedMachineAntarctica with MPAS-Ocean names')
+
+ config = self.config
+
+ section = config['combine_topo']
+ in_filename = section.get('antarctic_filename')
+ out_filename = 'BedMachineAntarctica-v3_mod.nc'
+ bedmachine = xr.open_dataset(in_filename)
+ mask = bedmachine.mask
+ ice_mask = (mask != 0).astype(float)
+ ocean_mask = (np.logical_or(mask == 0, mask == 3)).astype(float)
+ grounded_mask = np.logical_or(np.logical_or(mask == 1, mask == 2),
+ mask == 4).astype(float)
+
+ bedmachine['bathymetry'] = bedmachine.bed.where(ocean_mask, 0.)
+ bedmachine['ice_draft'] = \
+ (bedmachine.surface -
+ bedmachine.thickness).where(ocean_mask, 0.)
+ bedmachine.ice_draft.attrs['units'] = 'meters'
+ bedmachine['thickness'] = \
+ bedmachine.thickness.where(ocean_mask, 0.)
+
+ bedmachine['ice_mask'] = ice_mask
+ bedmachine['grounded_mask'] = grounded_mask
+ bedmachine['ocean_mask'] = ocean_mask
+
+ varlist = ['bathymetry', 'ice_draft', 'thickness', 'ice_mask',
+ 'grounded_mask', 'ocean_mask']
+
+ bedmachine = bedmachine[varlist]
+
+ bedmachine.to_netcdf(out_filename)
+ logger.info(' Done.')
+
+ def _downsample_bedmachine(self):
+ """
+ Downsample bedmachine from 0.5 to 1 km grid
+ """
+ logger = self.logger
+ logger.info('Downsample BedMachineAntarctica from 500 m to 1 km')
+
+ in_filename = 'BedMachineAntarctica-v3_mod.nc'
+ out_filename = 'BedMachineAntarctica-v3_1k.nc'
+ bedmachine = xr.open_dataset(in_filename)
+ x = bedmachine.x.values
+ y = bedmachine.y.values
+
+ nx = len(x) // 2
+ ny = len(y) // 2
+ x = 0.5 * (x[0:2 * nx:2] + x[1:2 * nx:2])
+ y = 0.5 * (y[0:2 * ny:2] + y[1:2 * ny:2])
+ bedmachine1k = xr.Dataset()
+ for field in bedmachine.data_vars:
+ in_array = bedmachine[field].values
+ out_array = np.zeros((ny, nx))
+ for yoffset in range(2):
+ for xoffset in range(2):
+ out_array += 0.25 * \
+ in_array[yoffset:2 * ny:2, xoffset:2 * nx:2]
+ da = xr.DataArray(out_array, dims=('y', 'x'),
+ coords={'x': (('x',), x),
+ 'y': (('y',), y)})
+ bedmachine1k[field] = da
+ bedmachine1k[field].attrs = bedmachine[field].attrs
+
+ bedmachine1k.to_netcdf(out_filename)
+ logger.info(' Done.')
+
+ def _remap_bedmachine(self):
+ """
+ Remap BedMachine Antarctica to GEBCO lat-lon grid
+ """
+ logger = self.logger
+ logger.info('Remap BedMachineAntarctica to GEBCO 1/80 deg grid')
+
+ config = self.config
+
+ section = config['combine_topo']
+ renorm_thresh = section.getfloat('renorm_thresh')
+
+ in_filename = 'BedMachineAntarctica-v3_mod.nc'
+ out_filename = 'BedMachineAntarctica_on_GEBCO_low.nc'
+ gebco_filename = 'GEBCO_2023_0.0125_degree.nc'
+
+ projection = pyproj.Proj('+proj=stere +lat_ts=-71.0 +lat_0=-90 '
+ '+lon_0=0.0 +k_0=1.0 +x_0=0.0 +y_0=0.0 '
+ '+ellps=WGS84')
+
+ bedmachine = xr.open_dataset(in_filename)
+ x = bedmachine.x.values
+ y = bedmachine.y.values
+
+ in_descriptor = ProjectionGridDescriptor.create(
+ projection, x, y, 'BedMachineAntarctica_500m')
+
+ out_descriptor = LatLonGridDescriptor.read(fileName=gebco_filename)
+
+ mapping_filename = \
+ 'map_BedMachineAntarctica_500m_to_GEBCO_0.0125deg_bilinear.nc'
+
+ remapper = Remapper(in_descriptor, out_descriptor, mapping_filename)
+ remapper.build_mapping_file(method='bilinear', mpiTasks=self.ntasks,
+ esmf_parallel_exec='srun', tempdir='.')
+ bedmachine = xr.open_dataset(in_filename)
+ bedmachine_on_gebco_low = remapper.remap(bedmachine)
+
+ for field in ['bathymetry', 'ice_draft', 'thickness']:
+ bedmachine_on_gebco_low[field].attrs['unit'] = 'meters'
+
+ # renormalize the fields based on the ocean masks
+ ocean_mask = bedmachine_on_gebco_low.ocean_mask
+
+ valid = ocean_mask > renorm_thresh
+ norm = ocean_mask.where(valid, 1.)
+ norm = 1. / norm
+ for field in ['bathymetry', 'ice_draft', 'thickness']:
+ bedmachine_on_gebco_low[field] = \
+ norm * bedmachine_on_gebco_low[field].where(valid, 0.)
+
+ bedmachine_on_gebco_low.to_netcdf(out_filename)
+ logger.info(' Done.')
+
+ def _combine(self):
+ """
+ Combine GEBCO with BedMachine Antarctica
+ """
+ logger = self.logger
+ logger.info('Combine BedMachineAntarctica and GEBCO')
+
+ config = self.config
+ section = config['combine_topo']
+
+ latmin = section.getfloat('latmin')
+ latmax = section.getfloat('latmax')
+ cobined_filename = section.get('cobined_filename')
+
+ gebco_filename = 'GEBCO_2023_0.0125_degree.nc'
+ gebco = xr.open_dataset(gebco_filename)
+
+ bedmachine_filename = 'BedMachineAntarctica_on_GEBCO_low.nc'
+ bedmachine = xr.open_dataset(bedmachine_filename)
+
+ combined = xr.Dataset()
+ alpha = (gebco.lat - latmin) / (latmax - latmin)
+ alpha = np.maximum(np.minimum(alpha, 1.0), 0.0)
+
+ bedmachine_bathy = bedmachine.bathymetry
+ valid = bedmachine_bathy.notnull()
+ bedmachine_bathy = bedmachine_bathy.where(valid, 0.)
+
+ combined['bathymetry'] = \
+ alpha * gebco.bathymetry.where(gebco.bathymetry < 0, 0.) + \
+ (1.0 - alpha) * bedmachine_bathy
+ for field in ['ice_draft', 'thickness']:
+ combined[field] = bedmachine[field]
+ for field in ['bathymetry', 'ice_draft', 'thickness']:
+ combined[field].attrs['unit'] = 'meters'
+
+ fill = {'ice_mask': 0., 'grounded_mask': 0.,
+ 'ocean_mask': combined['bathymetry'] < 0.}
+
+ for field, fill_val in fill.items():
+ valid = bedmachine[field].notnull()
+ combined[field] = bedmachine[field].where(valid, fill_val)
+
+ combined['water_column'] = \
+ combined['ice_draft'] - combined['bathymetry']
+ combined.water_column.attrs['units'] = 'meters'
+
+ combined.to_netcdf(cobined_filename)
+ logger.info(' Done.')
+
+ diff = xr.Dataset()
+
+ diff['bathymetry'] = \
+ gebco.bathymetry.where(gebco.bathymetry < 0, 0.) - \
+ bedmachine.bathymetry
+ diff.to_netcdf('gebco_minus_bedmachine.nc')
+
+
All modules for which code is available
- compass.ocean.tests.utility.cull_restarts +
- compass.ocean.tests.utility.combine_topo +
- compass.ocean.tests.utility.cull_restarts
- compass.ocean.tests.utility.extrap_woa
- compass.ocean.tests.utility.extrap_woa.combine diff --git a/latest/_sources/developers_guide/ocean/api.rst.txt b/latest/_sources/developers_guide/ocean/api.rst.txt index a956b8ab5a..733aa0f21f 100644 --- a/latest/_sources/developers_guide/ocean/api.rst.txt +++ b/latest/_sources/developers_guide/ocean/api.rst.txt @@ -907,6 +907,11 @@ utility Utility + combine_topo.CombineTopo + combine_topo.Combine + combine_topo.Combine.setup + combine_topo.Combine.run + cull_restarts.CullRestarts cull_restarts.Cull cull_restarts.Cull.run diff --git a/latest/_sources/developers_guide/ocean/generated/compass.ocean.tests.utility.combine_topo.Combine.rst.txt b/latest/_sources/developers_guide/ocean/generated/compass.ocean.tests.utility.combine_topo.Combine.rst.txt new file mode 100644 index 0000000000..17ed4849db --- /dev/null +++ b/latest/_sources/developers_guide/ocean/generated/compass.ocean.tests.utility.combine_topo.Combine.rst.txt @@ -0,0 +1,37 @@ +compass.ocean.tests.utility.combine\_topo.Combine +================================================= + +.. currentmodule:: compass.ocean.tests.utility.combine_topo + +.. autoclass:: Combine + + + .. automethod:: __init__ + + + .. rubric:: Methods + + .. autosummary:: + + ~Combine.__init__ + ~Combine.add_input_file + ~Combine.add_model_as_input + ~Combine.add_namelist_file + ~Combine.add_namelist_options + ~Combine.add_output_file + ~Combine.add_streams_file + ~Combine.constrain_resources + ~Combine.process_inputs_and_outputs + ~Combine.run + ~Combine.runtime_setup + ~Combine.set_resources + ~Combine.setup + ~Combine.update_namelist_at_runtime + ~Combine.update_namelist_pio + ~Combine.update_streams_at_runtime + + + + + + \ No newline at end of file diff --git a/latest/_sources/developers_guide/ocean/generated/compass.ocean.tests.utility.combine_topo.Combine.run.rst.txt b/latest/_sources/developers_guide/ocean/generated/compass.ocean.tests.utility.combine_topo.Combine.run.rst.txt new file mode 100644 index 0000000000..7540799b0e --- /dev/null +++ b/latest/_sources/developers_guide/ocean/generated/compass.ocean.tests.utility.combine_topo.Combine.run.rst.txt @@ -0,0 +1,6 @@ +compass.ocean.tests.utility.combine\_topo.Combine.run +===================================================== + +.. currentmodule:: compass.ocean.tests.utility.combine_topo + +.. automethod:: Combine.run \ No newline at end of file diff --git a/latest/_sources/developers_guide/ocean/generated/compass.ocean.tests.utility.combine_topo.Combine.setup.rst.txt b/latest/_sources/developers_guide/ocean/generated/compass.ocean.tests.utility.combine_topo.Combine.setup.rst.txt new file mode 100644 index 0000000000..98807db0a1 --- /dev/null +++ b/latest/_sources/developers_guide/ocean/generated/compass.ocean.tests.utility.combine_topo.Combine.setup.rst.txt @@ -0,0 +1,6 @@ +compass.ocean.tests.utility.combine\_topo.Combine.setup +======================================================= + +.. currentmodule:: compass.ocean.tests.utility.combine_topo + +.. automethod:: Combine.setup \ No newline at end of file diff --git a/latest/_sources/developers_guide/ocean/generated/compass.ocean.tests.utility.combine_topo.CombineTopo.rst.txt b/latest/_sources/developers_guide/ocean/generated/compass.ocean.tests.utility.combine_topo.CombineTopo.rst.txt new file mode 100644 index 0000000000..29df1e00b5 --- /dev/null +++ b/latest/_sources/developers_guide/ocean/generated/compass.ocean.tests.utility.combine_topo.CombineTopo.rst.txt @@ -0,0 +1,27 @@ +compass.ocean.tests.utility.combine\_topo.CombineTopo +===================================================== + +.. currentmodule:: compass.ocean.tests.utility.combine_topo + +.. autoclass:: CombineTopo + + + .. automethod:: __init__ + + + .. rubric:: Methods + + .. autosummary:: + + ~CombineTopo.__init__ + ~CombineTopo.add_step + ~CombineTopo.check_validation + ~CombineTopo.configure + ~CombineTopo.run + ~CombineTopo.validate + + + + + + \ No newline at end of file diff --git a/latest/_sources/developers_guide/ocean/test_groups/utility.rst.txt b/latest/_sources/developers_guide/ocean/test_groups/utility.rst.txt index 649655ee71..f1157ecbbd 100644 --- a/latest/_sources/developers_guide/ocean/test_groups/utility.rst.txt +++ b/latest/_sources/developers_guide/ocean/test_groups/utility.rst.txt @@ -8,6 +8,22 @@ may create datasets for other test groups to use. It is partly designed to provide provenance for data processing that may be more complex than a single, short script. +combine_topo +------------ +The class :py:class:`compass.ocean.tests.utility.combine_topo.CombineTopo` +defines a test case for combining the +`BedMachine Antarctica v3
utility¶
Utility
(mpas_core)
A test group for general ocean utilities
+combine_topo.CombineTopo
(test_group)
+A test case for combining GEBCO 2023 with BedMachineAntarctica topography datasets
+
+combine_topo.Combine
(test_case)
+A step for combining GEBCO 2023 with BedMachineAntarctica topography datasets
+
+
+Set up the step in the work directory, including downloading any dependencies.
+
+
+Run this step of the test case
+
cull_restarts.CullRestarts
(test_group)
A test case for culling MPAS-Ocean and -Seaice restart files to exclude ice-shelf cavities
diff --git a/latest/developers_guide/ocean/generated/compass.ocean.tests.utility.Utility.html b/latest/developers_guide/ocean/generated/compass.ocean.tests.utility.Utility.html
index 16921a02bc..d79f038d55 100644
--- a/latest/developers_guide/ocean/generated/compass.ocean.tests.utility.Utility.html
+++ b/latest/developers_guide/ocean/generated/compass.ocean.tests.utility.Utility.html
@@ -19,7 +19,7 @@
-
+
@@ -162,7 +162,7 @@ compass.ocean.tests.utility.Utility
Previous
- Next
+ Next
Utility
(mpas_core)
A test group for general ocean utilities
combine_topo.CombineTopo
(test_group)
A test case for combining GEBCO 2023 with BedMachineAntarctica topography datasets
combine_topo.Combine
(test_case)
A step for combining GEBCO 2023 with BedMachineAntarctica topography datasets
Set up the step in the work directory, including downloading any dependencies.
Run this step of the test case
cull_restarts.CullRestarts
(test_group)
A test case for culling MPAS-Ocean and -Seaice restart files to exclude ice-shelf cavities