def stability(temp, lev, zdim, punit=100.): """ P level coordinates stability (Brunt-Vaisala). :param temp: array_like, temperature. :param lev: array_like, pressure level. :param zdim: vertical dimension axis. :param punit: pressure unit. :return: ndarray. """ temp = np.asarray(temp) ndim = temp.ndim p = arr.expand(lev, ndim, axis=zdim) * punit theta = pottemp(temp, lev, zdim, punit=punit) alpha = Rd * temp / p N = -alpha * grid.dvardp(np.log(theta), lev, zdim, punit=punit) return N
def pottemp(temp, lev, zdim, punit=100., p0=100000.): """ Calculate potential temperature. :param temp: array_like, temperature [K]. :param lev: array_like, level [punit*Pa]. :param zdim: vertical dimensions. :param punit: pressure level punit. :param p0: reference pressure. :return: ndarray. """ temp = np.asarray(temp) ndim = temp.ndim p = arr.expand(lev, ndim, axis=zdim) out = temp * ((p0 / p / punit)**kappa) return out
def ertelpv(uwnd, vwnd, temp, lon, lat, lev, xdim, ydim, zdim, cyclic=True, punit=100., sphere=True): """ Calculate Ertel potential vorticity. Hoskins, B.J., M.E. McIntyre and A.E. Robertson, 1985: On the use and significance of isentropic potential vorticity maps, `QJRMS`, 111, 877-946, <http://onlinelibrary.wiley.com/doi/10.1002/qj.49711147002/abstract> :param uwnd: ndarray, u component wind [m/s]. :param vwnd: ndarray, v component wind [m/s]. :param temp: ndarray, temperature [K]. :param lon: array_like, longitude [degrees]. :param lat: array_like, latitude [degrees]. :param lev: array_like, pressure level [punit*Pa]. :param xdim: west-east axis :param ydim: south-north axis :param zdim: vertical axis :param cyclic: west-east cyclic boundary :param punit: pressure level unit :param sphere: sphere coordinates. :return: """ u, v, t = np.ma.getdata(uwnd), np.ma.getdata(vwnd), np.ma.getdata(temp) mask = np.ma.getmask(uwnd) | np.ma.getmask(vwnd) | np.ma.getmask(temp) ndim = u.ndim # potential temperature theta = pottemp(t, lev, zdim, punit=punit) # partial derivation dthdp = dvardp(theta, lev, zdim, punit=punit) dudp = dvardp(u, lev, zdim, punit=punit) dvdp = dvardp(v, lev, zdim, punit=punit) dthdx = dvardx(theta, lon, lat, xdim, ydim, cyclic=cyclic, sphere=sphere) dthdy = dvardy(theta, lat, ydim, sphere=sphere) # absolute vorticity vor = rot(u, v, lon, lat, xdim, ydim, cyclic=cyclic, sphere=sphere) f = arr.expand(constants.earth_f(lat), ndim, axis=ydim) avor = f + vor out = -g * (avor * dthdp - (dthdx * dvdp - dthdy * dudp)) out = np.ma.array(out, mask=mask) out = arr.mrollaxis(out, ydim, 0) out[0, ...] = np.ma.masked out[-1, ...] = np.ma.masked out = arr.mrollaxis(out, 0, ydim + 1) return out
def tnflux3d(U, V, T, strm, lon, lat, lev, xdim, ydim, zdim, cyclic=True, limit=100, punit=100.): """ Takaya & Nakamura (2001) 计算等压面上的波活动度. Takaya, K and H. Nakamura, 2001: A formulation of a phase-independent wave-activity flux for stationary and migratory quasigeostrophic eddies on a zonally varying basic flow, `JAS`, 58, 608-627. http://journals.ametsoc.org/doi/abs/10.1175/1520-0469%282001%29058%3C0608%3AAFOAPI%3E2.0.CO%3B2 :param U: u component wind [m/s]. :param V: v component wind [m/s]. :param T: climate temperature [K]. :param strm: stream function bias [m^2/s] :param lon: longitude degree. :param lat: latitude degree. :param lev: level pressure. :param xdim: longitude dimension index. :param ydim: latitude dimension index. :param zdim: level dimension index. :param cyclic: east-west cyclic boundary. :param limit: :param punit: level pressure unit. :return: east-west, south-north, vertical component. """ U, V, T = np.asarray(U), np.asarray(V), np.asarray(T) ndim = U.ndim S = stability(T, lev, zdim, punit=punit) f = arr.expand(constants.earth_f(lat), ndim, axis=ydim) dstrmdx = dvardx(strm, lon, lat, xdim, ydim, cyclic=cyclic) dstrmdy = dvardy(strm, lat, ydim) dstrmdp = dvardp(strm, lev, zdim, punit=punit) d2strmdx2 = d2vardx2(strm, lon, lat, xdim, ydim, cyclic=cyclic) d2strmdy2 = d2vardy2(strm, lat, ydim) d2strmdxdy = dvardy(dstrmdx, lat, ydim) d2strmdxdp = dvardx(dstrmdp, lon, lat, xdim, ydim, cyclic=True) d2strmdydp = dvardy(dstrmdp, lat, ydim) tnx = U * (dstrmdx ** 2 - strm * d2strmdx2) + \ V * (dstrmdx * dstrmdy - strm * d2strmdxdy) tny = U * (dstrmdx * dstrmdy - strm * d2strmdxdy) + \ V * (dstrmdy ** 2 - strm * d2strmdy2) tnz = f**2 / S**2 * (U * (dstrmdx * dstrmdp - strm * d2strmdxdp) - V * (dstrmdy * dstrmdp - strm * d2strmdydp)) tnx = 0.5 * tnx / np.abs(U + 1j * V) tny = 0.5 * tny / np.abs(U + 1j * V) tnxy = np.sqrt(tnx**2 + tny**2) tnx = np.ma.asarray(tnx) tny = np.ma.asarray(tny) tnz = np.ma.asarray(tnz) tnx[(U < 0) | (tnxy > limit)] = np.ma.masked tny[(U < 0) | (tnxy > limit)] = np.ma.masked tnz[(U < 0) | (tnxy > limit)] = np.ma.masked return tnx, tny, tnz