def run(self):
        """
        Run this step of the testcase
        """
        with xarray.open_dataset('restart.nc') as ds:
            mesh_short_name = ds.attrs['MPAS_Mesh_Short_Name']
            mesh_prefix = ds.attrs['MPAS_Mesh_Prefix']
            prefix = 'MPAS_Mesh_{}'.format(mesh_prefix)
            creation_date = ds.attrs['{}_Version_Creation_Date'.format(prefix)]

        try:
            os.makedirs('../assembled_files/inputdata/ocn/mpas-o/{}'.format(
                mesh_short_name))
        except OSError:
            pass

        source_filename = 'restart.nc'
        dest_filename = 'mpaso.{}.{}.nc'.format(mesh_short_name, creation_date)

        with xarray.open_dataset(source_filename) as ds:
            ds.load()
            ds = ds.drop_vars('xtime')
            write_netcdf(ds, dest_filename)

        symlink(
            '../../../../../ocean_initial_condition/{}'.format(dest_filename),
            '../assembled_files/inputdata/ocn/mpas-o/{}/{}'.format(
                mesh_short_name, dest_filename))
Exemple #2
0
    def run(self):
        """
        Run this step of the test case
        """
        config = self.config
        logger = self.logger

        section = config['gotm']
        nx = section.getint('nx')
        ny = section.getint('ny')
        dc = section.getfloat('dc')

        dsMesh = make_planar_hex_mesh(nx=nx, ny=ny, dc=dc, nonperiodic_x=False,
                                      nonperiodic_y=False)
        write_netcdf(dsMesh, 'grid.nc')

        dsMesh = cull(dsMesh, logger=logger)
        dsMesh = convert(dsMesh, graphInfoFileName='graph.info',
                         logger=logger)
        write_netcdf(dsMesh, 'mesh.nc')

        replacements = dict()
        replacements['config_periodic_planar_vert_levels'] = \
            config.get('gotm', 'vert_levels')
        replacements['config_periodic_planar_bottom_depth'] = \
            config.get('gotm', 'bottom_depth')
        self.update_namelist_at_runtime(options=replacements)

        run_model(self)
Exemple #3
0
def _compute_barotropic_streamfunction(dsMesh, ds, out_dir, show_progress):
    """
    compute the barotropic streamfunction for the given mesh and monthly-mean
    data set
    """

    bsfFileName = '{}/barotropicStreamfunction.nc'.format(out_dir)
    if file_complete(ds, bsfFileName):
        return

    bsfVertex = _compute_barotropic_streamfunction_vertex(
        dsMesh, ds, show_progress)
    bsfCell = _compute_barotropic_streamfunction_cell(dsMesh, bsfVertex)
    dsBSF = xarray.Dataset()
    dsBSF['xtime_startMonthly'] = ds.xtime_startMonthly
    dsBSF['xtime_endMonthly'] = ds.xtime_endMonthly
    dsBSF['bsfVertex'] = bsfVertex
    dsBSF.bsfVertex.attrs['units'] = 'Sv'
    dsBSF.bsfVertex.attrs['description'] = 'barotropic streamfunction ' \
        'on vertices'
    dsBSF['bsfCell'] = bsfCell
    dsBSF.bsfCell.attrs['units'] = 'Sv'
    dsBSF.bsfCell.attrs['description'] = 'barotropic streamfunction ' \
        'on cells'
    dsBSF = dsBSF.transpose('Time', 'nCells', 'nVertices')
    write_netcdf(dsBSF, bsfFileName)
Exemple #4
0
def entry_point_compute_mpas_flood_fill_mask():
    """ Entry point for ``compute_mpas_flood_fill_mask()``"""

    parser = argparse.ArgumentParser()
    parser.add_argument("-m", "--mesh_file_name", dest="mesh_file_name",
                        type=str, required=True,
                        help="An MPAS mesh file")
    parser.add_argument("-g", "--geojson_file_name",
                        dest="geojson_file_name", type=str, required=True,
                        help="An Geojson file containing points at which to "
                             "start the flood fill")
    parser.add_argument("-o", "--mask_file_name", dest="mask_file_name",
                        type=str, required=True,
                        help="An output MPAS region masks file")
    parser.add_argument("--format", dest="format", type=str,
                        help="NetCDF file format")
    parser.add_argument("--engine", dest="engine", type=str,
                        help="NetCDF output engine")
    args = parser.parse_args()

    dsMesh = xr.open_dataset(args.mesh_file_name, decode_cf=False,
                             decode_times=False)
    fcSeed = read_feature_collection(args.geojson_file_name)

    with LoggingContext('compute_mpas_flood_fill_mask') as logger:
        dsMasks = compute_mpas_flood_fill_mask(
            dsMesh=dsMesh, fcSeed=fcSeed, logger=logger)

    write_netcdf(dsMasks, args.mask_file_name, format=args.format,
                 engine=args.engine)
Exemple #5
0
    def run(self):
        """
        Run this step of the test case
       """
        logger = self.logger
        section = self.config['enthalpy_benchmark']
        nx = section.getint('nx')
        ny = section.getint('ny')
        dc = section.getfloat('dc')
        levels = section.get('levels')

        dsMesh = make_planar_hex_mesh(nx=nx, ny=ny, dc=dc, nonperiodic_x=True,
                                      nonperiodic_y=True)

        write_netcdf(dsMesh, 'grid.nc')

        dsMesh = cull(dsMesh, logger=logger)
        dsMesh = convert(dsMesh, logger=logger)
        write_netcdf(dsMesh, 'mpas_grid.nc')

        args = ['create_landice_grid_from_generic_MPAS_grid.py',
                '-i', 'mpas_grid.nc',
                '-o', 'landice_grid.nc',
                '-l', levels,
                '--thermal']

        check_call(args, logger)

        make_graph_file(mesh_filename='landice_grid.nc',
                        graph_filename='graph.info')

        _setup_initial_conditions(section, 'landice_grid.nc')
