Example #1
0
    def __init__(self, var, maxvalue=0., fillvalue=0., shoreline=None):
        if var.getLongitude() is None:
            var.getAxis(1).designateLongitude()
        if var.getLatitude() is None:
            var.getAxis(1).designateLatitude()
        if var.getGrid() is None:
            var.setGrid(create_grid(var.getLongitude(), var.getLatitude()))
        self._bathy = var
        self._xres, self._yres = resol(self.get_grid())
        _GriddedBathyMasked_.__init__(self, shoreline=shoreline, fillvalue=fillvalue, maxvalue=maxvalue)
        self._lon2d, self._lat2d = meshgrid(self.get_lon(), self.get_lat())
#        self._lon2dp,self._lat2dp = meshbounds(self.get_lon(), self.get_lat())
        self._xxs = self._yys = None
Example #2
0
import pylab as P

# Création de bathymétries fictives à partir de Smith and Sandwell
import cdms2
from vacumm.config import data_sample
cdms2.axis.longitude_aliases.append('x')
cdms2.axis.latitude_aliases.append('y')
f = cdms2.open(data_sample('ETOPO2v2g_flt.grd'))
# - large
var_large = f('z', lon=(-7, -1), lat=(46, 49))
# - petite
var_small = f('z', lon=(-4.5, -.5), lat=(44.5, 46.5))
f.close()
# - regrillage de la large vers une grille moins fine
from vacumm.misc.grid import regridding, resol, create_grid
xr, yr = resol(var_large.getGrid())
grid_large = create_grid((-7., -1, xr * 4.5), (46., 49, yr * 4.5))
var_large = regridding.regrid2d(var_large, grid_large)

# On ajoute un traît de côte pour le masquage
from vacumm.bathy.bathy import GriddedBathy, GriddedBathyMerger
bathy_large = GriddedBathy(var_large, shoreline='i')
bathy_small = var_small

# Création de la grille finale de résolution intermédiaire
final_grid = create_grid((-6., .5, xr * 2.5), (45, 47., yr * 2.5))

# On crée maintenant le merger
merger = GriddedBathyMerger(final_grid)
# - ajout de la bathy basse resolution en premier (en dessous)
merger += bathy_large
Example #3
0
def get_spec(var1, var2=None, dx=None, dy=None, verbose=False, fft=False, **kwargs):
    """Get the spectrum of a 2D variable

    :Return: specvar,nbwave,dk
    """
    # Get the resolution in meters
    kwresol = kwfilter(kwargs, 'resol_')
    if None in [dx, dy]:
        if not cdms2.isVariable(var1):
            raise TypeError('var1 must be a MV2 array to compute dx and dy')
        kwresol.setdefault('proj', True)
        ldx, ldy = resol(var1, **kwresol)
        dx = dx or ldx
        dy = dy or ldy
    if N.ma.isMA(var1): var1= var1.filled(0.)
    if N.ma.isMA(var2): var2 = var2.filled(0.)


    # Part 1 - estimate of the wavenumbers
    [kx,ky,kkx,kky,kk,Lx,Ly] = get_kxky(var1, dx, dy, verbose=verbose)
    if verbose:
        print "dx = %s, fy = %s " %(dx,dy)
        print "kx = ",kx[0:3]
        print "ky = ",ky[0:3]
        print "kkx[0:3,2] = ",kkx[0:3,2]
        print "kky[0:3,1] = ",kky[0:3,1]
        print "kk[0:3,3] = ",kk[0:3,3]
        print "shape",kx.shape,ky.shape,kkx.shape,kky.shape,kk.shape

    # Part 2 - estimate of the spectrum
    # - fast fourier transform
    if fft:
        hat_phi1=N.fft.fft2(var1)
        hat_phi1=hat_phi1*hat_phi1.conj()
        hat_phi1=hat_phi1.real.copy()  # useless
    else:
        hat_phi1 = var1

    if var2 is not None:
        if fft:
            hat_phi2=N.fft.fft2(var2)
            hat_phi2=hat_phi2*hat_phi2.conj()
            hat_phi2=hat_phi2.real.copy()  # useless
        else:
            hat_phi2 = var2
        hat_spec = hat_phi1 + hat_phi2
    else:
        hat_spec = hat_phi1
    # - integration of the spectrum
    #   shift to have values centered on the intervals
    dk = kx[1] - kx[0]
    dk_half = dk/2  # half of the interval
    k_= kx[0:min(var1.shape[1],var1.shape[0])/2] + dk
    specvar = k_*0
    for i in range(len(k_)):
        # get indexes that satisfy two conditions
        # integration over a spectral width
        specvar[i] = ( hat_spec[ (kk<=k_[i]+dk_half) & (kk>k_[i]-dk_half) ] ).sum()

    # Normalisation (Danioux 2011)
    specvar /= (var1.shape[1]*var1.shape[0])**2 * dk

    # Dimensionalization to be able to compare with the litterature
    nbwave = k_*1000.0/2.0/N.pi     # from rad/m to km/m
    dk *= 1000.0/2.0/N.pi
    specvar *= 2.0*N.pi/1000.0
    if verbose:
        if var2 is not None:
            print "\n Normalized co-spectrum : \n",specvar
        else:
            print "\n Normalized spectrum : \n",specvar
    return specvar,nbwave,dk
