예제 #1
0
def vbyz(dgl):
    """Calculate the effect on stratification of differential meridional
    buoyancy fluxes"""
    #First ensure that the correct vertical field is present
    fld_exists = mit.check_field(dgl,'pvz')
    if not fld_exists:
        dgl = mit.add_field(dgl,'pvz')
        zlen = len(dgl[0]['z'])
        dgl[0]['pvz'] = 0.5*(dgl[0]['z'][0:zlen-1] + dgl[0]['z'][1:zlen])
    import eosmit   #This routine checks if buoyancy is already loaded before running
    eos = 'jmd'
    dgl = eosmit.buoy_dgl(dgl,eos=eos)
    fld_exists = mit.check_field(dgl,'vbxz')
    if not fld_exists:
        dgl = mit.add_field(dgl,'vbyz')
    dgl[0]['vbyz'] = dgl[0]['v']*mit.ddy(dgl[0]['b'],dgl[0]['y'])

    return dgl
예제 #2
0
def ldgl(
    tims,
    levs,
    diag_file,
    diag_name,
    search_folders=None,
    ylims=None,
    xlims=None,
    eos="None",
    normf=False,
    alpha=2e-4,
    sbeta=7.4e-4,
    len_dgl=1,
):
    """
    Mandatory input fields:
    tims - a list of the times when output is wanted in days e.g. np.arange(0,10,1e-1)
    Can also be given as an int/float/long that is converted to a list.
    levs - a list of the model levels where output is wanted e.g. np.arange(0,100)
    where 0 is the surface level and 100 is the deepest level.
    Can also be given as an int/float/long that is converted to a list.
    diag_file - a string that allows unique identification of the output files.
    For state files (e.g. state.0000000000.t0001.nc) this must be 'st', otherwise
    can be 'pv', for example, if the output files are called 'pvDiag.0000000000.t001.nc'.
    diag_name - a list of strings that set the fields that will be read from the model.
    For ease of use, one letter shortcuts are used and converted to the proper model names in
    the function 'get_full_diag_name' below e.g. ['u','s'] loads u velocity and salt.

    Optional input fields:
    search_folders - a two element list setting the number of the first and last
    of the mnc_tile_xxxx folders to be read from e.g. [1, 24] (note 1-based indexing
    for the tile numbers).
    ylims - a two element list that specifies the lower and upper bounds to load
    in **kilometres**.  Note that closest tile boundary to the limits is found
    rather than the closest grid point to avoid reading in partial tiles.
    xlims - as for ylims.
    eos - string. Needed if buoyancy is wanted. Can be 'lin' for a linear
    equation of state or 'jmd' for Jackett and McDougall (1995). No default
    is specified to ensure the user chooses.

    Procedure
    Load the desired model output as a structured array.
    First get the overall model attributes and use this to create the model grid.
    Then adapt the desired output times (called 'tims') to the actual model output times.
    If x or y limits have been specified, set the tile limits accordingly.
    Then pre-allocate the output structured array (called 'dgl').
    Load the grid and time output into the output structured array.
    Then load in the model diagnostic fields into the output structured array.
    Finally, add any fields that are calculated from other outputs to the
    output structured array.

    Glossary
    "Job" refers to a batch of outputs from breaking a simulation into a series
    of model runs.  If there are 24 tiles and 3 jobs, the output will be in files
    mnc_tile_0001 to mnc_tile_0072.
    """
    # First make sure that input parameters are lists and convert them if not
    if isinstance(tims, (int, long, float)):
        tims = [tims]
    if isinstance(levs, (int, long, float)):
        levs = [levs]
    if isinstance(diag_name, (str)):
        diag_name = [diag_name]
    # Find the range of tile output files to examine.  This can be specified
    # as an optional input to improve speed or exclude certain files
    if search_folders is None:
        search_folders = [int(sorted(glob.glob("mnc_tile*"))[0][-4:])]
        search_folders.append(int(sorted(glob.glob("mnc_tile*"))[-1][-4:]))
    # Get the overall attributes of the domain from a grid file - parameters set initially in SIZE.h
    nx, ny, sx, sy, px, py = read_grid_atts(search_folders, diag_file)
    # Define a variable that captures the number of tiles for each job
    tile_interval = px * py
    ## Construct the grid - horizontal then vertical. This is done using
    # the first grid tile only for the doubly-periodic set-up.
    x, dx, y, dy, depths, f = make_grid_hor(search_folders, diag_file, nx, ny)
    z, levs = make_grid_vert(search_folders, depths, diag_file, levs)

    # Now establish at what times the model outputs occur. Have further lists
    # that record what job each output time occurred in (tjobs),
    # what file in a folder it corresponds to (tfiles)
    # and what time point in that file it corresponds to (tpoints).
    t, tjobs, tfiles, tpoints = find_output_times(search_folders, diag_file, tile_interval)
    # Convert the index values to integers
    tjobs = tjobs.astype(int)
    tfiles = tfiles.astype(int)
    tpoints = tpoints.astype(int)
    # Change the input time series (tims) to match the range of values for which
    # there is model output
    tims = chop_tims(tims, t)
    # Align input times (tims) with model times (t). Have further lists that
    # record the job number, file number and time point in the file these are found at.
    tims, tjs, fls, pts = align_tims(tims, t, tjobs, tfiles, tpoints)
    # Re-set range of search tiles to omit those outside the time range.
    search_folders = np.arange(tjs[0], tjs[-1] + tile_interval)

    if ylims is not None:
        # If we want to specify y-limits...
        # Make the list of files we actually want to extract output
        # from - these relate to the numbers at the end of the .nc files,
        # not the random number of the tile directories
        # 0-based index
        rl, ru = find_row_range(nx, ny, sx, sy, px, py, x, dx, y, dy, ylims)
        y = y[rl * sy : ((ru + 1) * sy)]
    else:
        # otherwise if no y-limits specified then just take all the rows
        rl = 0
        ru = (ny / sy) - 1

    if xlims is not None:
        # If we want to specify x-limits...
        # Make the list of files we actually want to extract output
        # from - these relate to the numbers at the end of the .nc files,
        # not the random number of the tile directories
        # 0-based index
        cl, cu = find_col_range(nx, ny, sx, sy, px, py, x, dx, y, dy, xlims)
        x = x[cl * sx : ((cu + 1) * sx)]

    else:
        # otherwise if no y-limits specified then just take all the rows
        cl = 0
        cu = (nx / sx) - 1

    if xlims or ylims is not None:
        # If we have specified y-limits or x-limits then constrain the list of
        # output tiles we want to read from in read_diag below.
        output_folder_list = []
        for rws in np.arange(rl, ru + 1):
            output_folder_list = np.hstack((output_folder_list, px * (rws) + np.arange(cl + 1, cu + 2)))
    else:
        output_folder_list = np.arange(1, tile_interval + 1)
    # A set of handy variables used repeatedly below
    xlen = len(x)
    ylen = len(y)
    zlen = len(z)
    tlen = len(tims)
    # Create the shape of the output array
    dty_info = [
        ("tims", np.float32, np.shape(tims)),
        ("x", np.float32, np.shape(x)),
        ("y", np.float32, np.shape(y)),
        ("z", np.float32, np.shape(z)),
        ("f", np.float32, np.shape(f)),
    ]
    # Specify the initial list of grid output fields.
    out_diags = []
    calc_diags = []
    model_name = []
    # Add the desired diagnostic fields to the pre-allocation array and field list.
    for dindx, diag in enumerate(diag_name):
        if diag is "n2" or diag is "pv" or diag is "pv1" or diag is "pv2" or diag is "pv3" or diag is "rib":
            """Shorten the vertical length for fields that have a first-order
            #vertical derivative."""
            zl = zlen - 1
        else:
            """Else just use the full z-length"""
            zl = zlen
        # Add the diagnostic to the pre-allocation array.  Use float32 in line
        # with 32-bit model outputs.
        dty_info.append((diag_name[dindx], np.float32, [ylen, xlen, zl, tlen]))

        if (
            diag == "rv"
            or diag == "rvf"
            or diag == "b"
            or diag == "n2"
            or diag == "pv"
            or diag == "pv1"
            or diag == "pv2"
            or diag == "pv3"
            or diag == "rib"
        ):
            calc_diags.append(diag)
        else:
            out_diags.append(diag)
            model_name.append(get_full_diag_name(diag_file, diag))

    ## Load the output array dgl with the grid variables
    dgl = np.zeros((len_dgl,), dtype=dty_info)
    dgl[0]["tims"][:] = tims
    dgl[0]["x"][:] = x
    dgl[0]["y"][:] = y
    dgl[0]["z"][:] = z
    dgl[0]["f"][:] = f

    ## Load all the diagnostics together to avoid large overhead of opening/closing netcdf files
    dgl = read_diag(
        search_folders,
        tile_interval,
        output_folder_list,
        cl,
        rl,
        tjs,
        fls,
        pts,
        levs,
        diag_file,
        out_diags,
        model_name,
        dgl,
    )
    if calc_diags:
        for cld in calc_diags:
            if cld == "rv":
                import pvmit

                dgl = pvmit.rv(dgl, normf)
            elif cld == "rvf":
                import pvmit

                dgl = pvmit.rv(dgl, normf=True)
            if cld == "b" or cld == "n2" or cld == "rib":
                import eosmit

                dgl = eosmit.buoy_dgl(dgl, eos=eos, alpha=alpha, sbeta=sbeta)
            if cld[0:2] == "n2" or cld[0:2] == "pv":
                import eosmit

                dgl = eosmit.buoy_dgl(dgl, eos=eos, alpha=alpha, sbeta=sbeta)
            if cld == "n2":
                import pvmit

                dgl = pvmit.n2(dgl)
            if cld == "pv1":
                import pvmit

                dgl = pvmit.pv1(dgl)
            if cld == "pv2":
                import pvmit

                dgl = pvmit.pv2(dgl)
            if cld == "pv3":
                import pvmit

                dgl = pvmit.pv3(dgl)
            if cld == "rib":
                import pvmit

                dgl = pvmit.rib(dgl)
            if cld == "pv":
                import pvmit

                dgl = pvmit.pv(dgl)

    return dgl