Exemple #6
0
def make_moc_basins_and_transects(gf, mesh_filename,
                                  mask_and_transect_filename,
                                  geojson_filename=None,
                                  mask_filename=None,
                                  logger=None,
                                  dir=None):
    """
    Builds features defining the ocean basins and southern transects used in
    computing the meridional overturning circulation (MOC)

    Parameters
    ----------
    gf : geometric_features.GeometricFeatures
        An object that knows how to download and read geometric features

    mesh_filename : str
        A file with MPAS mesh information

    mask_and_transect_filename : str
        A file to write the MOC region masks and southern-boundary transects to

    geojson_filename : str, optional
        A file to write MOC regions to

    mask_filename : str, optional
        A file to write MOC region masks to

    logger : ``logging.Logger``, optional
        A logger for the output if not stdout

    dir : str, optional
        A directory in which a temporary directory will be added with files
        produced during conversion and then deleted upon completion.

    Returns
    -------
    fc : geometric_features.FeatureCollection
        The new feature collection
    """
    # Authors
    # -------
    # Xylar Asay-Davis

    fcMOC = moc(gf)

    if geojson_filename is not None:
        fcMOC.to_geojson(geojson_filename)

    dsMesh = xarray.open_dataset(mesh_filename)
    dsMasks = mpas_tools.mesh.conversion.mask(dsMesh=dsMesh, fcMask=fcMOC,
                                              logger=logger, dir=dir)

    if mask_filename is not None:
        write_netcdf(dsMasks, mask_filename, char_dim_name='StrLen')

    dsMasksAndTransects = add_moc_southern_boundary_transects(dsMasks, dsMesh,
                                                              logger=logger)
    write_netcdf(dsMasksAndTransects, mask_and_transect_filename,
                 char_dim_name='StrLen')
Exemple #7
0
def add_depth(inFileName, outFileName, coordFileName=None):
    """
    Add a 1D depth coordinate to an MPAS-Ocean file.

    Parameters
    ----------
    inFileName : str
        An input MPAS-Ocean file that depth should be added to, used for coords
        if another file is not provided via ``coordFileName``.

    outFileName : str
        An output MPAS-Ocean file with depth added

    coordFileName : str, optional
        An MPAS-Ocean file with ``refBottomDepth``
    """

    if coordFileName is None:
        coordFileName = inFileName

    ds = xarray.open_dataset(inFileName, mask_and_scale=False)
    if 'nVertLevels' in ds.dims:
        ds = ds.rename({'nVertLevels': 'depth'})

        dsCoord = xarray.open_dataset(coordFileName, mask_and_scale=False)
        dsCoord = dsCoord.rename({'nVertLevels': 'depth'})

        depth, depth_bnds = compute_depth(dsCoord.refBottomDepth)
        ds.coords['depth'] = ('depth', depth)
        ds.depth.attrs['long_name'] = 'reference depth of the center of ' \
                                      'each vertical level'
        ds.depth.attrs['standard_name'] = 'depth'
        ds.depth.attrs['units'] = 'meters'
        ds.depth.attrs['axis'] = 'Z'
        ds.depth.attrs['positive'] = 'down'
        ds.depth.attrs['valid_min'] = depth_bnds[0, 0]
        ds.depth.attrs['valid_max'] = depth_bnds[-1, 1]
        ds.depth.attrs['bounds'] = 'depth_bnds'

        ds.coords['depth_bnds'] = (('depth', 'nbnd'), depth_bnds)
        ds.depth_bnds.attrs['long_name'] = 'Gridcell depth interfaces'

        for varName in ds.data_vars:
            var = ds[varName]
            if 'depth' in var.dims:
                var = var.assign_coords(depth=ds.depth)
                ds[varName] = var

    time = datetime.now().strftime('%c')

    history = '{}: {}'.format(time, ' '.join(sys.argv))

    if 'history' in ds.attrs:
        ds.attrs['history'] = '{}\n{}'.format(history, ds.attrs['history'])
    else:
        ds.attrs['history'] = history

    write_netcdf(ds, outFileName)
Exemple #8
0
def write_time_varying_zmid(inFileName,
                            outFileName,
                            coordFileName=None,
                            prefix=''):
    """
    Add a 3D, time-independent depth coordinate to an MPAS-Ocean file.

    Parameters
    ----------
    inFileName : str
        An input MPAS-Ocean file with some form of ``layerThickness``, and also
        ``bottomDepth`` and ``maxLevelCell`` if no ``coordFileName``
        is provided.

    outFileName : str
        An output MPAS-Ocean file with ``zMid`` for each time in the input file

    coordFileName : str, optional
        An MPAS-Ocean file with ``bottomDepth`` and ``maxLevelCell``

    prefix : str, optional
        A prefix on ``layerThickness`` (in) and ``zMid`` (out), such as
        ``timeMonthly_avg_``
    """
    if coordFileName is None:
        coordFileName = inFileName

    dsCoord = xarray.open_dataset(coordFileName)
    dsCoord = dsCoord.rename({'nVertLevels': 'depth'})

    dsIn = xarray.open_dataset(inFileName)
    dsIn = dsIn.rename({'nVertLevels': 'depth'})
    inVarName = '{}layerThickness'.format(prefix)
    outVarName = '{}zMid'.format(prefix)
    layerThickness = dsIn[inVarName]

    zMid = compute_zmid(dsCoord.bottomDepth,
                        dsCoord.maxLevelCell,
                        layerThickness,
                        depth_dim='depth')

    dsOut = xarray.Dataset()
    dsOut[outVarName] = zMid
    fillValue = netCDF4.default_fillvals['f8']
    dsOut[outVarName] = dsOut[outVarName].where(dsOut[outVarName].notnull(),
                                                other=fillValue)
    dsOut[outVarName].attrs['units'] = 'meters'
    dsOut[outVarName].attrs['positive'] = 'up'
    dsOut[outVarName].attrs['_FillValue'] = fillValue

    time = datetime.now().strftime('%c')

    history = '{}: {}'.format(time, ' '.join(sys.argv))
    dsOut.attrs['history'] = history

    write_netcdf(dsOut, outFileName)
