def compute_tendencies_gm(grid, q_tendencies, q, Case, TS, tmp, tri_diag): i_gm, i_env, i_uds, i_sd = q.domain_idx() k_1 = grid.first_interior(Zmin()) dzi = grid.dzi α_1 = tmp['α_0'][k_1] ae_1 = q['a', i_env][k_1] slice_all_c = grid.slice_all(Center()) q_tendencies['q_tot', i_gm][slice_all_c] += [ tmp['mf_tend_q_tot'][k] + tmp['prec_src_q_tot', i_gm][k] * TS.Δti for k in grid.over_elems(Center()) ] q_tendencies['q_tot', i_gm][k_1] += Case.Sur.rho_q_tot_flux * dzi * α_1 / ae_1 q_tendencies['θ_liq', i_gm][slice_all_c] += [ tmp['mf_tend_θ_liq'][k] + tmp['prec_src_θ_liq', i_gm][k] * TS.Δti for k in grid.over_elems(Center()) ] q_tendencies['θ_liq', i_gm][k_1] += Case.Sur.rho_θ_liq_flux * dzi * α_1 / ae_1 q_tendencies['U', i_gm][k_1] += Case.Sur.rho_uflux * dzi * α_1 / ae_1 q_tendencies['V', i_gm][k_1] += Case.Sur.rho_vflux * dzi * α_1 / ae_1 return
def plot_state(self, grid, directory, filename, name_idx=None, i_sd=0, include_ghost=True): domain_range = grid.over_elems( Center()) if include_ghost else grid.over_elems_real(Center()) x = [grid.z_half[k] for k in domain_range] if name_idx == None: r = 0 for name_idx in self.var_names: y = [self[name_idx, i_sd][k] for k in domain_range] plt.plot(y, x, markershapes[r], label=friendly_name(name_idx)) plt.hold(True) r += 1 plt.title('state vector vs z') plt.xlabel('state vector') plt.ylabel('z') else: x_name = filename y = [self[name_idx, i_sd][k] for k in domain_range] plt.plot(y, x, markershapes[i_sd]) plt.title(x_name + ' vs z') plt.xlabel(x_name) plt.ylabel('z') plt.savefig(directory + filename) plt.close()
def update_GMV_MF(grid, q, TS, tmp): i_gm, i_env, i_uds, i_sd = q.domain_idx() slice_all_c = grid.slice_real(Center()) domain_c = grid.over_elems_real(Center()) for i in i_uds: tmp['mf_tmp', i][slice_all_c] = [((q['w', i].Mid(k) - q['w', i_env].Mid(k)) * tmp['ρ_0'][k] * q['a', i][k]) for k in domain_c] for k in domain_c: tmp['mf_θ_liq'][k] = np.sum([ tmp['mf_tmp', i][k] * (q['θ_liq', i][k] - q['θ_liq', i_env][k]) for i in i_uds ]) tmp['mf_q_tot'][k] = np.sum([ tmp['mf_tmp', i][k] * (q['q_tot', i][k] - q['q_tot', i_env][k]) for i in i_uds ]) tmp['mf_tend_θ_liq'][slice_all_c] = [ -tmp['α_0'][k] * grad(tmp['mf_θ_liq'].Cut(k), grid) for k in domain_c ] tmp['mf_tend_q_tot'][slice_all_c] = [ -tmp['α_0'][k] * grad(tmp['mf_q_tot'].Cut(k), grid) for k in domain_c ] return
def compute_inversion(grid, q, option, tmp, Ri_bulk_crit, temp_C): i_gm, i_env, i_uds, i_sd = q.domain_idx() maxgrad = 0.0 theta_rho_bl = temp_C.first_interior(grid) for k in grid.over_elems_real(Center()): q_tot = q['q_tot', i_gm][k] q_vap = q_tot - tmp['q_liq', i_gm][k] temp_C[k] = theta_rho_c(tmp['p_0'][k], tmp['T', i_gm][k], q_tot, q_vap) if option == 'theta_rho': for k in grid.over_elems_real(Center()): if temp_C[k] > theta_rho_bl: zi = grid.z_half[k] break elif option == 'thetal_maxgrad': for k in grid.over_elems_real(Center()): grad_TH = grad(q['θ_liq', i_gm].Dual(k), grid) if grad_TH > maxgrad: maxgrad = grad_TH zi = grid.z[k] elif option == 'critical_Ri': zi = compute_inversion_height(temp_C, q['U', i_gm], q['V', i_gm], grid, Ri_bulk_crit) else: print('INVERSION HEIGHT OPTION NOT RECOGNIZED') return zi
def assign(self, grid, name, value): if isinstance(name, tuple): for k in grid.over_elems(Center()): for v in name: for i in self.over_sub_domains(v): self[v, i][k] = value elif isinstance(name, str): for k in grid.over_elems(Center()): for i in self.over_sub_domains(name): self[name, i][k] = value
def calculate_radiation(self, tmp): """ see eq. 3 in Stevens et. al. 2005 DYCOMS paper """ # find z_i (level of 8.0 g/kg isoline of q_tot) k_1 = grid.first_interior(Zmin()) z_i = grid.z[k_1] for k in grid.over_elems_real(Center()): if (q['q_tot', i_gm][k] < 8.0 / 1000): idx_zi = k # will be used at cell edges z_i = grid.z[idx_zi] rhoi = tmp['ρ_0'][idx_zi] break self.f_rad = Full(grid) k_2 = grid.boundary(Zmax()) k_1 = 0 k_2 = grid.nzg - 1 # cloud-top cooling q_0 = 0.0 self.f_rad[k_2] = self.F0 * np.exp(-q_0) for k in range(k_2 - 1, -1, -1): q_0 += self.kappa * tmp['ρ_0'][k] * tmp['q_liq', i_gm][k] * grid.dz self.f_rad[k] = self.F0 * np.exp(-q_0) # cloud-base warming q_1 = 0.0 self.f_rad[k_1] += self.F1 * np.exp(-q_1) for k in range(1, k_2 + 1): q_1 += self.kappa * tmp['ρ_0'][k - 1] * tmp['q_liq', i_gm][k - 1] * grid.dz self.f_rad[k] += self.F1 * np.exp(-q_1) # cooling in free troposphere for k in range(k_1, k_2): if grid.z[k] > z_i: cbrt_z = np.cbrt(grid.z[k] - z_i) self.f_rad[ k] += rhoi * dycoms_cp * self.divergence * self.alpha_z * ( np.power(cbrt_z, 4) / 4.0 + z_i * cbrt_z) # condition at the top cbrt_z = np.cbrt(grid.z[k] + grid.dz - z_i) self.f_rad[ k_2] += rhoi * dycoms_cp * self.divergence * self.alpha_z * ( np.power(cbrt_z, 4) / 4.0 + z_i * cbrt_z) for k in grid.over_elems_real(Center()): self.dTdt[k] = -(self.f_rad[k + 1] - self.f_rad[k] ) / grid.dz / tmp['ρ_0'][k] / dycoms_cp return
def export_state(self, grid, directory, filename, ExportType=UseDat()): domain = grid.over_elems(Center()) headers = [ str(name) if len(self.over_sub_domains(name)) == 1 else str(name) + '_' + str(i_sd) for name in self.var_names for i_sd in self.over_sub_domains(name) ] headers = [friendly_name(s) for s in headers] n_vars = len(headers) n_elem = len(domain) data = np.array([ self[name, k, i_sd] for name in self.var_names for i_sd in self.over_sub_domains(name) for k in domain ]) data = data.reshape(n_elem, n_vars) z = grid.z[domain] # TODO: Clean up using numpy export data_all = [] data_all.append(z) data_all.append(data) file_name = str(directory + filename + '_vs_z.dat') with open(file_name, 'w') as f: f.write(', '.join(headers) + '\n') for k in domain: row = data_all[k] f.write('\t'.join(row)) return
def test(): grid = Grid(0.0, 1.0, 1000, 2) f = Half(grid) for i in range(1, 1000): for k in grid.over_elems_real(Center()): temp = f.Mid(k) f[k] += 1.0
def update(self, grid, q_new, q, q_tendencies, tmp, tmp_O2, UpdVar, Case, TS, tri_diag): i_gm, i_env, i_uds, i_sd = q.domain_idx() self.pre_compute_vars(grid, q, q_tendencies, tmp, tmp_O2, UpdVar, Case, TS, tri_diag) assign_new_to_values(grid, q_new, q, tmp) self.compute_prognostic_updrafts(grid, q_new, q, q_tendencies, tmp, UpdVar, Case, TS) update_cv_env(grid, q, q_tendencies, tmp, tmp_O2, TS, 'tke', tri_diag, self.tke_diss_coeff) update_cv_env(grid, q, q_tendencies, tmp, tmp_O2, TS, 'cv_θ_liq', tri_diag, self.tke_diss_coeff) update_cv_env(grid, q, q_tendencies, tmp, tmp_O2, TS, 'cv_q_tot', tri_diag, self.tke_diss_coeff) update_cv_env(grid, q, q_tendencies, tmp, tmp_O2, TS, 'cv_θ_liq_q_tot', tri_diag, self.tke_diss_coeff) update_sol_gm(grid, q_new, q, q_tendencies, TS, tmp, tri_diag) for k in grid.over_elems_real(Center()): q['U', i_gm][k] = q_new['U', i_gm][k] q['V', i_gm][k] = q_new['V', i_gm][k] q['θ_liq', i_gm][k] = q_new['θ_liq', i_gm][k] q['q_tot', i_gm][k] = q_new['q_tot', i_gm][k] q['q_rai', i_gm][k] = q_new['q_rai', i_gm][k] apply_gm_bcs(grid, q) return
def compute_entrainment_detrainment(grid, UpdVar, Case, tmp, q, entr_detr_fp, wstar, tke_ed_coeff, entrainment_factor, detrainment_factor): quadrature_order = 3 i_gm, i_env, i_uds, i_sd = q.domain_idx() compute_cloud_base_top_cover(grid, q, tmp, UpdVar) n_updrafts = len(i_uds) input_st = type('', (), {})() input_st.wstar = wstar input_st.b_mean = 0 input_st.dz = grid.dz input_st.zbl = compute_zbl_qt_grad(grid, q) for i in i_uds: input_st.zi = UpdVar[i].cloud_base for k in grid.over_elems_real(Center()): input_st.quadrature_order = quadrature_order input_st.z = grid.z_half[k] input_st.ml = tmp['l_mix'][k] input_st.b = tmp['B', i][k] input_st.w = q['w', i].Mid(k) input_st.af = q['a', i][k] input_st.tke = q['tke', i_env][k] input_st.qt_env = q['q_tot', i_env][k] input_st.q_liq_env = tmp['q_liq', i_env][k] input_st.θ_liq_env = q['θ_liq', i_env][k] input_st.b_env = tmp['B', i_env][k] input_st.w_env = q['w', i_env].values[k] input_st.θ_liq_up = q['θ_liq', i][k] input_st.qt_up = q['q_tot', i][k] input_st.q_liq_up = tmp['q_liq', i][k] input_st.env_Hvar = q['cv_θ_liq', i_env][k] input_st.env_QTvar = q['cv_q_tot', i_env][k] input_st.env_HQTcov = q['cv_θ_liq_q_tot', i_env][k] input_st.p0 = tmp['p_0'][k] input_st.alpha0 = tmp['α_0'][k] input_st.tke = q['tke', i_env][k] input_st.tke_ed_coeff = tke_ed_coeff input_st.L = 20000.0 # need to define the scale of the GCM grid resolution input_st.n_up = n_updrafts w_cut = q['w', i].DualCut(k) w_env_cut = q['w', i_env].DualCut(k) a_cut = q['a', i].Cut(k) a_env_cut = (1.0 - q['a', i].Cut(k)) aw_cut = a_cut * w_cut + a_env_cut * w_env_cut input_st.dwdz = grad(aw_cut, grid) if input_st.zbl - UpdVar[i].cloud_base > 0.0: input_st.poisson = np.random.poisson( grid.dz / ((input_st.zbl - UpdVar[i].cloud_base) / 10.0)) else: input_st.poisson = 0.0 ret = entr_detr_fp(input_st) tmp['entr_sc', i][k] = ret.entr_sc * entrainment_factor tmp['detr_sc', i][k] = ret.detr_sc * detrainment_factor return
def initialize_vars(self, grid, q, q_tendencies, tmp, tmp_O2, UpdVar, Case, TS, tri_diag): i_gm, i_env, i_uds, i_sd = q.domain_idx() self.zi = compute_inversion(grid, q, Case.inversion_option, tmp, self.Ri_bulk_crit, tmp['temp_C']) zs = self.zi self.wstar = compute_convective_velocity(Case.Sur.bflux, zs) ws = self.wstar ws3 = ws**3.0 us3 = Case.Sur.ustar**3.0 k_1 = grid.first_interior(Zmin()) cv_θ_liq_1 = q['cv_θ_liq', i_gm][k_1] cv_q_tot_1 = q['cv_q_tot', i_gm][k_1] cv_θ_liq_q_tot_1 = q['cv_θ_liq_q_tot', i_gm][k_1] reset_surface_covariance(grid, q, tmp, Case, ws) if ws > 0.0: for k in grid.over_elems(Center()): z = grid.z_half[k] temp = ws * 1.3 * np.cbrt(us3 / ws3 + 0.6 * z / zs) * np.sqrt( np.fmax(1.0 - z / zs, 0.0)) q['tke', i_gm][k] = temp q['cv_θ_liq', i_gm][k] = cv_θ_liq_1 * temp q['cv_q_tot', i_gm][k] = cv_q_tot_1 * temp q['cv_θ_liq_q_tot', i_gm][k] = cv_θ_liq_q_tot_1 * temp reset_surface_covariance(grid, q, tmp, Case, ws) compute_mixing_length(grid, q, tmp, Case.Sur.obukhov_length, self.zi, self.wstar) self.pre_compute_vars(grid, q, q_tendencies, tmp, tmp_O2, UpdVar, Case, TS, tri_diag) return
def update_cv_env(grid, q, q_tendencies, tmp, tmp_O2, TS, cv, tri_diag, tke_diss_coeff): i_gm, i_env, i_uds, i_sd = q.domain_idx() construct_tridiag_diffusion_O2(grid, q, tmp, TS, tri_diag, tke_diss_coeff) k_1 = grid.first_interior(Zmin()) slice_all_c = grid.slice_all(Center()) a_e = q['a', i_env] tri_diag.f[slice_all_c] = [ tmp['ρ_0'][k] * a_e[k] * q[cv, i_env][k] * TS.Δti + q_tendencies[cv, i_env][k] for k in grid.over_elems(Center()) ] tri_diag.f[k_1] = tmp['ρ_0'][k_1] * a_e[k_1] * q[ cv, i_env][k_1] * TS.Δti + q[cv, i_env][k_1] solve_tridiag_wrapper(grid, q[cv, i_env], tri_diag) return
def compute_cv_env_tendencies(grid, q_tendencies, tmp_O2, cv): i_gm, i_env, i_uds, i_sd = q_tendencies.domain_idx() k_1 = grid.first_interior(Zmin()) for k in grid.over_elems_real(Center()): q_tendencies[cv, i_env][k] = tmp_O2[cv]['press'][k] + tmp_O2[cv][ 'buoy'][k] + tmp_O2[cv]['shear'][k] + tmp_O2[cv]['entr_gain'][ k] + tmp_O2[cv]['rain_src'][k] q_tendencies[cv, i_env][k_1] = 0.0 return
def assign_new_to_values(grid, q_new, q, tmp): i_gm, i_env, i_uds, i_sd = q.domain_idx() slice_all_c = grid.slice_all(Center()) slice_all_n = grid.slice_all(Node()) for i in i_uds: q_new['w', i][slice_all_n] = [ q['w', i][k] for k in grid.over_elems(Node()) ] q_new['q_tot', i][slice_all_c] = [ q['q_tot', i][k] for k in grid.over_elems(Center()) ] q_new['q_rai', i][slice_all_c] = [ q['q_rai', i][k] for k in grid.over_elems(Center()) ] q_new['θ_liq', i][slice_all_c] = [ q['θ_liq', i][k] for k in grid.over_elems(Center()) ] return
def compute_covariance_detr(grid, q, tmp, tmp_O2, cv): i_gm, i_env, i_uds, i_sd = q.domain_idx() for k in grid.over_elems_real(Center()): tmp_O2[cv]['detr_loss'][k] = sum([ q['a', i][k] * np.fabs(q['w', i].Mid(k)) * tmp['entr_sc', i][k] for i in i_uds ]) tmp_O2[cv]['detr_loss'][k] *= tmp['ρ_0'][k] * q[cv, i_env][k] return
def coriolis_force(self, grid, q, q_tendencies): i_gm, i_env, i_uds, i_sd = q_tendencies.domain_idx() for k in grid.over_elems_real(Center()): q_tendencies['U', i_gm][k] -= self.coriolis_param * (self.vg[k] - q['V', i_gm][k]) q_tendencies['V', i_gm][k] += self.coriolis_param * (self.ug[k] - q['U', i_gm][k]) return
def compute_covariance_dissipation(grid, q, tmp, tmp_O2, tke_diss_coeff, cv): i_gm, i_env, i_uds, i_sd = q.domain_idx() ae = q['a', i_env] for k in grid.over_elems_real(Center()): l_mix = np.fmax(tmp['l_mix'][k], 1.0) tke_env = np.fmax(q['tke', i_env][k], 0.0) tmp_O2[cv]['dissipation'][k] = (tmp['ρ_0'][k] * ae[k] * q[cv, i_env][k] * pow(tke_env, 0.5) / l_mix * tke_diss_coeff) return
def free_convection_windspeed(self, grid, q, tmp): i_gm, i_env, i_uds, i_sd = tmp.domain_idx() theta_rho = Half(grid) for k in grid.over_elems(Center()): q_vap = q['q_tot', i_gm][k] - tmp['q_liq', i_gm][k] theta_rho[k] = theta_rho_c(tmp['p_0'][k], tmp['T', i_gm][k], q['q_tot', i_gm][k], q_vap) zi = compute_inversion_height(theta_rho, q['U', i_gm], q['V', i_gm], grid, self.Ri_bulk_crit) wstar = compute_convective_velocity(self.bflux, zi) # yair here zi in TRMM should be adjusted self.windspeed = np.sqrt(self.windspeed*self.windspeed + (1.2 *wstar)*(1.2 * wstar) ) return
def update_updraftvars(grid, q, tmp): i_gm, i_env, i_uds, i_sd = q.domain_idx() for i in i_uds: for k in grid.over_elems(Center()): s = tmp['prec_src_q_tot', i][k] q['q_tot', i][k] += s tmp['q_liq', i][k] += s q['q_rai', i][k] -= s q['θ_liq', i][k] += tmp['prec_src_θ_liq', i][k] return
def buoyancy(grid, q, tmp): i_gm, i_env, i_uds, i_sd = q.domain_idx() for i in i_uds: for k in grid.over_elems_real(Center()): if q['a', i][k] > 1e-3: q_tot = q['q_tot', i][k] q_vap = q_tot - tmp['q_liq', i][k] T = tmp['T', i][k] α_i = alpha_c(tmp['p_0'][k], T, q_tot, q_vap) tmp['B', i][k] = buoyancy_c(tmp['α_0'][k], α_i) else: tmp['B', i][k] = tmp['B', i_env][k] # Subtract grid mean buoyancy for k in grid.over_elems_real(Center()): tmp['B', i_gm][k] = np.sum([q['a', i][k] * tmp['B', i][k] for i in i_sd]) for i in i_sd: tmp['B', i][k] -= tmp['B', i_gm][k] return
def compute_sources(grid, q, tmp, max_supersaturation): i_gm, i_env, i_uds, i_sd = tmp.domain_idx() for i in i_uds: for k in grid.over_elems(Center()): q_tot = q['q_tot', i][k] q_tot = tmp['q_liq', i][k] T = tmp['T', i][k] p_0 = tmp['p_0'][k] tmp_qr = acnv_instant(q_tot, q_tot, max_supersaturation, T, p_0) tmp['prec_src_θ_liq', i][k] = rain_source_to_thetal(p_0, T, q_tot, q_tot, 0.0, tmp_qr) tmp['prec_src_q_tot', i][k] = -tmp_qr for k in grid.over_elems(Center()): tmp['prec_src_θ_liq', i_gm][k] = np.sum( [tmp['prec_src_θ_liq', i][k] * q['a', i][k] for i in i_sd]) tmp['prec_src_q_tot', i_gm][k] = np.sum( [tmp['prec_src_q_tot', i][k] * q['a', i][k] for i in i_sd]) return
def assign_values_to_new(grid, q, q_new, tmp): i_gm, i_env, i_uds, i_sd = q.domain_idx() for k in grid.over_elems(Center()): for i in i_uds: q['w', i][k] = q_new['w', i][k] q['q_tot', i][k] = q_new['q_tot', i][k] q['q_rai', i][k] = q_new['q_rai', i][k] q['θ_liq', i][k] = q_new['θ_liq', i][k] q['a', i][k] = q_new['a', i][k] q['a', i_env][k] = 1.0 - np.sum([q_new['a', i][k] for i in i_uds]) return
def compute_zbl_qt_grad(grid, q): i_gm, i_env, i_uds, i_sd = q.domain_idx() # computes inversion height as z with max gradient of q_tot zbl_q_tot = 0.0 q_tot_grad = 0.0 for k in grid.over_elems_real(Center()): q_tot_grad_new = grad(q['q_tot', i_gm].Dual(k), grid) if np.fabs(q_tot_grad) > q_tot_grad: q_tot_grad = np.fabs(q_tot_grad_new) zbl_q_tot = grid.z_half[k] return zbl_q_tot
def eos_update_SA_mean(grid, q, in_Env, tmp, max_supersaturation): i_gm, i_env, i_uds, i_sd = q.domain_idx() for k in grid.over_elems_real(Center()): p_0_k = tmp['p_0'][k] T, q_liq = eos(p_0_k, q['q_tot', i_env][k], q['θ_liq', i_env][k]) mph = microphysics(T, q_liq, p_0_k, q['q_tot', i_env][k], max_supersaturation, in_Env) update_env(q, tmp, k, mph.T, mph.θ_liq, mph.q_tot, mph.q_liq, mph.q_rai, mph.alpha) update_cloud_dry(k, mph.T, mph.θ, mph.q_tot, mph.q_liq, mph.q_vap, tmp) return
def compute_covariance_interdomain_src(grid, q, tmp, tmp_O2, ϕ, ψ, cv, tke_factor, interp_func): i_gm, i_env, i_uds, i_sd = q.domain_idx() for k in grid.over_elems(Center()): tmp_O2[cv]['interdomain'][k] = 0.0 for i in i_uds: Δϕ = interp_func(q[ϕ, i], k) - interp_func(q[ϕ, i_env], k) Δψ = interp_func(q[ψ, i], k) - interp_func(q[ψ, i_env], k) tmp_O2[cv]['interdomain'][k] += tke_factor * q['a', i][k] * ( 1.0 - q['a', i][k]) * Δϕ * Δψ return
def compute_eddy_diffusivities_similarity_Siebesma2007(grid, Case, tmp, zi, wstar, prandtl_number): ustar = Case.Sur.ustar for k in grid.over_elems_real(Center()): zzi = grid.z_half[k] / zi tmp['K_h'][k] = 0.0 tmp['K_m'][k] = 0.0 if zzi <= 1.0 and not (wstar < 1e-6): tmp['K_h'][k] = vkb * ((ustar / wstar)**3.0 + 39.0 * vkb * zzi)**( 1.0 / 3.0) * zzi * (1.0 - zzi) * (1.0 - zzi) * wstar * zi tmp['K_m'][k] = tmp['K_h'][k] * prandtl_number return
def compute_cv_gm(grid, q, ϕ, ψ, cv, tke_factor, interp_func): i_gm, i_env, i_uds, i_sd = q.domain_idx() ae = q['a', i_env] for k in grid.over_elems(Center()): Δϕ = interp_func(q[ϕ, i_env], k) - interp_func(q[ϕ, i_gm], k) Δψ = interp_func(q[ψ, i_env], k) - interp_func(q[ψ, i_gm], k) q[cv, i_gm][k] = tke_factor * ae[k] * Δϕ * Δψ + ae[k] * q[cv, i_env][k] for i in i_uds: Δϕ = interp_func(q[ϕ, i], k) - interp_func(q[ϕ, i_gm], k) Δψ = interp_func(q[ψ, i], k) - interp_func(q[ψ, i_gm], k) q[cv, i_gm][k] += tke_factor * q['a', i][k] * Δϕ * Δψ return
def compute_covariance_entr(grid, q, tmp, tmp_O2, ϕ, ψ, cv, tke_factor, interp_func): i_gm, i_env, i_uds, i_sd = q.domain_idx() for k in grid.over_elems_real(Center()): tmp_O2[cv]['entr_gain'][k] = 0.0 for i in i_uds: Δϕ = interp_func(q[ϕ, i], k) - interp_func(q[ϕ, i_env], k) Δψ = interp_func(q[ψ, i], k) - interp_func(q[ψ, i_env], k) tmp_O2[cv]['entr_gain'][k] += tke_factor * q['a', i][k] * np.fabs( q['w', i].Mid(k)) * tmp['detr_sc', i][k] * Δϕ * Δψ tmp_O2[cv]['entr_gain'][k] *= tmp['ρ_0'][k] return
def compute_tke_buoy(grid, q, tmp, tmp_O2, cv): i_gm, i_env, i_uds, i_sd = q.domain_idx() ae = q['a', i_env] # Note that source terms at the first interior point are not really used because that is where tke boundary condition is # enforced (according to MO similarity). Thus here I am being sloppy about lowest grid point for k in grid.over_elems_real(Center()): q_tot_dry = tmp['q_tot_dry'][k] θ_dry = tmp['θ_dry'][k] t_cloudy = tmp['t_cloudy'][k] q_vap_cloudy = tmp['q_vap_cloudy'][k] q_tot_cloudy = tmp['q_tot_cloudy'][k] θ_cloudy = tmp['θ_cloudy'][k] p_0 = tmp['p_0'][k] lh = latent_heat(t_cloudy) cpm = cpm_c(q_tot_cloudy) grad_θ_liq = grad_neg(q['θ_liq', i_env].Cut(k), grid) grad_q_tot = grad_neg(q['q_tot', i_env].Cut(k), grid) prefactor = Rd * exner_c(p_0) / p_0 d_alpha_θ_liq_dry = prefactor * (1.0 + (eps_vi - 1.0) * q_tot_dry) d_alpha_q_tot_dry = prefactor * θ_dry * (eps_vi - 1.0) CF_env = tmp['CF'][k] if CF_env > 0.0: d_alpha_θ_liq_cloudy = ( prefactor * (1.0 + eps_vi * (1.0 + lh / Rv / t_cloudy) * q_vap_cloudy - q_tot_cloudy) / (1.0 + lh * lh / cpm / Rv / t_cloudy / t_cloudy * q_vap_cloudy)) d_alpha_q_tot_cloudy = (lh / cpm / t_cloudy * d_alpha_θ_liq_cloudy - prefactor) * θ_cloudy else: d_alpha_θ_liq_cloudy = 0.0 d_alpha_q_tot_cloudy = 0.0 d_alpha_θ_liq_total = (CF_env * d_alpha_θ_liq_cloudy + (1.0 - CF_env) * d_alpha_θ_liq_dry) d_alpha_q_tot_total = (CF_env * d_alpha_q_tot_cloudy + (1.0 - CF_env) * d_alpha_q_tot_dry) K_h_k = tmp['K_h'][k] term_1 = -K_h_k * grad_θ_liq * d_alpha_θ_liq_total term_2 = -K_h_k * grad_q_tot * d_alpha_q_tot_total # TODO - check tmp_O2[cv]['buoy'][k] = g / tmp['α_0'][k] * ae[k] * tmp['ρ_0'][k] * ( term_1 + term_2) return
def compute_grid_means(grid, q, tmp): i_gm, i_env, i_uds, i_sd = q.domain_idx() ae = q['a', i_env] for k in grid.over_elems_real(Center()): tmp['q_liq', i_gm][k] = np.sum( [q['a', i][k] * tmp['q_liq', i][k] for i in i_sd]) q['q_rai', i_gm][k] = np.sum([q['a', i][k] * q['q_rai', i][k] for i in i_sd]) tmp['T', i_gm][k] = np.sum([q['a', i][k] * tmp['T', i][k] for i in i_sd]) tmp['B', i_gm][k] = np.sum([q['a', i][k] * tmp['B', i][k] for i in i_sd]) return