Example #4
0
def energy_spectrum(var, dx=None, dy=None, ctime=None, dispfig=False, latmean=None, verbose=False):
    """Compute the energy spectrum of a 2D variable"""
    # Guess dx and/or dy
    if None in [dx, dy]:
        if not cdms2.isVariable(var):
            raise TypeError('var must be a MV2 array to compute dx and dy')
        kwresol.setdefault('proj', True)
        ldx, ldy = resol(var, **kwresol)
        dx = dx or ldx
        dy = dy or ldy

    if latmean is None:
        if not cdms2.isVariable(var):
            raise Exception('You must provide explicitly latmean')
        latmean = var.getLatitude().getValue().mean()

    # Numpy arrays
    sshbox = var.filled(0.) if N.ma.isMA(var) else var

    #####################################################
    # estimate of the spatial resolution and the latitude
    #####################################################

    grav = 9.81
    #latmean = int(float(latmean))
    #dx = int(grid[0])*np.cos(np.pi*latmean/180.)
    f0 = 2*N.pi/(24.*3600.)*2.0*N.sin(N.pi*latmean/180.)
    gof0 = grav/f0
    if verbose:
        print "the spatial resolution of the grid is constant \n dx = %s m, dy = %s m" %(dx,dy)
        print "the averaged latitude is %s degrees\n" %(latmean)


    ###############################################
    #  1ST PART ANALYZE FROM THE SEA SURFACE HEIGHT
    #  --------------------------------------------
    ###############################################

    # zonal average and its removing from ssh
    # mean on i (we erase 1 dimension)
    # and duplication along i (depends on sshbox.mean(1).shape)
    # then we need to transpose to have constant value along i and variations along j
    #revoir sshbox = sshbox - N.tile( sshbox.mean(1),(sshbox.shape[1],1) ).T
    # plot of ssh (box domain)
    #if options.dispfig: plot.contour_xy(sshbox,sshbox.shape[0],sshbox.shape[1],'ssh_box_minus_iaverage')

    # estimate of the rms to further check
    sshbox_rms = N.sqrt( (sshbox**2).mean() )
    if verbose: print "rms of the ssh over the region of interest (from physical field) : %s \n" %sshbox_rms

    ################################
    # create a double periodic field
    ################################

    ssh2per = N.tile( sshbox, (2,2) )
    ssh2per[ssh2per.shape[0]/2:ssh2per.shape[0],0:ssh2per.shape[1]/2] = sshbox[::-1,::]
    ssh2per[::,ssh2per.shape[1]/2:] = N.fliplr(ssh2per[::,0:ssh2per.shape[1]/2])
    #if options.dispfig: plot.contour_xy(ssh2per,ssh2per.shape[0],ssh2per.shape[1],'ssh_double_periodic')
    del sshbox

    # estimate of the rms to further check
    ssh2per_rms = N.sqrt( (ssh2per**2).mean() )
    if verbose: print "rms of the double periodic ssh over the region of interest (from physical field) : %s \n" %ssh2per_rms

    ################################
    # wavenumber spectrum of the ssh (double periodic field)
    ################################

    # estimate of the spectrum
    ssh2per_spec, ssh2per_k, dk = get_spec(ssh2per, dx=dx, dy=dy, fft='x2k', verbose=verbose)  # sshbox in physical space

    # make sure the FFT is correct : we must have the same rms either from physics or from wavenumbers
    ssh2per_rmsk = N.sqrt( (ssh2per_spec*dk).sum() )
    if verbose: print "rms of the ssh over the region of interest (from wave number fields) : %s \n" %ssh2per_rmsk

    # figure
    if dispfig: plot_loglog_kspec(ssh2per_spec, ssh2per_k, savefig='ssh2per_spec',
        title='SPECTRUM OF SSH (double periodic)', subtitle=str(ctime),
        xlabel='Wavenumber (cycles/km)', ylabel='SSH [m^2/(cycle/km)]',
        slope=-5)


    ###########################################
    # the ssh pectrum after doubling the domain
    # is much better than the previous one
    ###########################################

    ####################################################
    #  2ND PART ANALYZIS FROM THE GEOSTROPHIC VELOCITIES
    #  -------------------------------------------------
    ####################################################

    ###########################################
    # estimate of the geostrophic velocities (from the spectrum of the periodic field of ssh)
    ###########################################

    # estimate of the wavenumbers
    kx,ky,kkx,kky,kk,Lx,Ly = get_kxky(ssh2per, dx, dy, verbose=verbose)
    # estimate of the velocities from the spectrum of the ssh
    ussh = -gof0*N.fft.ifft2( (kky*N.fft.fft2(ssh2per))*N.complex(0,1) ).real
    vssh =  gof0*N.fft.ifft2( (kkx*N.fft.fft2(ssh2per))*N.complex(0,1) ).real
    #if options.dispfig: plot.contour_xy(ussh,ussh.shape[0],ussh.shape[1],'ussh (from double periodic field spectral method) ')
    #if options.dispfig: plot.contour_xy(vssh,vssh.shape[0],vssh.shape[1],'vssh (from double periodic field and spectral method) ')
    ssh2per_shape = ssh2per.shape
    del ssh2per

    #######################################################
    # wavenumber co-spectrum of the geostrophic velocities (eke)
    #######################################################

    # estimate of the co-spectrum
    uv2per_cospec,eke_k,dk = get_cospec(ussh, vssh, dx=dx, dy=dy, verbose=verbose, fft=True)

    # estimate of the eke to further check
    uv2per_rmsk = N.sqrt( ((uv2per_cospec*dk)/2.).sum() )
    if verbose: print "eke over the region of interest (from physical field) : %s \n" %uv2per_rmsk
    # make sure the FFT is correct : we must have the same rms either from physics or from wavenumbers
    #ssh2per_rmsk = N.sqrt( (ssh2per_spec*dk).mean() )
    #if verbose: print "eke over the region of interest (from physical field) : %s \n" %sshbox_rms
    #if verbose: print "rms of the ssh over the region of interest (from wave number fields) : %s \n" %ssh2per_rmsk
    #if verbose: print "rms difference (wavenumber - physics) : %s \n" %(ssh2per_rmsk-ssh2per_rms)

    # figure
    if dispfig:
        plot_loglog_kspec(uv2per_cospec, eke_k, savefig='eke2per_spec',
            title='SPECTRUM OF EKE', subtitle=str(ctime),
            xlabel='Wavenumber (cycles/km)', ylabel='EKE [(m/s)^2/(cycle/km)]')


    ####################################################
    #  3RD PART ESTIMATE OF THE FLUXES OF ENERGY
    #  -------------------------------------------------
    ####################################################

    ###########################################
    # estimate of the production of eke
    ###########################################

    # geostrophic velocities in the spectral space are non zero in the bottom-left corner
    ug = ussh.copy() ; del ussh
    ug[ssh2per_shape[0]/2:ssh2per_shape[0],::] = 0.
    ug[::,ssh2per_shape[1]/2:] = 0.
    vg = vssh.copy() ; del vssh
    vg[ssh2per_shape[0]/2:ssh2per_shape[0],::] = 0.
    vg[::,ssh2per_shape[1]/2:] = 0.
    #if options.dispfig: plot.contour_xy(ug,ug.shape[0],ug.shape[1],'ug (from the spectrum of the periodic ssh)')
    #if options.dispfig: plot.contour_xy(vg,vg.shape[0],vg.shape[1],'vg (from the spectrum of the periodic ssh)')


    u = N.fft.fft2(ug)
    v = N.fft.fft2(vg)

    ugx = N.fft.ifft2( (u*kkx)*N.complex(0,1) ).real
    ugy = N.fft.ifft2( (u*kky)*1j ).real
    vgx = N.fft.ifft2( (v*kkx)*1j ).real
    vgy = N.fft.ifft2( (v*kky)*1j ).real
    term_u = N.fft.fft2(ug*ugx + vg*ugy)
    term_v = N.fft.fft2(ug*vgx + vg*vgy)
    eke_prod = - ( u.conj()*term_u + v.conj()*term_v ).real
    eke_prod_phys1=N.fft.ifft2(eke_prod).real
    #if options.dispfig: plot.contour_xy(eke_prod_phys1,eke_prod_phys1.shape[0],eke_prod_phys1.shape[1],'eke_prod_phys1')

    term_u = 1j*kkx*N.fft.fft2(ug*ug) + 1j*kky*N.fft.fft2(vg*ug)
    term_v = 1j*kkx*N.fft.fft2(ug*vg) + 1j*kky*N.fft.fft2(vg*vg)
    eke_prod = - ( u.conj()*term_u + v.conj()*term_v ).real
    eke_prod_phys2=N.fft.ifft2(eke_prod).real
    #if options.dispfig: plot.contour_xy(eke_prod_phys2,eke_prod_phys2.shape[0],eke_prod_phys2.shape[1],'eke_prod_phys2')
    #if options.dispfig: plot.contour_xy(eke_prod_phys1-eke_prod_phys2,eke_prod_phys2.shape[0],eke_prod_phys2.shape[1],'diff_eke_prod')
    phi = eke_prod_phys1-eke_prod_phys2

    # estimate of the total energy flux of the momentum equation
    gg_spec, gg_k, dk = get_spec(eke_prod, dx=dx, dy=dy, verbose=verbose, fft=False)  # phi in Fourier space

    # choose kmax1 such that it corresponds to gg_k(kmax1) < 1/(3*dx)*1000 [km/m] (2dx Shanon + take into account diffusion)
    kmax1 = min( N.where(gg_k>= 1/(3.0*dx)*1000.)[0][0] - 1 ,gg_spec.shape[0])
    if verbose: print "Shanon criterium kmax1 = %s, gg_k(kmax1) = %s, gg_k(kmax1+1) = %s, 1/(3.0*dx)*1000. = %s" %(kmax1,gg_k[kmax1],gg_k[kmax1+1],1/(3.0*dx)*1000.)
    # integration from large scales to small ones (shift one large scales)
    tpi = N.array( [sum(gg_spec[ i:kmax1 ]) for i in range(kmax1)] )
    tpi[0]=0.

    # figure
    if dispfig:
        plot_semilogx_kspec(tpi, gg_k[:kmax1], savefig='ssh_spec',
        title='TOTAL ENERGY FLUX', subtitle=str(ctime),
        xlabel='Wavenumber (cycles/km)', ylabel='Sum of EKE from small scales to k [(m/s)^2/(cycle/km)]')


    if verbose: print "The end !"

    del grav,f0,gof0,sshbox_rms,ssh2per_rms,dk,kx,ky,kkx,kky,kk,Lx,Ly,uv2per_rmsk,ug,vg,u,v,term_u,term_v,ugx,ugy,vgx,vgy,eke_prod,eke_prod_phys1,eke_prod_phys2,phi,gg_spec
    gc.collect()

    return ssh2per_spec, ssh2per_k, uv2per_cospec, eke_k, tpi, gg_k[:kmax1]