Exemple #9
0
def add_zmid(inFileName, outFileName, coordFileName=None):
    """
    Add a 3D, time-independent depth coordinate to an MPAS-Ocean file.

    Parameters
    ----------
    inFileName : str
        An input MPAS-Ocean file that ``zMid`` should be added to, used for
        coords if another file is not provided via ``coordFileName``.

    outFileName : str
        An output MPAS-Ocean file with ``zMid`` added

    coordFileName : str, optional
        An MPAS-Ocean file with ``bottomDepth``, ``maxLevelCell`` and
        ``layerThickness`` but not ``zMid``
    """
    if coordFileName is None:
        coordFileName = inFileName

    ds = xarray.open_dataset(inFileName, mask_and_scale=False)
    if 'nVertLevels' in ds.dims:
        ds = ds.rename({'nVertLevels': 'depth'})

        # dsCoord doesn't have masking disabled because we want it for zMid
        dsCoord = xarray.open_dataset(coordFileName)
        dsCoord = dsCoord.rename({'nVertLevels': 'depth'})
        if 'Time' in dsCoord.dims:
            dsCoord = dsCoord.isel(Time=0)

        ds.coords['zMid'] = compute_zmid(dsCoord.bottomDepth,
                                         dsCoord.maxLevelCell,
                                         dsCoord.layerThickness,
                                         depth_dim='depth')
        fillValue = netCDF4.default_fillvals['f8']
        ds.coords['zMid'] = ds.zMid.where(ds.zMid.notnull(), other=fillValue)
        ds.zMid.attrs['units'] = 'meters'
        ds.zMid.attrs['positive'] = 'up'
        ds.zMid.attrs['_FillValue'] = fillValue

        for varName in ds.data_vars:
            var = ds[varName]
            if 'nCells' in var.dims and 'depth' in var.dims:
                var = var.assign_coords(zMid=ds.zMid)
                ds[varName] = var

    time = datetime.now().strftime('%c')

    history = '{}: {}'.format(time, ' '.join(sys.argv))

    if 'history' in ds.attrs:
        ds.attrs['history'] = '{}\n{}'.format(history, ds.attrs['history'])
    else:
        ds.attrs['history'] = history

    write_netcdf(ds, outFileName)
Exemple #10
0
def _make_moc_masks(mesh_short_name, logger, cores):
    gf = GeometricFeatures()

    mesh_filename = 'restart.nc'

    function, prefix, date = get_aggregator_by_name('MOC Basins')
    fcMask = function(gf)

    suffix = '{}{}'.format(prefix, date)

    geojson_filename = '{}.geojson'.format(suffix)
    mask_filename = '{}_{}.nc'.format(mesh_short_name, suffix)

    fcMask.to_geojson(geojson_filename)

    # these defaults may have been updated from config options -- pass them
    # along to the subprocess
    netcdf_format = mpas_tools.io.default_format
    netcdf_engine = mpas_tools.io.default_engine

    args = ['compute_mpas_region_masks',
            '-m', mesh_filename,
            '-g', geojson_filename,
            '-o', mask_filename,
            '-t', 'cell',
            '--process_count', '{}'.format(cores),
            '--format', netcdf_format,
            '--engine', netcdf_engine]
    check_call(args, logger=logger)

    mask_and_transect_filename = '{}_mocBasinsAndTransects{}.nc'.format(
        mesh_short_name, date)

    dsMesh = xarray.open_dataset(mesh_filename)
    dsMask = xarray.open_dataset(mask_filename)

    dsMasksAndTransects = add_moc_southern_boundary_transects(
        dsMask, dsMesh, logger=logger)

    write_netcdf(dsMasksAndTransects, mask_and_transect_filename,
                 char_dim_name='StrLen')

    # make links in output directories (both inputdata and diagnostics)
    output_dir = '../assembled_files/inputdata/ocn/mpas-o/{}'.format(
        mesh_short_name)
    symlink(
        '../../../../../diagnostics_files/{}'.format(
            mask_and_transect_filename),
        '{}/{}'.format(output_dir, mask_and_transect_filename))

    output_dir = '../assembled_files/diagnostics/mpas_analysis/' \
                 'region_masks'
    symlink(
        '../../../../diagnostics_files/{}'.format(
            mask_and_transect_filename),
        '{}/{}'.format(output_dir, mask_and_transect_filename))
Exemple #11
0
def make_moc_basins_and_transects(gf,
                                  mesh_filename,
                                  mask_and_transect_filename,
                                  geojson_filename=None,
                                  mask_filename=None,
                                  logger=None):
    """
    Builds features defining the ocean basins and southern transects used in
    computing the meridional overturning circulation (MOC)
    Parameters
    ----------
    gf : ``GeometricFeatures``
        An object that knows how to download and read geometric featuers

    mesh_filename : str
        A file with MPAS mesh information

    mask_and_transect_filename : str
        A file to write the MOC region masks and southern-boundary transects to

    geojson_filename : str, optional
        A file to write MOC regions to

    mask_filename : str, optional
        A file to write MOC region masks to

    logger : ``logging.Logger``, optional
        A logger for the output if not stdout

    Returns
    -------
    fc : ``FeatureCollection``
        The new feature collection
    """
    # Authors
    # -------
    # Xylar Asay-Davis

    fcMOC = build_moc_basins(gf, logger)

    if geojson_filename is not None:
        fcMOC.to_geojson(geojson_filename)

    dsMesh = xarray.open_dataset(mesh_filename)
    dsMasks = mpas_tools.conversion.mask(dsMesh=dsMesh,
                                         fcMask=fcMOC,
                                         logger=logger)

    if mask_filename is not None:
        write_netcdf(dsMasks, mask_filename)

    dsMasksAndTransects = add_moc_southern_boundary_transects(dsMasks,
                                                              dsMesh,
                                                              logger=logger)
    write_netcdf(dsMasksAndTransects, mask_and_transect_filename)
