Source code for compass.ocean.tests.utility.create_salin_restoring.extrap

from datetime import datetime

import numpy as np
import xarray as xr
from scipy.signal import convolve2d

from compass.step import Step


[docs] class Extrap(Step): """ Extrapolate WOA 2023 monthly sea surface salinity data into missing ocean regions, including ice cavities and coasts Attributes ---------- woa_filename : str The name of the output file name after extrapolation """
[docs] def __init__(self, test_case): """ Create the step Parameters ---------- test_case : compass.ocean.tests.utility.create_salin_restoring.CreateSalinRestoring The test case this step belongs to """ # noqa: E501 super().__init__(test_case=test_case, name='extrap', cpus_per_task=64, min_cpus_per_task=1, openmp_threads=1) self.add_input_file( filename='woa_surface_salinity_monthly.nc', target='../combine/woa_surface_salinity_monthly.nc') self.woa_filename = None
def setup(self): """ Determine the output filename """ super().setup() now = datetime.now() datestring = now.strftime("%Y%m%d") self.woa_filename = f'woa23_decav_0.25_sss_monthly_extrap.' \ f'{datestring}.nc' self.add_output_file(self.woa_filename) def run(self): """ Extrapolate WOA 2023 model temperature and salinity into ice-shelf cavities. """ super().run() # extrapolate horizontally using the ocean mask _extrap(self.woa_filename)
def _extrap(out_filename): in_filename = 'woa_surface_salinity_monthly.nc' ds = xr.open_dataset(in_filename) field = ds.SALT.values.copy() # a small averaging kernel x = np.arange(-1, 2) x, y = np.meshgrid(x, x) kernel = np.exp(-0.5 * (x**2 + y**2)) threshold = 0.01 nlon = field.shape[-1] lon_with_halo = np.array([nlon - 2, nlon - 1] + list(range(nlon)) + [0, 1]) lon_no_halo = list(range(2, nlon + 2)) for i in range(12): valid = np.isfinite(field[i, :, :]) orig_mask = valid prev_fill_count = 0 while True: valid_weight_sum = _extrap_with_halo(valid, kernel, valid, lon_with_halo, lon_no_halo) new_valid = valid_weight_sum > threshold # don't want to overwrite original data but do want ot smooth # extrapolated data fill_mask = np.logical_and(new_valid, np.logical_not(orig_mask)) fill_count = np.count_nonzero(fill_mask) if fill_count == prev_fill_count: # no change so we're done break field_extrap = _extrap_with_halo(field[i, :, :], kernel, valid, lon_with_halo, lon_no_halo) field[i, fill_mask] = field_extrap[fill_mask] / \ valid_weight_sum[fill_mask] valid = new_valid prev_fill_count = fill_count attrs = ds.SALT.attrs dims = ds.SALT.dims ds['SALT'] = (dims, field) ds['SALT'].attrs = attrs ds.to_netcdf(out_filename) def _extrap_with_halo(field, kernel, valid, lon_with_halo, lon_no_halo): field = field.copy() field[np.logical_not(valid)] = 0. field_with_halo = field[:, lon_with_halo] field_extrap = convolve2d(field_with_halo, kernel, mode='same') field_extrap = field_extrap[:, lon_no_halo] return field_extrap