Example #5
0
y = xyz.y
z = xyz.z

# %% Extensions
# - en tenant compte des zones de selection et exclusion
print 'Limites:', xyz.xmin, xyz.xmax, xyz.ymin, xyz.ymax
# - donnees brutes
print 'X min brut:', xyz.get_xmin(mask=False), xyz.get_x(mask=False).min()

# %% Mean resolution
print 'Resolution in degrees:', xyz.resol(deg=True)
print 'Resolution in meters:', xyz.resol()

# %% Automatic grid
grid_auto = xyz.grid
print 'Resolution of auto grid:', resol(grid_auto)

# %% Interpolation on auto grid
print 'Interpolation:'
gridded_auto = xyz.togrid()
#  equivalent a :
#  >>> gridded_auto = xyz.togrid(xyz.grid)

# %% Interpolation on manual grid
print 'Interpolation and masking, then extraction'
# - defintion
grid_manual = create_grid((-5.3, -4.91, .01), (48.1, 48.41, .01))
# - interpolation
gridded_manual = xyz.togrid(grid_manual, mask='h')
# - extraction with margin
xyz_up = xyz.clip(zone=(None, None, None, 48.3), margin=2)
y = xyz.y
z = xyz.z

# Extensions
# - en tenant compte des zones de selection et exclusion
print 'Limites :', xyz.xmin, xyz.xmax, xyz.ymin, xyz.ymax
# - donnees brutes
print 'X min brut :', xyz.get_xmin(mask=False), xyz.get_x(mask=False).min()