Exemple #12
0
def convert(dsIn, graphInfoFileName=None, logger=None, dir=None):
    """
    Use ``MpasMeshConverter.x`` to convert an input mesh to a valid MPAS
    mesh that is fully compliant with the MPAS mesh specification.
    https://mpas-dev.github.io/files/documents/MPAS-MeshSpec.pdf

    Parameters
    ----------
    dsIn : xarray.Dataset
        A data set to convert

    graphInfoFileName : str, optional
        A file path (relative or absolute) where the graph file (typically
        ``graph.info`` should be written out.  By default, ``graph.info`` is
        not saved.

    logger : logging.Logger, optional
        A logger for the output if not stdout

    dir : str, optional
        A directory in which a temporary directory will be added with files
        produced during conversion and then deleted upon completion.

    Returns
    -------
    dsOut : xarray.Dataset
        The MPAS mesh
    """
    if dir is not None:
        dir = os.path.abspath(dir)
    with TemporaryDirectory(dir=dir) as tempdir:
        inFileName = '{}/mesh_in.nc'.format(tempdir)
        write_netcdf(dsIn, inFileName)

        outFileName = '{}/mesh_out.nc'.format(tempdir)

        if graphInfoFileName is not None:
            graphInfoFileName = os.path.abspath(graphInfoFileName)

        # go into the directory of the output file so the graph.info file ends
        # up in the same place
        owd = os.getcwd()
        outDir = os.path.dirname(outFileName)
        os.chdir(outDir)
        _call_subprocess(['MpasMeshConverter.x', inFileName, outFileName],
                         logger)
        os.chdir(owd)

        dsOut = xarray.open_dataset(outFileName)
        dsOut.load()

        if graphInfoFileName is not None:
            shutil.copyfile('{}/graph.info'.format(outDir), graphInfoFileName)

    return dsOut
Exemple #13
0
def mask(dsMesh, fcMask=None, fcSeed=None, logger=None, dir=None):
    """
    Use ``MpasMaskCreator.x`` to create a set of region masks either from
    mask feature collections or from seed points to be used to flood fill

    Parameters
    ----------
    dsMesh : xarray.Dataset, optional
        An MPAS mesh on which the masks should be created

    fcMask : geometric_features.FeatureCollection, optional
        A feature collection containing features to use to create the mask

    fcSeed : geometric_features.FeatureCollection, optional
        A feature collection with points to use a seeds for a flood fill that
        will create a mask of all cells connected to the seed points

    logger : logging.Logger, optional
        A logger for the output if not stdout

    dir : str, optional
        A directory in which a temporary directory will be added with files
        produced during mask creation and then deleted upon completion.

    Returns
    -------
    dsMask : xarray.Dataset
        The masks

    """
    if dir is not None:
        dir = os.path.abspath(dir)
    with TemporaryDirectory(dir=dir) as tempdir:
        inFileName = '{}/mesh_in.nc'.format(tempdir)
        write_netcdf(dsMesh, inFileName)
        outFileName = '{}/mesh_out.nc'.format(tempdir)

        args = ['MpasMaskCreator.x', inFileName, outFileName]

        if fcMask is not None:
            fileName = '{}/mask.geojson'.format(tempdir)
            fcMask.to_geojson(fileName)
            args.extend(['-f', fileName])

        if fcSeed is not None:
            fileName = '{}/seed.geojson'.format(tempdir)
            fcSeed.to_geojson(fileName)
            args.extend(['-s', fileName])

        _call_subprocess(args, logger)

        dsOut = xarray.open_dataset(outFileName)
        dsOut.load()

    return dsOut
Exemple #14
0
def mask(dsMesh, fcMask=None, fcSeed=None, positiveLon=False, logger=None):
    '''
    Use ``MpasMaskCreator.x`` to create a set of region masks either from
    mask feature collecitons or from seed points to be used to flood fill

    Parameters
    ----------
    dsMesh : ``xarray.Dataset``, optional
        An MPAS mesh on which the masks should be created

    fcMask : ``geometric_features.FeatureCollection``, optional
        A feature collection containing features to use to create the mask

    fcSeed : ``geometric_features.FeatureCollection``, optional
        A feature collection with points to use a seeds for a flood fill that
        will create a mask of all cells connected to the seed points

    logger : ``logging.Logger``, optional
        A logger for the output if not stdout

    Returns
    -------
    dsMask : ``xarray.Dataset``
        The masks

    '''

    with TemporaryDirectory() as tempdir:
        inFileName = '{}/mesh_in.nc'.format(tempdir)
        write_netcdf(dsMesh, inFileName)
        outFileName = '{}/mesh_out.nc'.format(tempdir)

        args = ['MpasMaskCreator.x', inFileName, outFileName]

        if fcMask is not None:
            fileName = '{}/mask.geojson'.format(tempdir)
            fcMask.to_geojson(fileName)
            args.extend(['-f', fileName])

        if fcSeed is not None:
            fileName = '{}/seed.geojson'.format(tempdir)
            fcSeed.to_geojson(fileName)
            args.extend(['-s', fileName])

        if positiveLon:
            args.append('--positive_lon')

        _call_subprocess(args, logger)

        dsOut = xarray.open_dataset(outFileName)
        dsOut.load()

    return dsOut
