Ejemplo n.º 1
0
def section_integral(v, xmin, xmax):
    """ Section integral between x values """
    minind, maxind = utils.get_indrange(v.x, xmin, xmax)
    if v.surface_field:
        dx = v.cell_widths_as_data[:, minind:maxind]
        return np.sum(v.data[:, minind:maxind] * dx, axis=1)
    else:
        da = v.cell_widths_as_data[:, :,
                                   minind:maxind] * v.dz_as_data[:, :,
                                                                 minind:maxind]
        return np.sum(v.data[:, :, minind:maxind] * da, axis=(1, 2))
Ejemplo n.º 2
0
def calc_ek(v, tau, minlon, maxlon, ek_level, profile='uniform'):
    """ Return ZonalSections containing Ekman velocities """

    # Copy velocity data structure
    ek = copy.deepcopy(v)
    ek.data.data[:] = 0.0

    # Get indices for gyre interior
    intmin, intmax = utils.get_indrange(tau.x, minlon, maxlon)

    # Calculate depth-integrated Ekman transports
    dx = tau.cell_widths_as_data[:, intmin:intmax]
    lats = tau.y[intmin:intmax]
    taux = tau.data[:, intmin:intmax]
    corf = 2 * ROT * np.sin(np.pi * (lats / 180.))
    ek_trans = ((-1. * taux / (corf * RHO_REF)) * dx).sum(axis=1)

    # Calculate velocities over ekman layer
    ek_minind, ek_maxind = utils.get_indrange(v.z, 0, ek_level)
    dz = v.dz_as_data[0, ek_minind:ek_maxind, intmin:intmax]
    dx = v.cell_widths_as_data[0, ek_minind:ek_maxind, intmin:intmax]

    if profile == 'uniform':
        # Use uniform Ekman velocities
        ek_area = (dx * dz).sum()
        ek.data[:, ek_minind:ek_maxind,
                intmin:intmax] = ek_trans[:, np.newaxis, np.newaxis] / ek_area
        ek.data = np.ma.MaskedArray(ek.data, mask=v.mask)
    elif profile == 'linear':
        # Use Ekman transport profile that linearly reduces to zero at z=zek
        zprof = ek.z[ek_minind:ek_maxind]
        dzprof = ek.dz[ek_minind:ek_maxind]
        zmax = dzprof.sum()
        vek = get_linear_profiles(ek_trans, zprof, dzprof,
                                  zmax) / dx[np.newaxis].sum(axis=2)
        ek.data[:, ek_minind:ek_maxind, intmin:intmax] = vek[:, :, np.newaxis]
        ek.data = np.ma.MaskedArray(ek.data, mask=v.mask)
    else:
        raise ValueError('Unrecognized ekman profile type')

    return ek
Ejemplo n.º 3
0
def rapid_mass_balance(vgeo, ek, minlon, midlon, maxlon):
    """ 
    Return vgeo after applying RAPID-style mass-balance constraint
    as a barotropic velocity over geostrophic interior
    """

    # Calculate net transports
    fcwbw_tot = section_integral(vgeo, minlon, midlon)
    ek_tot = section_integral(ek, midlon, maxlon)
    int_tot = section_integral(vgeo, midlon, maxlon)
    net = int_tot + ek_tot + fcwbw_tot

    # Get cell dimensions in gyre interior
    minind, maxind = utils.get_indrange(vgeo.x, midlon, maxlon)
    dz = vgeo.dz_as_data[0]
    dx = vgeo.cell_widths_as_data[0]
    da = (dx[:, minind:maxind] * dz[:, minind:maxind])

    # Correct geostrophic transports in gyre interior
    corr = net / da.sum()
    vgeo.data[:, :, minind:maxind] = (vgeo.data[:, :, minind:maxind] -
                                      corr[:, np.newaxis, np.newaxis])

    return vgeo
Ejemplo n.º 4
0
def merge_vgeo_and_v(vgeo, v, minlon, maxlon):
    """ Return vgeo with velocities from v west of lonbnd """
    minind, maxind = utils.get_indrange(vgeo.x, minlon, maxlon)
    vgeo.data[:, :, minind:maxind] = v.data[:, :, minind:maxind]

    return vgeo
Ejemplo n.º 5
0
def calc_transports_from_sections(config, v, tau, t_on_v, s_on_v):
    """
    High-level routine to call transport calculations and return
    integrated transports on RAPID section as netcdf object
    
    """
    # Extract sub-section boundaries
    fc_minlon = config.getfloat(
        'options', 'fc_minlon')  # Minimum longitude for Florida current
    fc_maxlon = config.getfloat(
        'options', 'fc_maxlon')  # Longitude of Florida current/WBW boundary
    wbw_maxlon = config.getfloat(
        'options', 'wbw_maxlon')  # Longitude of WBW/gyre boundary
    int_maxlon = config.getfloat(
        'options', 'int_maxlon')  # Maximum longitude of gyre interior

    # Get indices for sub-sections
    fcmin, fcmax = utils.get_indrange(v.x, fc_minlon,
                                      fc_maxlon)  # Florida current
    wbwmin, wbwmax = utils.get_indrange(v.x, fc_maxlon, wbw_maxlon)  # WBW
    intmin, intmax = utils.get_indrange(v.x, wbw_maxlon,
                                        int_maxlon)  # Gyre interior

    # Calculate dynamic heights
    dh = calc_dh(t_on_v, s_on_v)

    # Calculate geostrophic transports
    georef = config.getfloat('options', 'georef_level')
    vgeo = calc_vgeo(v, dh, georef=georef)

    # Optionally reference geostrophic transports to model velocities
    if config.has_option('options', 'vref_level'):
        vref_level = config.getfloat('options', 'vref_level')
        vgeo = update_georef(vgeo, v, vref_level)

    # Calculate Ekman velocities
    ek_level = config.getfloat('options', 'ekman_depth')
    if config.has_option('options', 'ek_profile_type'):
        ek_profile = config.get('options', 'ek_profile_type')
    else:
        ek_profile = 'uniform'

    ek = calc_ek(v, tau, wbw_maxlon, int_maxlon, ek_level, profile=ek_profile)

    # Use model velocities in fc and WBW regions
    vgeo = merge_vgeo_and_v(vgeo, v, fc_minlon, wbw_maxlon)

    # Apply mass-balance constraints to section
    vgeo = rapid_mass_balance(vgeo, ek, fc_minlon, wbw_maxlon, int_maxlon)

    # Add ekman to geostrophic transports for combined rapid velocities
    vrapid = copy.deepcopy(vgeo)
    vrapid.data = vgeo.data + ek.data

    # Get volume and heat transports on each (sub-)section
    fc_trans = Transports(vgeo, t_on_v, fcmin,
                          fcmax)  # Florida current transports
    wbw_trans = Transports(vgeo, t_on_v, wbwmin,
                           wbwmax)  # Western-boundary wedge transports
    int_trans = Transports(vgeo, t_on_v, intmin,
                           intmax)  # Gyre interior transports
    ek_trans = Transports(ek, t_on_v, intmin, intmax)  # Ekman transports
    model_trans = Transports(
        v, t_on_v, fcmin,
        intmax)  # Total section transports using model velocities
    rapid_trans = Transports(
        vrapid, t_on_v, fcmin,
        intmax)  # Total section transports using RAPID approximation

    # Create netcdf object for output/plotting
    trans = output.create_netcdf(config, rapid_trans, model_trans, fc_trans,
                                 wbw_trans, int_trans, ek_trans)

    return trans