# Resolution moyenne
print 'Resolution geographique :', xyz.resol(deg=True)
print 'Resolution metrique :', xyz.resol()

# Definition auto d'une grille reguliere
grid_auto = xyz.grid
print 'Resolution grille auto :', resol(grid_auto)

# Interpolation sur grille auto
print 'Interpolation auto'
gridded_auto = xyz.togrid()
#  equivalent a :
#  >>> gridded_auto = xyz.togrid(xyz.grid)

# Interpolation sur grille manuelle
print 'Interpolation et masquage manuels puis extraction'
# - defintion de la grille
grid_manual = create_grid((-5.3, -4.91, .01), (48.1, 48.41, .01))
# - interpolation
gridded_manual = xyz.togrid(grid_manual, mask='h')
# Extraction d'une sous-zone (xmin,ymin...) avec marge
xyz_up = xyz.clip(zone=(None, None, None, 48.3), margin=2)
Example #7
0
lonn, latn = get_xy(gg, num=True)
grid = create_grid(*gg)
print 'Dimensions           : nx=%i ny=%i' % grid.shape[::-1]
print 'Axes                 : lon="%s" lat="%s" (%iD)' % (lon.id, lat.id,
                                                          lonn.ndim)

# Extension
print 'Zonal extent         : %s -> %s  [%s -> %s]' % (
    lonn.min(), lonn.max(), lonlab(
        lonn.min(), decimal=False), lonlab(lonn.max(), decimal=False))