Exemple #15
0
def build_mesh(preserve_floodplain=False,
               floodplain_elevation=20.0,
               do_inject_bathymetry=False):

    print('Step 1. Build cellWidth array as function of latitude and '
          'longitude')
    cellWidth, lon, lat = define_base_mesh.cellWidthVsLatLon()
    da = xarray.DataArray(cellWidth,
                          dims=['lat', 'lon'],
                          coords={
                              'lat': lat,
                              'lon': lon
                          },
                          name='cellWidth')
    da.to_netcdf('cellWidthVsLatLon.nc')

    print('Step 2. Generate mesh with JIGSAW')
    jigsaw_driver(cellWidth, lon, lat)

    print('Step 3. Convert triangles from jigsaw format to netcdf')
    jigsaw_to_netcdf(msh_filename='mesh-MESH.msh',
                     output_name='mesh_triangles.nc',
                     on_sphere=True)

    print('Step 4. Convert from triangles to MPAS mesh')
    write_netcdf(convert(xarray.open_dataset('mesh_triangles.nc')),
                 'base_mesh.nc')

    print('Step 5. Inject correct meshDensity variable into base mesh file')
    inject_meshDensity(cw_filename='cellWidthVsLatLon.nc',
                       mesh_filename='base_mesh.nc')

    if do_inject_bathymetry:
        print('Step 6. Injecting bathymetry')
        inject_bathymetry(mesh_file='base_mesh.nc')

    if preserve_floodplain:
        print('Step 7. Injecting flag to preserve floodplain')
        inject_preserve_floodplain(mesh_file='base_mesh.nc',
                                   floodplain_elevation=floodplain_elevation)

    print('Step 8. Create vtk file for visualization')
    args = [
        'paraview_vtk_field_extractor.py', '--ignore_time', '-l', '-d',
        'maxEdges=0', '-v', 'allOnCells', '-f', 'base_mesh.nc', '-o',
        'base_mesh_vtk'
    ]
    print("running", ' '.join(args))
    subprocess.check_call(args, env=os.environ.copy())

    print("***********************************************")
    print("**    The global mesh file is base_mesh.nc   **")
    print("***********************************************")
Exemple #16
0
def main(args):

    earth_radius = 6371.0e3

    out_dir = os.path.abspath(args.output)
    out_base = os.path.basename(args.output)
    out_basepath = out_dir + "/" + out_base
    out_filename = out_dir + "/" + out_base + "_mpas.nc"
    p = bool(args.plots)
    print(p)
    if not os.path.exists(out_dir):
        os.makedirs(out_dir)
    else:
        print("Base dir already exists: ", out_dir)

    if (args.opt == "unif" or args.opt == "localref"):

        #Density based grid
        if (args.opt == "unif"):
            cellWidth, lon, lat = jutil.cellWidthVsLatLon(args.r)
        elif (args.opt == "localref"):
            cellWidth, lon, lat = jutil.localrefVsLatLon(args.r, p=p)

        mesh_file = jutil.jigsaw_gen_sph_grid(cellWidth,
                                              lon,
                                              lat,
                                              basename=out_basepath)

    elif (args.opt == "icos"):

        #Icosahedral grid
        mesh_file = jutil.jigsaw_gen_icos_grid(basename=out_basepath, level=4)

    else:
        print("Unknown option")
        exit(1)

    #Convert jigsaw mesh to netcdf
    jigsaw_to_netcdf(msh_filename=mesh_file,
                     output_name=out_basepath + '_triangles.nc',
                     on_sphere=True,
                     sphere_radius=1.0)

    #convert to mpas grid specific format
    write_netcdf(
        convert(xarray.open_dataset(out_basepath + '_triangles.nc'),
                dir=out_dir,
                graphInfoFileName=out_basepath + "_graph.info"), out_filename)
Exemple #17
0
def _vertical_cumsum_horizontal_transport(ds, outFileName):
    """
    compute the cumsum in the vertical of the horizontal transport
    """

    if file_complete(ds, outFileName):
        return

    chunks = {'Time': 1, 'nInternalEdges': 32768}
    ds = ds.chunk(chunks)

    nTime = ds.sizes['Time']
    nInternalEdges = ds.sizes['nInternalEdges']
    nz = ds.sizes['nz']

    transport = ds.transport.rename({'nzM1': 'nz'})

    transportSumTop = xarray.DataArray(numpy.zeros((nTime, nInternalEdges, 1)),
                                       dims=('Time', 'nInternalEdges',
                                             'nz')).chunk(chunks)

    # zeros on top and then the cumsum for the rest
    transportSum = xarray.concat(
        [transportSumTop, transport.cumsum(dim='nz')], dim='nz')

    # mask out locations on the output where no input-grid layers overlap
    # with either the output layer above or the one below
    mask = ds.mask.rename({'nzM1': 'nz'})
    maskTop = mask.isel(nz=0)
    maskBot = mask.isel(nz=nz - 2)

    outMask = xarray.concat(
        [maskTop,
         numpy.logical_or(mask[:, 0:-1, :], mask[:, 1:, :]), maskBot],
        dim='nz')

    dsOut = xarray.Dataset()
    dsOut['xtime_startMonthly'] = ds.xtime_startMonthly
    dsOut['xtime_endMonthly'] = ds.xtime_endMonthly
    dsOut['z'] = ds.z
    dsOut['transportSum'] = transportSum
    dsOut['mask'] = outMask

    dsOut = dsOut.transpose('Time', 'nz', 'nInternalEdges')

    print('compute and caching vertical transport sum on z-level grid:')
    write_netcdf(dsOut, outFileName)
    def run(self):
        """
        Run this step of the testcase
            """
        with_ice_shelf_cavities = self.with_ice_shelf_cavities

        with xarray.open_dataset('restart.nc') as ds:
            mesh_short_name = ds.attrs['MPAS_Mesh_Short_Name']
            mesh_prefix = ds.attrs['MPAS_Mesh_Prefix']
            prefix = 'MPAS_Mesh_{}'.format(mesh_prefix)
            creation_date = ds.attrs['{}_Version_Creation_Date'.format(prefix)]

        try:
            os.makedirs(
                '../assembled_files/inputdata/ocn/mpas-seaice/{}'.format(
                    mesh_short_name))
        except OSError:
            pass

        dest_filename = 'mpassi.{}.{}.nc'.format(mesh_short_name,
                                                 creation_date)

        keep_vars = [
            'areaCell', 'cellsOnCell', 'edgesOnCell', 'fCell', 'indexToCellID',
            'latCell', 'lonCell', 'meshDensity', 'nEdgesOnCell',
            'verticesOnCell', 'xCell', 'yCell', 'zCell', 'angleEdge',
            'cellsOnEdge', 'dcEdge', 'dvEdge', 'edgesOnEdge', 'fEdge',
            'indexToEdgeID', 'latEdge', 'lonEdge', 'nEdgesOnCell',
            'nEdgesOnEdge', 'verticesOnEdge', 'weightsOnEdge', 'xEdge',
            'yEdge', 'zEdge', 'areaTriangle', 'cellsOnVertex', 'edgesOnVertex',
            'fVertex', 'indexToVertexID', 'kiteAreasOnVertex', 'latVertex',
            'lonVertex', 'xVertex', 'yVertex', 'zVertex'
        ]

        if with_ice_shelf_cavities:
            keep_vars.append('landIceMask')

        with xarray.open_dataset('restart.nc') as ds:
            ds.load()
            ds = ds[keep_vars]
            write_netcdf(ds, dest_filename)

        symlink(
            '../../../../../seaice_initial_condition/{}'.format(dest_filename),
            '../assembled_files/inputdata/ocn/mpas-seaice/{}/{}'.format(
                mesh_short_name, dest_filename))
