Source code for compass.landice.extrapolate

import numpy as np
from netCDF4 import Dataset
import sys
from datetime import datetime

[docs]def extrapolate_variable(nc_file, var_name, extrap_method, set_value=None): """ Function to extrapolate variable values into undefined regions Parameters ---------- nc_file : str the mpas file to modify var_name : str the mpas variable to extrapolate extrap_method : str idw, min, or value method of extrapolation set_value : float value to set variable to outside keepCellMask when using -v value """ dataset = Dataset(nc_file, 'r+') varValue = dataset.variables[var_name][0, :] # Extrapolation nCells = len(dataset.dimensions['nCells']) if 'thickness' in dataset.variables.keys(): thickness = dataset.variables['thickness'][0,:] bed = dataset.variables["bedTopography"][0,:] cellsOnCell = dataset.variables['cellsOnCell'][:] nEdgesOnCell = dataset.variables['nEdgesOnCell'][:] xCell = dataset.variables["yCell"][:] yCell = dataset.variables["xCell"][:] # Define region of good data to extrapolate from. Different methods for different variables if var_name in ["effectivePressure", "beta", "muFriction"]: groundedMask = (thickness > (-1028.0 / 910.0 * bed)) keepCellMask = np.copy(groundedMask) extrap_method == "min" # grow mask by one cell oceanward of GL for iCell in range(nCells): for n in range(nEdgesOnCell[iCell]): jCell = cellsOnCell[iCell, n] - 1 if (groundedMask[jCell] == 1): keepCellMask[iCell] = 1 continue keepCellMask *= (varValue > 0) # ensure zero muFriction does not get extrapolated elif var_name in ["floatingBasalMassBal"]: floatingMask = (thickness <= (-1028.0 / 910.0 * bed)) keepCellMask = floatingMask * (varValue != 0.0) extrap_method == "idw" else: keepCellMask = (thickness > 0.0) keepCellMaskNew = np.copy(keepCellMask) # make a copy to edit that will be used later keepCellMaskOrig = np.copy(keepCellMask) # make a copy to edit that can be edited without changing the original # recursive extrapolation steps: # 1) find cell A with mask = 0 # 2) find how many surrounding cells have nonzero mask, and their indices (this will give us the cells from upstream) # 3) use the values for nonzero mask upstream cells to extrapolate the value for cell A # 4) change the mask for A from 0 to 1 # 5) Update mask # 6) go to step 1) print("Start {} extrapolation using {} method".format(var_name, extrap_method)) if extrap_method == 'value': varValue[np.where(np.logical_not(keepCellMask))] = float(options.set_value) else: while np.count_nonzero(keepCellMask) != nCells: keepCellMask = np.copy(keepCellMaskNew) searchCells = np.where(keepCellMask==0)[0] varValueOld = np.copy(varValue) for iCell in searchCells: neighborcellID = cellsOnCell[iCell,:nEdgesOnCell[iCell]]-1 neighborcellID = neighborcellID[neighborcellID>=0] # Important: ignore the phantom "neighbors" that are off the edge of the mesh (0 values in cellsOnCell) mask_for_idx = keepCellMask[neighborcellID] # active cell mask mask_nonzero_idx, = np.nonzero(mask_for_idx) nonzero_id = neighborcellID[mask_nonzero_idx] # id for nonzero beta cells nonzero_num = np.count_nonzero(mask_for_idx) assert len(nonzero_id) == nonzero_num if nonzero_num > 0: x_i = xCell[iCell] y_i = yCell[iCell] x_adj = xCell[nonzero_id] y_adj = yCell[nonzero_id] var_adj = varValueOld[nonzero_id] if extrap_method == 'idw': ds = np.sqrt((x_i-x_adj)**2+(y_i-y_adj)**2) assert np.count_nonzero(ds)==len(ds) var_interp = 1.0/sum(1.0/ds)*sum(1.0/ds*var_adj) varValue[iCell] = var_interp elif extrap_method == 'min': varValue[iCell] = np.min(var_adj) else: sys.exit("ERROR: invalid extrapolation scheme! Set option m as idw or min!") keepCellMaskNew[iCell] = 1 # print ("{0:8d} cells left for extrapolation in total {1:8d} cells".format(nCells-np.count_nonzero(keepCellMask), nCells)) dataset.variables[var_name][0,:] = varValue # Put updated array back into file. # === Clean-up ============= # Update history attribute of netCDF file #thiscommand = datetime.now().strftime("%a %b %d %H:%M:%S %Y") + ": " + " ".join(sys.argv[:]) #thiscommand = thiscommand+"; {} successfully extrapolated using the {} method".format(var_name, extrap_method) #if hasattr(dataset, 'history'): # newhist = '\n'.join([thiscommand, getattr(dataset, 'history')]) #else: # newhist = thiscommand #setattr(dataset, 'history', newhist) dataset.close()