print 'Meridional extent    : %s -> %s  [%s -> %s]' % (
    latn.min(), latn.max(), latlab(
        latn.min(), decimal=False), latlab(latn.max(), decimal=False))

# Resolution
lonres, latres = resol(gg, proj=False)
xres, yres = resol(gg, proj=True)
xres /= 1000.
yres /= 1000.
print 'Zonal resolution     : %g° / %gkm' % (lonres, xres)
print 'Meridional resolution: %g° / %gkm' % (latres, yres)

# Plot
if options.plot or options.out:

    xmin, ymin, xmax, ymax = scalebox(grid, 1 / options.zoom)
    for att in 'xmin', 'xmax', 'ymin', 'ymax':
        if getattr(options, att) is not None:
            exec att + " = %s" % getattr(options, att)
    if options.figsize is not None:
        try:
Example #8
0
    if grid is None:
        sys.exit('Variable "%s" has no grid'%options.vname)
else: # loop on all variables
    for vname in f.listvariables():
        grid = f[vname].getGrid()
        if grid is not None: break
    else:
        sys.exit('No variable with a grid found')
grid = (grid.getLongitude().clone(), grid.getLatitude().clone())

# VACUMM path
here = os.path.dirname(__file__)
for rpath in [os.path.join(here, '../lib/python')]:
    path = os.path.abspath(rpath)
    sys.path.append(path)

