def gms_like_ratio(weights, tracer, dp): """Compute ratio of integrals in the style of gross moist stability.""" # Integrate weights over lower tropospheric layer dp = to_pascal(dp) denominator = field_vert_int_max(weights, dp) # Integrate tracer*weights over whole column and divide. numerator = np.sum(weights*tracer*dp, axis=-3) / grav return numerator / denominator
def gms_like_ratio(weights, tracer, dp): """Compute ratio of integrals in the style of gross moist stability.""" # Integrate weights over lower tropospheric layer dp = to_pascal(dp) denominator = field_vert_int_max(weights, dp) # Integrate tracer*weights over whole column and divide. numerator = np.sum(weights * tracer * dp, axis=-3) / grav return numerator / denominator
def field_vert_int_max(arr, dp): """Maximum magnitude of integral of a field from surface up.""" dp = to_pascal(dp) # 2015-05-15: Problem: Sigma data indexing starts at TOA, while pressure # data indexing starts at 1000 hPa. So for now only do for # sigma data and flip array direction to start from sfc. arr_dp_g = (arr*dp)[::-1] / grav # Input array dimensions are assumed ([time dims,] level, lat, lon). pos_max = np.amax(np.cumsum(arr_dp_g, axis=0), axis=-3) neg_max = np.amin(np.cumsum(arr_dp_g, axis=0), axis=-3) # Flip sign because integrating from p_sfc up, i.e. with dp negative. return -1*np.where(pos_max > -neg_max, pos_max, neg_max)
def field_vert_int_max(arr, dp): """Maximum magnitude of integral of a field from surface up.""" dp = to_pascal(dp) # 2015-05-15: Problem: Sigma data indexing starts at TOA, while pressure # data indexing starts at 1000 hPa. So for now only do for # sigma data and flip array direction to start from sfc. arr_dp_g = (arr * dp)[::-1] / grav # Input array dimensions are assumed ([time dims,] level, lat, lon). pos_max = np.amax(np.cumsum(arr_dp_g, axis=0), axis=-3) neg_max = np.amin(np.cumsum(arr_dp_g, axis=0), axis=-3) # Flip sign because integrating from p_sfc up, i.e. with dp negative. return -1 * np.where(pos_max > -neg_max, pos_max, neg_max)
def msf(lats, levs, v): """Meridional mass streamfunction.""" # Compute half level boundaries and widths. p_top = 5. p_bot = 1005. p_half = 0.5*(levs[1:] + levs[:-1]) p_half = np.insert(np.append(p_half, p_top), 0, p_bot) dp = to_pascal(p_half[:-1] - p_half[1:])[np.newaxis, ::-1, np.newaxis] geom_factor = (2.*np.pi*r_e/grav * np.cos(np.deg2rad(lats))[np.newaxis, np.newaxis, :]) # Integrate from TOA down to surface. msf_ = geom_factor * np.cumsum(v.mean(axis=-1) * dp, axis=1)[::-1] # Average the values calculated at half levels; flip sign by convention. msf_[:,:-1] = -0.5*(msf_[:,1:] + msf_[:,:-1]) # Uppermost level goes to 0 hPa (so divide by 2); surface value is zero. msf_[:,-1]*=0.5 msf_[:,0] = 0. return msf_
def msf(lats, levs, v): """Meridional mass streamfunction.""" # Compute half level boundaries and widths. p_top = 5. p_bot = 1005. p_half = 0.5 * (levs[1:] + levs[:-1]) p_half = np.insert(np.append(p_half, p_top), 0, p_bot) dp = to_pascal(p_half[:-1] - p_half[1:])[np.newaxis, ::-1, np.newaxis] geom_factor = (2. * np.pi * r_e / grav * np.cos(np.deg2rad(lats))[np.newaxis, np.newaxis, :]) # Integrate from TOA down to surface. msf_ = geom_factor * np.cumsum(v.mean(axis=-1) * dp, axis=1)[::-1] # Average the values calculated at half levels; flip sign by convention. msf_[:, :-1] = -0.5 * (msf_[:, 1:] + msf_[:, :-1]) # Uppermost level goes to 0 hPa (so divide by 2); surface value is zero. msf_[:, -1] *= 0.5 msf_[:, 0] = 0. return msf_