Exemple #19
0
def convert(dsIn, graphInfoFileName=None):
    '''
    Use ``MpasMeshConverter.x`` to convert an input mesh to a valid MPAS
    mesh that is fully compliant with the MPAS mesh specification.
    https://mpas-dev.github.io/files/documents/MPAS-MeshSpec.pdf

    Parameters
    ----------
    dsIn : ``xarray.Dataset``
        A data set to convert

    graphInfoFileName : str, optional
        A file path (relative or absolute) where the graph file (typically
        ``graph.info`` should be written out.  By default, ``graph.info`` is
        not saved.

    Returns
    -------
    dsOut : ``xarray.Dataset``
        The MPAS mesh
    '''

    with TemporaryDirectory() as tempdir:
        inFileName = '{}/mesh_in.nc'.format(tempdir)
        write_netcdf(dsIn, inFileName)

        outFileName = '{}/mesh_out.nc'.format(tempdir)

        if graphInfoFileName is not None:
            graphInfoFileName = os.path.abspath(graphInfoFileName)

        # go into the directory of the output file so the graph.info file ends
        # up in the same place
        owd = os.getcwd()
        outDir = os.path.dirname(outFileName)
        os.chdir(outDir)
        subprocess.check_call(['MpasMeshConverter.x', inFileName, outFileName])
        os.chdir(owd)

        dsOut = xarray.open_dataset(outFileName)
        dsOut.load()

        if graphInfoFileName is not None:
            shutil.copyfile('{}/graph.info'.format(outDir), graphInfoFileName)

    return dsOut
Exemple #20
0
    def run(self):
        """
        Run this step of the test case
       """
        logger = self.logger
        section = self.config['eismint2']

        nx = section.getint('nx')
        ny = section.getint('ny')
        dc = section.getfloat('dc')

        dsMesh = make_planar_hex_mesh(nx=nx,
                                      ny=ny,
                                      dc=dc,
                                      nonperiodic_x=False,
                                      nonperiodic_y=False)

        dsMesh = convert(dsMesh, logger=logger)
        write_netcdf(dsMesh, 'mpas_grid.nc')
        dsMesh.close()

        radius = section.get('radius')
        args = [
            'define_cullMask.py', '-f', 'mpas_grid.nc', '-m', 'radius', '-d',
            radius
        ]

        check_call(args, logger)

        dsMesh = xarray.open_dataset('mpas_grid.nc')
        dsMesh = cull(dsMesh, logger=logger)
        dsMesh = convert(dsMesh, logger=logger)
        write_netcdf(dsMesh, 'mpas_grid2.nc')

        levels = section.get('levels')
        args = [
            'create_landice_grid_from_generic_MPAS_grid.py', '-i',
            'mpas_grid2.nc', '-o', 'landice_grid.nc', '-l', levels,
            '--thermal', '--beta'
        ]

        check_call(args, logger)

        make_graph_file(mesh_filename='landice_grid.nc',
                        graph_filename='graph.info')
def make_region_masks(mesh_name, suffix, fcMask):  # {{{
    mesh_filename = '../mesh.nc'

    geojson_filename = '{}.geojson'.format(suffix)
    mask_filename = '{}_{}.nc'.format(mesh_name, suffix)

    fcMask.to_geojson(geojson_filename)

    dsMesh = xr.open_dataset(mesh_filename)

    dsMask = mpas_tools.conversion.mask(dsMesh, fcMask=fcMask)

    write_netcdf(dsMask, mask_filename)

    # make links in output directory
    output_dir = '../assembled_files_for_upload/diagnostics/mpas_analysis/' \
                 'region_masks'
    make_link('../../../../transects_and_regions/{}'.format(mask_filename),
              '{}/{}'.format(output_dir, mask_filename))
Exemple #22
0
    def _write_time_varying_forcing(self, ds_init):
        """
        Write time-varying land-ice forcing and update the initial condition
        """

        config = self.config
        dates = config.get('isomip_plus_forcing', 'dates')
        dates = [date.ljust(64) for date in dates.replace(',', ' ').split()]
        scales = config.get('isomip_plus_forcing', 'scales')
        scales = [float(scale) for scale in scales.replace(',', ' ').split()]

        ds_out = xarray.Dataset()
        ds_out['xtime'] = ('Time', dates)
        ds_out['xtime'] = ds_out.xtime.astype('S')

        landIceDraft = list()
        landIcePressure = list()
        landIceFraction = list()

        for scale in scales:
            landIceDraft.append(scale * ds_init.landIceDraft)
            landIcePressure.append(scale * ds_init.landIcePressure)
            landIceFraction.append(ds_init.landIceFraction)

        ds_out['landIceDraftForcing'] = xarray.concat(landIceDraft, 'Time')
        ds_out.landIceDraftForcing.attrs['units'] = 'm'
        ds_out.landIceDraftForcing.attrs['long_name'] = \
            'The approximate elevation of the land ice-ocean interface'
        ds_out['landIcePressureForcing'] = \
            xarray.concat(landIcePressure, 'Time')
        ds_out.landIcePressureForcing.attrs['units'] = 'm'
        ds_out.landIcePressureForcing.attrs['long_name'] = \
            'Pressure from the weight of land ice at the ice-ocean interface'
        ds_out['landIceFractionForcing'] = \
            xarray.concat(landIceFraction, 'Time')
        ds_out.landIceFractionForcing.attrs['units'] = 'unitless'
        ds_out.landIceFractionForcing.attrs['long_name'] = \
            'The fraction of each cell covered by land ice'
        write_netcdf(ds_out, 'land_ice_forcing.nc')

        ds_init['landIceDraft'] = scales[0] * ds_init.landIceDraft
        ds_init['ssh'] = ds_init.landIceDraft
        ds_init['landIcePressure'] = scales[0] * ds_init.landIcePressure