# Resolution
try:
    from vacumm.misc.grid import resol
except:
    sys.exit('Error when loading vacumm')
xres, yres = resol(grid, proj=options.meters)
if options.meters:
    units = 'km'
    xres /= 1000.
    yres /= 1000.
else:
    units = '°'
print 'dx=%(xres)g%(units)s, dy=%(yres)g%(units)s'%locals()
f.close()
Example #9
0
y = xyz.y
z = xyz.z

# Extensions
# - en tenant compte des zones de selection et exclusion
print  'Limites :', xyz.xmin,  xyz.xmax, xyz.ymin,  xyz.ymax
# - donnees brutes
print  'X min brut :', xyz.get_xmin(mask=False),   xyz.get_x(mask=False).min()

# Resolution moyenne
print 'Resolution geographique :', xyz.resol(deg=True)
print 'Resolution metrique :', xyz.resol()

# Definition auto d'une grille reguliere
grid_auto = xyz.grid
print 'Resolution grille auto :', resol(grid_auto)

# Interpolation sur grille auto
print 'Interpolation auto'
gridded_auto = xyz.togrid()
#  equivalent a :
#  >>> gridded_auto = xyz.togrid(xyz.grid)

# Interpolation sur grille manuelle
print 'Interpolation et masquage manuels puis extraction'
# - defintion de la grille
grid_manual = create_grid((-5.3, -4.91, .01), (48.1, 48.41, .01))
# - interpolation
gridded_manual = xyz.togrid(grid_manual, mask='h')
# Extraction d'une sous-zone (xmin,ymin...) avec marge
xyz_up = xyz.clip(zone=(None, None, None, 48.3), margin=2)
Example #10
0
# Dimension
gg = (lon, lat)
lonn, latn = get_xy(gg, num=True)
grid = create_grid(*gg)
print 'Dimensions           : nx=%i ny=%i'%grid.shape[::-1]
print 'Axes                 : lon="%s" lat="%s" (%iD)'%(lon.id, lat.id, lonn.ndim)


# Extension
print 'Zonal extent         : %s -> %s  [%s -> %s]'%(
    lonn.min(), lonn.max(), lonlab(lonn.min(), decimal=False), lonlab(lonn.max(), decimal=False))
print 'Meridional extent    : %s -> %s  [%s -> %s]'%(
    latn.min(), latn.max(), latlab(latn.min(), decimal=False), latlab(latn.max(), decimal=False))

# Resolution
lonres, latres = resol(gg, proj=False)
xres, yres = resol(gg, proj=True)
xres /= 1000.
yres /= 1000.
print 'Zonal resolution     : %g° / %gkm'%(lonres, xres)
print 'Meridional resolution: %g° / %gkm'%(latres, yres)

# Plot
if options.plot or options.out:

    xmin, ymin, xmax, ymax = scalebox(grid, 1/options.zoom)
    for att in 'xmin', 'xmax', 'ymin', 'ymax':
        if getattr(options, att) is not None: exec att+" = %s"%getattr(options, att)
    if options.figsize is not None:
        try:
            options.figsize = eval(options.figsize)
