from netCDF4 import Dataset
import numpy as np
import math
from mpas_tools.cime.constants import constants
[docs]
def extend_seaice_mask(filenameMesh, filenamePresence, extendDistance,
                       unitSphere=False):
    """
    Add a field ``icePresenceExtended`` to ``filenamePresence`` if it doesn't
    already exist.  This field is the ``icePresence`` field extended by
    a distance of ``extendDistance``.
    Parameters
    ----------
    filenameMesh : str
        The filename of the MPAS-Seaice mesh
    filenamePresence : str
        A filename for a file containing an ``icePresence`` field to be
        extended and to which a new ``icePresenceExtended`` will be added
    extendDistance : float
        The distance in km to expand (no expansion is performed if
        ``extendDistance=0.0``)
    unitSphere : bool, optional
        Whether the mesh is provided on the unit sphere, rather than one with
        the radius of the Earth
    """
    # mesh
    print("Load mesh...")
    fileMesh = Dataset(filenameMesh, "r")
    nCells = len(fileMesh.dimensions["nCells"])
    nEdgesOnCell = fileMesh.variables["nEdgesOnCell"][:]
    cellsOnCell = fileMesh.variables["cellsOnCell"][:]
    cellsOnCell[:] = cellsOnCell[:] - 1
    xCell = fileMesh.variables["xCell"][:]
    yCell = fileMesh.variables["yCell"][:]
    zCell = fileMesh.variables["zCell"][:]
    fileMesh.close()
    # presence
    print("Load ice presence...")
    filePresence = Dataset(filenamePresence, "r")
    if "icePresenceExtended" in filePresence.variables:
        # we're already done, probably from a previous call
        filePresence.close()
        return
    icePresence = filePresence.variables["icePresence"][:]
    filePresence.close()
    # ice edge cells
    print("Get ice edge cells...")
    iceEdgeCell = np.zeros(nCells, dtype="i")
    for iCell in range(0, nCells):
        # if (iCell % 100000 == 0):
        #    print(iCell, " of ", nCells, " cells...")
        for iCellOnCell in range(0, nEdgesOnCell[iCell]):
            iCell2 = cellsOnCell[iCell, iCellOnCell]
            if icePresence[iCell] == 1 and icePresence[iCell2] == 0:
                iceEdgeCell[iCell] = 1
    # only edge cells
    nEdgeCells = np.sum(iceEdgeCell)
    print("nEdgeCells: ", nEdgeCells)
    print("Get edge cell vector...")
    iCellEdge = np.zeros(nEdgeCells, dtype="i")
    iEdgeCell = 0
    for iCell in range(0, nCells):
        if iceEdgeCell[iCell] == 1:
            iCellEdge[iEdgeCell] = iCell
            iEdgeCell = iEdgeCell + 1
    del iceEdgeCell
    # get edge positions
    print("Get edge positions...")
    xCellEdgeCell = np.zeros(nEdgeCells)
    yCellEdgeCell = np.zeros(nEdgeCells)
    zCellEdgeCell = np.zeros(nEdgeCells)
    for iEdgeCell in range(0, nEdgeCells):
        iCell = iCellEdge[iEdgeCell]
        xCellEdgeCell[iEdgeCell] = xCell[iCell]
        yCellEdgeCell[iEdgeCell] = yCell[iCell]
        zCellEdgeCell[iEdgeCell] = zCell[iCell]
    # find extended mask
    print("Find new extended mask...")
    extendDistance = extendDistance * 1000.0  # convert from km to m
    if unitSphere:
        earthRadius = constants['SHR_CONST_REARTH']
        extendDistance = extendDistance / earthRadius
    distanceLimit = math.pow(extendDistance, 2)
    icePresenceNew = icePresence.copy()
    if extendDistance > 0.0:
        distances = np.zeros(nEdgeCells)
        for iCell in range(0, nCells):
            if iCell % 100000 == 0:
                print(iCell, " of ", nCells, " cells...")
            distances = np.multiply(
                (xCell[iCell] - xCellEdgeCell),
                (xCell[iCell] - xCellEdgeCell)) + np.multiply(
                (yCell[iCell] - yCellEdgeCell),
                (yCell[iCell] - yCellEdgeCell)) + np.multiply(
                (zCell[iCell] - zCellEdgeCell),
                (zCell[iCell] - zCellEdgeCell))
            if distances[distances.argmin()] <= distanceLimit:
                icePresenceNew[iCell] = 1
    print("Load ice presence...")
    filePresence = Dataset(filenamePresence, "a")
    icePresenceVar = filePresence.createVariable(
        "icePresenceExtended", "d", dimensions=["nCells"])
    icePresenceVar[:] = icePresenceNew[:]
    filePresence.close()