Exemple #23
0
    def run(self):
        """
        Run this step of the test case
        """

        config = self.config
        section = config['soma']
        options = dict(
            config_eos_linear_alpha=section.get('eos_linear_alpha'),
            config_soma_density_difference=section.get('density_difference'),
            config_soma_surface_temperature=section.get('surface_temperature'),
            config_soma_surface_salinity=section.get('surface_salinity'),
            config_soma_salinity_gradient=section.get('salinity_gradient'),
            config_soma_thermocline_depth=section.get('thermocline_depth'),
            config_soma_density_difference_linear=section.get(
                'density_difference_linear'),
            config_soma_phi=section.get('phi'),
            config_soma_shelf_depth=section.get('shelf_depth'),
            config_soma_bottom_depth=section.get('bottom_depth'))

        for out_name in ['namelist_mark_land.ocean', 'namelist.ocean']:
            self.update_namelist_at_runtime(options=options, out_name=out_name)
        ds_mesh = convert(xarray.open_dataset('base_mesh.nc'),
                          graphInfoFileName='base_graph.info',
                          logger=self.logger)
        write_netcdf(ds_mesh, 'mesh.nc')

        run_model(self,
                  namelist='namelist_mark_land.ocean',
                  streams='streams_mark_land.ocean',
                  graph_file='base_graph.info')

        ds_mesh = cull(xarray.open_dataset('masked_initial_state.nc'),
                       graphInfoFileName='graph.info',
                       logger=self.logger)
        write_netcdf(ds_mesh, 'culled_mesh.nc')

        run_model(self,
                  namelist='namelist.ocean',
                  streams='streams.ocean',
                  graph_file='graph.info')
Exemple #24
0
    def run(self):
        """
        Run this step of the test case
       """
        mesh_type = self.mesh_type
        logger = self.logger
        config = self.config
        section = config['dome']

        if mesh_type == '2000m':
            nx = section.getint('nx')
            ny = section.getint('ny')
            dc = section.getfloat('dc')

            dsMesh = make_planar_hex_mesh(nx=nx,
                                          ny=ny,
                                          dc=dc,
                                          nonperiodic_x=True,
                                          nonperiodic_y=True)

            write_netcdf(dsMesh, 'grid.nc')

            dsMesh = cull(dsMesh, logger=logger)
            dsMesh = convert(dsMesh, logger=logger)
            write_netcdf(dsMesh, 'mpas_grid.nc')

        levels = section.get('levels')
        args = [
            'create_landice_grid_from_generic_MPAS_grid.py', '-i',
            'mpas_grid.nc', '-o', 'landice_grid.nc', '-l', levels
        ]

        check_call(args, logger)

        make_graph_file(mesh_filename='landice_grid.nc',
                        graph_filename='graph.info')

        _setup_dome_initial_conditions(config,
                                       logger,
                                       filename='landice_grid.nc')
Exemple #25
0
def _compute_and_write_haney_number(dsMesh, ds, folder, showProgress=False):
    """
    compute the Haney number rx1 for each edge, and interpolate it to cells.
    """

    haneyFileName = '{}/haney.nc'.format(folder)
    if file_complete(ds, haneyFileName):
        return

    haneyEdge, haneyCell = compute_haney_number(
        dsMesh, ds.timeMonthly_avg_layerThickness, ds.timeMonthly_avg_ssh,
        showProgress)
    dsHaney = xarray.Dataset()
    dsHaney['xtime_startMonthly'] = ds.xtime_startMonthly
    dsHaney['xtime_endMonthly'] = ds.xtime_endMonthly
    dsHaney['haneyEdge'] = haneyEdge
    dsHaney.haneyEdge.attrs['units'] = 'unitless'
    dsHaney.haneyEdge.attrs['description'] = 'Haney number on edges'
    dsHaney['haneyCell'] = haneyCell
    dsHaney.haneyCell.attrs['units'] = 'unitless'
    dsHaney.haneyCell.attrs['description'] = 'Haney number on cells'
    dsHaney = dsHaney.transpose('Time', 'nCells', 'nEdges', 'nVertLevels')
    write_netcdf(dsHaney, haneyFileName)
Exemple #26
0
    def run(self):
        """
        Run this step of the test case
        """
        config = self.config
        resolution = float(self.resolution)

        section = config['planar_convergence']
        nx_1km = section.getint('nx_1km')
        ny_1km = section.getint('ny_1km')
        nx = int(nx_1km / resolution)
        ny = int(ny_1km / resolution)
        dc = resolution * 1e3

        ds_mesh = make_planar_hex_mesh(nx=nx,
                                       ny=ny,
                                       dc=dc,
                                       nonperiodic_x=False,
                                       nonperiodic_y=False)

        center(ds_mesh)

        write_netcdf(ds_mesh, 'mesh.nc')
        make_graph_file('mesh.nc', 'graph.info')