# -*- coding: utf8 -*-
# Création de bathymétries fictives à partir de Smith and Sandwell
import cdms2
from vacumm.config import data_sample
cdms2.axis.longitude_aliases.append('x')
cdms2.axis.latitude_aliases.append('y')
f = cdms2.open(data_sample('ETOPO2v2g_flt.grd'))
# - large
var_large = f('z', lon=(-7, -1), lat=(46, 49))
# - petite
var_small = f('z', lon=(-4.5, -.5), lat=(44.5, 46.5))
f.close()
# - regrillage de la large vers une grille moins fine
from vacumm.misc.grid import regridding, resol, create_grid
xr, yr = resol(var_large.getGrid())
grid_large = create_grid((-7., -1, xr*4.5), (46., 49, yr*4.5))
var_large = regridding.regrid2d(var_large, grid_large)

# On ajoute un traît de côte pour le masquage
from vacumm.bathy.bathy import GriddedBathy, GriddedBathyMerger
bathy_large = GriddedBathy(var_large, shoreline='i')
bathy_small = var_small

# Création de la grille finale de résolution intermédiaire
final_grid = create_grid((-6., .5, xr*2.5), (45, 47., yr*2.5))

# On crée maintenant le merger
merger = GriddedBathyMerger(final_grid)
# - ajout de la bathy basse resolution en premier (en dessous)
merger += bathy_large
# - puis ajout de celle haute résolution
Example #12
0
def barotropic_geostrophic_velocity(ssh,
                                    dxy=None,
                                    gravity=default_gravity,
                                    cyclic=False,
                                    format_axes=True,
                                    getu=True,
                                    getv=True,
                                    filter=None):
    """Get barotropic geostropic velocity from SSH on a C-grid

    .. note:: ssh is supposed to be at T points,
        ubt is computed at V points,
        and vbt is computed at U points.

    .. todo:: Rewrite it using :mod:`vacumm.data.misc.arakawa` and defining
        a limited number of algorithms for different staggering configurations.

    :Params:

        - **ssh**: Sea surface height.
        - **dxy**, optional: Horizontal resolutions (m).
          Resolution along X and Y are respectively at U and V points.
          Possible forms:

            - ``res``: A scalar meaning a constant resolution along X and Y.
            - ``(dx,dy)``: A tuple of resolutions along X and Y.
            - ``None``: Resolution is estimated using
              :func:`~vacumm.misc.grid.misc.resol`.

    :Return: ``(ubt,vbt)``
    """
    if not getu and not getv: return

    # Init masked
    if getu: ugbt = format_var(ssh * MV2.masked, 'ugbt', format_axes=False)
    if getv: vgbt = format_var(ssh * MV2.masked, 'vgbt', format_axes=False)

    # Grid
    tgrid = ssh.getGrid()
    if getu: ugrid = shiftgrid(tgrid, ishift=0.5)
    if getv: vgrid = shiftgrid(tgrid, jshift=0.5)
    if format_axes:
        if getv: format_grid(ugrid, 'u')
        if getu: format_grid(vgrid, 'v')
    if getu: set_grid(ugbt, vgrid)
    if getv: set_grid(vgbt, ugrid)

    # Resolutions
    if dxy is None:
        dxt, dyt = resol(ssh, proj=True, mode='local')
        dxu = 0.5 * (dxt[:, 1:] + dxt[:, :-1])
        del dxt
        dyv = 0.5 * (dyt[1:, :] + dyt[:-1, :])
        del dyt
    elif not isinstance(dxy, (list, tuple)):
        dxu = dyv = dxy
    else:
        dxu, dyv = dxy
    if getv and isinstance(dxu, N.ndarray):
        if cdms2.isVariable(dxu): dxu = dxu.asma()
        if dxu.ndim == 1: dxu.shape = 1, -1
        if dxu.shape[1] == ssh.shape[-1]:
            dxu = dxu[:, :-1]
    if getu and isinstance(dyv, N.ndarray):
        if cdms2.isVariable(dyv): dyv = dyv.asma()
        if dyv.ndim == 1: dyv.shape = -1, 1
        if dyv.shape[0] == ssh.shape[-2]:
            dyv = dyv[:-1]

    # Get geostrophic factor
    f0 = coriolis_parameter(ssh, gravity=gravity, fromvar=True).asma()
    bad = f0 == 0.
    f0[bad] = 1.
    f0[bad] = N.ma.masked
    del bad
    gf = gravity / f0
    del f0

    # Computes
    sshm = ssh.asma()
    sshm = sshm * gf
    del gf
    if getu:
        ugbt[..., :-1, :] = -N.ma.diff(sshm, axis=-2) / dyv
        del dyv
    if getv:
        vgbt[..., :-1] = N.ma.diff(sshm, axis=-1) / dxu
        del dxu
    del sshm
    if getu and cyclic:
        ugbt[..., -1] = ugbt[..., 0]

    if not getu: return vgbt
    elif not getv: return ugbt
    return ugbt, vgbt
Example #13
0
def barotropic_geostrophic_velocity(ssh, dxy=None, gravity=default_gravity, cyclic=False,
    format_axes=True, getu=True, getv=True, filter=None):
    """Get barotropic geostropic velocity from SSH on a C-grid

    .. note:: ssh is supposed to be at T points,
        ubt is computed at V points,
        and vbt is computed at U points.

    .. todo:: Rewrite it using :mod:`vacumm.data.misc.arakawa` and defining
        a limited number of algorithms for different staggering configurations.

    :Params:

        - **ssh**: Sea surface height.
        - **dxy**, optional: Horizontal resolutions (m).
          Resolution along X and Y are respectively at U and V points.
          Possible forms:

            - ``res``: A scalar meaning a constant resolution along X and Y.
            - ``(dx,dy)``: A tuple of resolutions along X and Y.
            - ``None``: Resolution is estimated using
              :func:`~vacumm.misc.grid.misc.resol`.

    :Return: ``(ubt,vbt)``
    """
    if not getu and not getv: return

    # Init masked
    if getu: ugbt = format_var(ssh*MV2.masked, 'ugbt', format_axes=False)
    if getv: vgbt = format_var(ssh*MV2.masked, 'vgbt', format_axes=False)

    # Grid
    tgrid = ssh.getGrid()
    if getu: ugrid = shiftgrid(tgrid, ishift=0.5)
    if getv: vgrid = shiftgrid(tgrid, jshift=0.5)
    if format_axes:
        if getv: format_grid(ugrid, 'u')
        if getu: format_grid(vgrid, 'v')
    if getu: set_grid(ugbt, vgrid)
    if getv: set_grid(vgbt, ugrid)

    # Resolutions
    if dxy is None:
        dxt, dyt = resol(ssh, proj=True, mode='local')
        dxu = 0.5*(dxt[:, 1:]+dxt[:, :-1]) ; del dxt
        dyv = 0.5*(dyt[1:, :]+dyt[:-1, :]) ; del dyt
    elif not isinstance(dxy, (list, tuple)):
        dxu = dyv = dxy
    else:
        dxu,  dyv = dxy
    if getv and isinstance(dxu, N.ndarray):
        if cdms2.isVariable(dxu): dxu = dxu.asma()
        if dxu.ndim==1: dxu.shape = 1, -1
        if dxu.shape[1]==ssh.shape[-1]:
            dxu = dxu[:, :-1]
    if getu and isinstance(dyv, N.ndarray):
        if cdms2.isVariable(dyv): dyv = dyv.asma()
        if dyv.ndim==1: dyv.shape = -1, 1
        if dyv.shape[0]==ssh.shape[-2]:
            dyv = dyv[:-1]


    # Get geostrophic factor
    f0 = coriolis_parameter(ssh, gravity=gravity, fromvar=True).asma()
    bad = f0==0.
    f0[bad] = 1.
    f0[bad] = N.ma.masked ; del bad
    gf = gravity/f0 ; del f0

    # Computes
    sshm = ssh.asma()
    sshm = sshm*gf ; del gf
    if getu: ugbt[..., :-1, :] = -N.ma.diff(sshm, axis=-2)/dyv ; del dyv
    if getv: vgbt[..., :-1] = N.ma.diff(sshm, axis=-1)/dxu ; del dxu
    del sshm
    if getu and cyclic:
        ugbt[..., -1] = ugbt[..., 0]

    if not getu: return vgbt
    elif not getv: return ugbt
    return ugbt, vgbt