Exemple #27
0
def make_diff(mesh, refMeshFileName, diffFileName):

    refMesh = xarray.open_dataset(refMeshFileName)
    diff = xarray.Dataset()
    for variable in mesh.data_vars:
        if variable in refMesh:
            diff[variable] = mesh[variable] - refMesh[variable]
            print(diff[variable].name, float(numpy.abs(diff[variable]).max()))
        else:
            print('mesh has extra variable {}'.format(mesh[variable].name))

    for variable in refMesh.data_vars:
        if variable not in mesh:
            print('mesh mising variable {}'.format(refMesh[variable].name))

    for attr in refMesh.attrs:
        if attr not in mesh.attrs:
            print('mesh mising attribute {}'.format(attr))

    for attr in mesh.attrs:
        if attr not in refMesh.attrs:
            print('mesh has extra attribute {}'.format(attr))

    write_netcdf(diff, diffFileName)
Exemple #28
0
    def run(self):
        """
        Run this step of the test case
        """
        config = self.config
        logger = self.logger

        section = config['ziso']
        nx = section.getint('nx')
        ny = section.getint('ny')
        dc = section.getfloat('dc')

        dsMesh = make_planar_hex_mesh(nx=nx, ny=ny, dc=dc, nonperiodic_x=False,
                                      nonperiodic_y=True)
        write_netcdf(dsMesh, 'base_mesh.nc')

        dsMesh = cull(dsMesh, logger=logger)
        dsMesh = convert(dsMesh, graphInfoFileName='culled_graph.info',
                         logger=logger)
        write_netcdf(dsMesh, 'culled_mesh.nc')

        ds = _write_initial_state(config, dsMesh, self.with_frazil)

        _write_forcing(config, ds.yCell, ds.zMid)
Exemple #29
0
def test_conversion():
    dsMesh = xarray.open_dataset(
        'mesh_tools/mesh_conversion_tools/test/mesh.QU.1920km.151026.nc')
    dsMesh = convert(dsIn=dsMesh)
    write_netcdf(dsMesh, 'mesh.nc')

    dsMask = xarray.open_dataset(
        'mesh_tools/mesh_conversion_tools/test/land_mask_final.nc')
    dsCulled = cull(dsIn=dsMesh, dsMask=dsMask)
    write_netcdf(dsCulled, 'culled_mesh.nc')

    fcMask = read_feature_collection(
        'mesh_tools/mesh_conversion_tools/test/Arctic_Ocean.geojson')
    dsMask = mask(dsMesh=dsMesh, fcMask=fcMask)
    write_netcdf(dsMask, 'antarctic_mask.nc')
def remap_rignot(inFileName,
                 meshFileName,
                 meshName,
                 outFileName,
                 mappingDirectory='.',
                 method='conserve',
                 renormalizationThreshold=None,
                 inVarName='melt_actual',
                 mpiTasks=1):
    # {{{
    """
    Remap the Rignot et al. (2013) melt rates at 1 km resolution to an MPAS
    mesh

    Parameters
    ----------
    inFileName : str
        The original Rignot et al. (2013) melt rates

    meshFileName : str
        The MPAS mesh

    meshName : str
        The name of the mesh (e.g. oEC60to30wISC), used in the name of the
        mapping file

    outFileName : str
        The melt rates interpolated to the MPAS mesh with ocean sensible heat
        fluxes added on (assuming insulating ice)

    mappingDirectory : str
        The directory where the mapping file should be stored (if it is to be
        computed) or where it already exists (if not)

    method : {'bilinear', 'neareststod', 'conserve'}, optional
        The method of interpolation used, see documentation for
        `ESMF_RegridWeightGen` for details.

    renormalizationThreshold : float, optional
        The minimum weight of a denstination cell after remapping, below
        which it is masked out, or ``None`` for no renormalization and
        masking.

    inVarName : {'melt_actual', 'melt_steadystate'}
        Whether to use the melt rate for the time period covered in Rignot et
        al. (2013) with observed thinning/thickening or the melt rates that
        would be required if ice shelves were in steady state.

    mpiTasks : int, optional
        The number of MPI tasks to use to compute the mapping file
    """

    ds = xr.open_dataset(inFileName)
    lx = np.abs(1e-3 * (ds.xaxis.values[-1] - ds.xaxis.values[0]))
    ly = np.abs(1e-3 * (ds.yaxis.values[-1] - ds.yaxis.values[0]))

    inGridName = '{}x{}km_1.0km_Antarctic_stereo'.format(lx, ly)

    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')

    inDescriptor = ProjectionGridDescriptor.read(projection,
                                                 inFileName,
                                                 xVarName='xaxis',
                                                 yVarName='yaxis',
                                                 meshName=inGridName)

    # convert to the units and variable names expected in MPAS-O
    rho_fw = 1000.
    s_per_yr = 365. * 24. * 60. * 60.
    latent_heat_of_fusion = 3.337e5
    ds['prescribedLandIceFreshwaterFlux'] = ds[inVarName] * rho_fw / s_per_yr
    ds['prescribedLandIceHeatFlux'] = (latent_heat_of_fusion *
                                       ds['prescribedLandIceFreshwaterFlux'])
    ds = ds.drop_vars(['melt_actual', 'melt_steadystate', 'lon', 'lat'])

    outDescriptor = MpasMeshDescriptor(meshFileName, meshName)

    mappingFileName = '{}/map_{}_to_{}.nc'.format(mappingDirectory, inGridName,
                                                  meshName)

    remapper = Remapper(inDescriptor, outDescriptor, mappingFileName)

    remapper.build_mapping_file(method=method, mpiTasks=mpiTasks)

    dsRemap = remapper.remap(ds,
                             renormalizationThreshold=renormalizationThreshold)

    for field in [
            'prescribedLandIceFreshwaterFlux', 'prescribedLandIceHeatFlux'
    ]:
        # zero out the field where it's currently NaN
        dsRemap[field] = dsRemap[field].where(dsRemap[field].nonnull(), 0.)

    dsRemap.attrs['history'] = ' '.join(sys.argv)
    write_netcdf(dsRemap, outFileName)  # }}}