def initial_state(): rhod = arr_t([1.]) th = arr_t([300.]) rv = arr_t([0.02]) T = common.T(th[0], rhod[0]) p = arr_t([common.p(rhod[0], rv[0], T)]) return rhod, th, rv, p
def supersat_state(): rhod = arr_t([1. ]) th = arr_t([300.]) rv = arr_t([0.0091]) T = common.T(th[0], rhod[0]) p = arr_t([common.p(rhod[0], rv[0], T)]) return rhod, th, rv, p
def supersat_state(): rhod = arr_t([1.]) th = arr_t([300.]) rv = arr_t([0.0091]) T = common.T(th[0], rhod[0]) p = arr_t([common.p(rhod[0], rv[0], T)]) return rhod, th, rv, p
def initial_state(): rhod = arr_t([1. ]) th = arr_t([300.]) rv = arr_t([0.02]) T = common.T(th[0], rhod[0]) p = arr_t([common.p(rhod[0], rv[0], T)]) return rhod, th, rv, p
def initial_state(): # a little below saturation rhod = arr_t([1.1]) th = arr_t([305.]) rv = arr_t([0.0085]) T = common.T(th[0], rhod[0]) p = arr_t([common.p(rhod[0], rv[0], T)]) return rhod, th, rv, p
def initial_state(): # a little below saturation rhod = arr_t([1.1 ]) th = arr_t([305.]) rv = arr_t([0.0085]) T = common.T(th[0], rhod[0]) p = arr_t([common.p(rhod[0], rv[0], T)]) return rhod, th, rv, p
def test_adj_cellwise(init_sup_sat, r_eps = r_eps_def): opts.r_eps = r_eps print "[standard adj_cellwise]" rhod, th, rv, rc, rr, dt = initial_state(init_sup_sat) blk_1m.adj_cellwise(opts, rhod, th, rv, rc, rr, dt) T = common.T(th[0], rhod[0]) p = common.p(rhod[0], rv[0], T) ss = supersaturation(T, p, rv[0]) print "final supersaturation", ss, th[0], rv[0] return ss
def test_adj_cellwise(init_sup_sat, r_eps=r_eps_def): opts.r_eps = r_eps print("[standard adj_cellwise]") rhod, th, rv, rc, rr, dt = initial_state(init_sup_sat) blk_1m.adj_cellwise(opts, rhod, th, rv, rc, rr, dt) T = common.T(th[0], rhod[0]) p = common.p(rhod[0], rv[0], T) ss = supersaturation(T, p, rv[0]) print("final supersaturation", ss, th[0], rv[0]) return ss
def test_adj_cellwise_nwtrph(init_sup_sat, nwtrph_iters = nwtrph_iters_def): opts.nwtrph_iters = nwtrph_iters print "[nwtrph adj_cellwise]" rhod, th, rv, rc, rr, dt = initial_state(init_sup_sat) # define pressure consistent with adj_cellwise to compare results p = arr_t([common.p(rhod[0], rv[0], common.T(th[0], rhod[0]))]) #nwtrph requires th_std input th_std = arr_t([common.th_dry2std(th[0], rv[0])]) blk_1m.adj_cellwise_nwtrph(opts, p, th_std, rv, rc, dt) T = common.exner(p[0]) * th_std[0] ss = supersaturation(T, p[0], rv[0]) print "final supersaturation", ss, th_std[0], rv[0] return ss
def test_adj_cellwise_constp(init_sup_sat, r_eps = r_eps_def): opts.r_eps = r_eps print "[constp adj_cellwise]" rhod, th, rv, rc, rr, dt = initial_state(init_sup_sat) # define pressure consistent with adj_cellwise to compare results p = arr_t([common.p(rhod[0], rv[0], common.T(th[0], rhod[0]))]) #constp requires th_std input th_std = arr_t([common.th_dry2std(th[0], rv[0])]) blk_1m.adj_cellwise_constp(opts, rhod, p, th_std, rv, rc, rr, dt) T = common.exner(p[0]) * th_std[0] ss = supersaturation(T, p[0], rv[0]) print "final supersaturation", ss, th_std[0], rv[0] return ss
def test_adj_cellwise_nwtrph(init_sup_sat, nwtrph_iters=nwtrph_iters_def): opts.nwtrph_iters = nwtrph_iters print("[nwtrph adj_cellwise]") rhod, th, rv, rc, rr, dt = initial_state(init_sup_sat) # define pressure consistent with adj_cellwise to compare results p = arr_t([common.p(rhod[0], rv[0], common.T(th[0], rhod[0]))]) #nwtrph requires th_std input th_std = arr_t([common.th_dry2std(th[0], rv[0])]) blk_1m.adj_cellwise_nwtrph(opts, p, th_std, rv, rc, dt) T = common.exner(p[0]) * th_std[0] ss = supersaturation(T, p[0], rv[0]) print("final supersaturation", ss, th_std[0], rv[0]) return ss
def initial_state(init_sup_sat): rhod = arr_t([1. ]) th = arr_t([300.]) if init_sup_sat: rv = arr_t([0.02]) else: rv = arr_t([0.002]) rc = arr_t([0.015]) rr = arr_t([0. ]) dt = 1 T = common.T(th[0], rhod[0]) p = common.p(rhod[0], rv[0], T) ss = supersaturation(T, p, rv[0]) print "initial supersaturation", ss return rhod, th, rv, rc, rr, dt
def initial_state(init_sup_sat): rhod = arr_t([1.]) th = arr_t([300.]) if init_sup_sat: rv = arr_t([0.02]) else: rv = arr_t([0.002]) rc = arr_t([0.015]) rr = arr_t([0.]) dt = 1 T = common.T(th[0], rhod[0]) p = common.p(rhod[0], rv[0], T) ss = supersaturation(T, p, rv[0]) print("initial supersaturation", ss) return rhod, th, rv, rc, rr, dt
def parcel( dt=.1, z_max=200., w=1., T_0=300., p_0=101300., r_0=-1., RH_0=-1., #if none specified, the default will be r_0=.022, outfile="test.nc", pprof="pprof_piecewise_const_rhod", outfreq=100, sd_conc=64, aerosol='{"ammonium_sulfate": {"kappa": 0.61, "mean_r": [0.02e-6], "gstdev": [1.4], "n_tot": [60.0e6]}}', out_bin='{"radii": {"rght": 0.0001, "moms": [0], "drwt": "wet", "nbin": 1, "lnli": "log", "left": 1e-09}}', SO2_g=0., O3_g=0., H2O2_g=0., CO2_g=0., HNO3_g=0., NH3_g=0., chem_dsl=False, chem_dsc=False, chem_rct=False, chem_rho=1.8e3, sstp_cond=1, sstp_chem=1, wait=0): """ Args: dt (Optional[float]): timestep [s] z_max (Optional[float]): maximum vertical displacement [m] w (Optional[float]): updraft velocity [m/s] T_0 (Optional[float]): initial temperature [K] p_0 (Optional[float]): initial pressure [Pa] r_0 (Optional[float]): initial water vapour mass mixing ratio [kg/kg] RH_0 (Optional[float]): initial relative humidity outfile (Optional[string]): output netCDF file name outfreq (Optional[int]): output interval (in number of time steps) sd_conc (Optional[int]): number of moving bins (super-droplets) aerosol (Optional[json str]): dict of dicts defining aerosol distribution, e.g.: {"ammonium_sulfate": {"kappa": 0.61, "mean_r": [0.02e-6, 0.07e-7], "gstdev": [1.4, 1.2], "n_tot": [120.0e6, 80.0e6]} "gccn" : {"kappa": 1.28, "mean_r": [2e-6], "gstdev": [1.6], "n_tot": [1e2]}} where kappa - hygroscopicity parameter (see doi:10.5194/acp-7-1961-2007) mean_r - lognormal distribution mean radius [m] (list if multimodal distribution) gstdev - lognormal distribution geometric standard deviation (list if multimodal distribution) n_tot - lognormal distribution total concentration under standard conditions (T=20C, p=1013.25 hPa, rv=0) [m^-3] (list if multimodal distribution) out_bin (Optional[json str]): dict of dicts defining spectrum diagnostics, e.g.: {"radii": {"rght": 0.0001, "moms": [0], "drwt": "wet", "nbin": 26, "lnli": "log", "left": 1e-09}, "cloud": {"rght": 2.5e-05, "moms": [0, 1, 2, 3], "drwt": "wet", "nbin": 49, "lnli": "lin", "left": 5e-07}} will generate five output spectra: - 0-th spectrum moment for 26 bins spaced logarithmically between 0 and 1e-4 m for dry radius - 0,1,2 & 3-rd moments for 49 bins spaced linearly between .5e-6 and 25e-6 for wet radius It can also define spectrum diagnostics for chemical compounds, e.g.: {"chem" : {"rght": 1e-6, "left": 1e-10, "drwt": "dry", "lnli": "log", "nbin": 100, "moms": ["S_VI", "NH4_a"]}} will output the total mass of H2SO4 and NH4 ions in each sizedistribution bin Valid "moms" for chemistry are: "O3_a", "H2O2_a", "H", "SO2_a", "S_VI", "CO2_a", "NH3_a", "HNO3_a", SO2_g (Optional[float]): initial SO2 gas mixing ratio [kg / kg dry air] O3_g (Optional[float]): initial O3 gas mixing ratio [kg / kg dry air] H2O2_g (Optional[float]): initial H2O2 gas mixing ratio [kg / kg dry air] CO2_g (Optional[float]): initial CO2 gas mixing ratio [kg / kg dry air] NH3_g (Optional[float]): initial NH3 gas mixing ratio [kg / kg dry air] HNO3_g (Optional[float]): initial HNO3 gas mixing ratio [kg / kg dry air] chem_dsl (Optional[bool]): on/off for dissolving chem species into droplets chem_dsc (Optional[bool]): on/off for dissociation of chem species in droplets chem_rct (Optional[bool]): on/off for oxidation of S_IV to S_VI pprof (Optional[string]): method to calculate pressure profile used to calculate dry air density that is used by the super-droplet scheme valid options are: pprof_const_th_rv, pprof_const_rhod, pprof_piecewise_const_rhod wait (Optional[float]): number of timesteps to run parcel model with vertical velocity=0 at the end of simulation (added for testing) """ # packing function arguments into "opts" dictionary args, _, _, _ = inspect.getargvalues(inspect.currentframe()) opts = dict(zip(args, [locals()[k] for k in args])) # parsing json specification of output spectra spectra = json.loads(opts["out_bin"]) # parsing json specification of init aerosol spectra aerosol = json.loads(opts["aerosol"]) # default water content if ((opts["r_0"] < 0) and (opts["RH_0"] < 0)): print "both r_0 and RH_0 negative, using default r_0 = 0.022" r_0 = .022 # water coontent specified with RH if ((opts["r_0"] < 0) and (opts["RH_0"] >= 0)): r_0 = common.eps * opts["RH_0"] * common.p_vs(T_0) / ( p_0 - opts["RH_0"] * common.p_vs(T_0)) # sanity checks for arguments _arguments_checking(opts, spectra, aerosol) th_0 = T_0 * (common.p_1000 / p_0)**(common.R_d / common.c_pd) nt = int(z_max / (w * dt)) state = { "t": 0, "z": 0, "r_v": np.array([r_0]), "p": p_0, "th_d": np.array([common.th_std2dry(th_0, r_0)]), "rhod": np.array([common.rhod(p_0, th_0, r_0)]), "T": None, "RH": None } if opts["chem_dsl"] or opts["chem_dsc"] or opts["chem_rct"]: for key in _Chem_g_id.iterkeys(): state.update({key: np.array([opts[key]])}) info = { "RH_max": 0, "libcloud_Git_revision": libcloud_version, "parcel_Git_revision": parcel_version } micro = _micro_init(aerosol, opts, state, info) with _output_init(micro, opts, spectra) as fout: # adding chem state vars if micro.opts_init.chem_switch: state.update({ "SO2_a": 0., "O3_a": 0., "H2O2_a": 0., }) state.update({"CO2_a": 0., "HNO3_a": 0.}) micro.diag_all() # selecting all particles micro.diag_chem(_Chem_a_id["NH3_a"]) state.update({"NH3_a": np.frombuffer(micro.outbuf())[0]}) # t=0 : init & save _output(fout, opts, micro, state, 0, spectra) # timestepping for it in range(1, nt + 1): # diagnostics # the reasons to use analytic solution: # - independent of dt # - same as in 2D kinematic model state["z"] += w * dt state["t"] = it * dt # pressure if pprof == "pprof_const_th_rv": # as in icicle model p_hydro = _p_hydro_const_th_rv(state["z"], p_0, th_0, r_0) elif pprof == "pprof_const_rhod": # as in Grabowski and Wang 2009 rho = 1.13 # kg/m3 1.13 state["p"] = _p_hydro_const_rho(state["z"], p_0, rho) elif pprof == "pprof_piecewise_const_rhod": # as in Grabowski and Wang 2009 but calculating pressure # for rho piecewise constant per each time step state["p"] = _p_hydro_const_rho(w * dt, state["p"], state["rhod"][0]) else: raise Exception( "pprof should be pprof_const_th_rv, pprof_const_rhod, or pprof_piecewise_const_rhod" ) # dry air density if pprof == "pprof_const_th_rv": state["rhod"][0] = common.rhod(p_hydro, th_0, r_0) state["p"] = common.p( state["rhod"][0], state["r_v"][0], common.T(state["th_d"][0], state["rhod"][0])) else: state["rhod"][0] = common.rhod( state["p"], common.th_dry2std(state["th_d"][0], state["r_v"][0]), state["r_v"][0]) # microphysics _micro_step(micro, state, info, opts, it, fout) # TODO: only if user wants to stop @ RH_max #if (state["RH"] < info["RH_max"]): break # output if (it % outfreq == 0): print str(round(it / (nt * 1.) * 100, 2)) + " %" rec = it / outfreq _output(fout, opts, micro, state, rec, spectra) _save_attrs(fout, info) _save_attrs(fout, opts) if wait != 0: for it in range(nt + 1, nt + wait): state["t"] = it * dt _micro_step(micro, state, info, opts, it, fout) if (it % outfreq == 0): rec = it / outfreq _output(fout, opts, micro, state, rec, spectra)
def test_pressure(arg, epsilon = 0.01): rho_d = anpy.density_dry(**arg) press_md = common.p(rho_d, arg["rv"], arg["T"]) assert abs(arg["press"] - press_md) <= epsilon * arg["press"]
def parcel(dt=.1, z_max=200., w=1., T_0=300., p_0=101300., r_0=-1., RH_0=-1., #if none specified, the default will be r_0=.022, outfile="test.nc", pprof="pprof_piecewise_const_rhod", outfreq=100, sd_conc=64, aerosol = '{"ammonium_sulfate": {"kappa": 0.61, "mean_r": [0.02e-6], "gstdev": [1.4], "n_tot": [60.0e6]}}', out_bin = '{"radii": {"rght": 0.0001, "moms": [0], "drwt": "wet", "nbin": 1, "lnli": "log", "left": 1e-09}}', SO2_g = 0., O3_g = 0., H2O2_g = 0., CO2_g = 0., HNO3_g = 0., NH3_g = 0., chem_dsl = False, chem_dsc = False, chem_rct = False, chem_rho = 1.8e3, sstp_cond = 1, sstp_chem = 1, wait = 0 ): """ Args: dt (Optional[float]): timestep [s] z_max (Optional[float]): maximum vertical displacement [m] w (Optional[float]): updraft velocity [m/s] T_0 (Optional[float]): initial temperature [K] p_0 (Optional[float]): initial pressure [Pa] r_0 (Optional[float]): initial water vapour mass mixing ratio [kg/kg] RH_0 (Optional[float]): initial relative humidity outfile (Optional[string]): output netCDF file name outfreq (Optional[int]): output interval (in number of time steps) sd_conc (Optional[int]): number of moving bins (super-droplets) aerosol (Optional[json str]): dict of dicts defining aerosol distribution, e.g.: {"ammonium_sulfate": {"kappa": 0.61, "mean_r": [0.02e-6, 0.07e-7], "gstdev": [1.4, 1.2], "n_tot": [120.0e6, 80.0e6]} "gccn" : {"kappa": 1.28, "mean_r": [2e-6], "gstdev": [1.6], "n_tot": [1e2]}} where kappa - hygroscopicity parameter (see doi:10.5194/acp-7-1961-2007) mean_r - lognormal distribution mean radius [m] (list if multimodal distribution) gstdev - lognormal distribution geometric standard deviation (list if multimodal distribution) n_tot - lognormal distribution total concentration under standard conditions (T=20C, p=1013.25 hPa, rv=0) [m^-3] (list if multimodal distribution) out_bin (Optional[json str]): dict of dicts defining spectrum diagnostics, e.g.: {"radii": {"rght": 0.0001, "moms": [0], "drwt": "wet", "nbin": 26, "lnli": "log", "left": 1e-09}, "cloud": {"rght": 2.5e-05, "moms": [0, 1, 2, 3], "drwt": "wet", "nbin": 49, "lnli": "lin", "left": 5e-07}} will generate five output spectra: - 0-th spectrum moment for 26 bins spaced logarithmically between 0 and 1e-4 m for dry radius - 0,1,2 & 3-rd moments for 49 bins spaced linearly between .5e-6 and 25e-6 for wet radius It can also define spectrum diagnostics for chemical compounds, e.g.: {"chem" : {"rght": 1e-6, "left": 1e-10, "drwt": "dry", "lnli": "log", "nbin": 100, "moms": ["S_VI", "NH4_a"]}} will output the total mass of H2SO4 and NH4 ions in each sizedistribution bin Valid "moms" for chemistry are: "O3_a", "H2O2_a", "H", "SO2_a", "S_VI", "CO2_a", "NH3_a", "HNO3_a", SO2_g (Optional[float]): initial SO2 gas mixing ratio [kg / kg dry air] O3_g (Optional[float]): initial O3 gas mixing ratio [kg / kg dry air] H2O2_g (Optional[float]): initial H2O2 gas mixing ratio [kg / kg dry air] CO2_g (Optional[float]): initial CO2 gas mixing ratio [kg / kg dry air] NH3_g (Optional[float]): initial NH3 gas mixing ratio [kg / kg dry air] HNO3_g (Optional[float]): initial HNO3 gas mixing ratio [kg / kg dry air] chem_dsl (Optional[bool]): on/off for dissolving chem species into droplets chem_dsc (Optional[bool]): on/off for dissociation of chem species in droplets chem_rct (Optional[bool]): on/off for oxidation of S_IV to S_VI pprof (Optional[string]): method to calculate pressure profile used to calculate dry air density that is used by the super-droplet scheme valid options are: pprof_const_th_rv, pprof_const_rhod, pprof_piecewise_const_rhod wait (Optional[float]): number of timesteps to run parcel model with vertical velocity=0 at the end of simulation (added for testing) """ # packing function arguments into "opts" dictionary args, _, _, _ = inspect.getargvalues(inspect.currentframe()) opts = dict(zip(args, [locals()[k] for k in args])) # parsing json specification of output spectra spectra = json.loads(opts["out_bin"]) # parsing json specification of init aerosol spectra aerosol = json.loads(opts["aerosol"]) # default water content if ((opts["r_0"] < 0) and (opts["RH_0"] < 0)): print "both r_0 and RH_0 negative, using default r_0 = 0.022" r_0 = .022 # water coontent specified with RH if ((opts["r_0"] < 0) and (opts["RH_0"] >= 0)): r_0 = common.eps * opts["RH_0"] * common.p_vs(T_0) / (p_0 - opts["RH_0"] * common.p_vs(T_0)) # sanity checks for arguments _arguments_checking(opts, spectra, aerosol) th_0 = T_0 * (common.p_1000 / p_0)**(common.R_d / common.c_pd) nt = int(z_max / (w * dt)) state = { "t" : 0, "z" : 0, "r_v" : np.array([r_0]), "p" : p_0, "th_d" : np.array([common.th_std2dry(th_0, r_0)]), "rhod" : np.array([common.rhod(p_0, th_0, r_0)]), "T" : None, "RH" : None } if opts["chem_dsl"] or opts["chem_dsc"] or opts["chem_rct"]: for key in _Chem_g_id.iterkeys(): state.update({ key : np.array([opts[key]])}) info = { "RH_max" : 0, "libcloud_Git_revision" : libcloud_version, "parcel_Git_revision" : parcel_version } micro = _micro_init(aerosol, opts, state, info) with _output_init(micro, opts, spectra) as fout: # adding chem state vars if micro.opts_init.chem_switch: state.update({ "SO2_a" : 0.,"O3_a" : 0.,"H2O2_a" : 0.,}) state.update({ "CO2_a" : 0.,"HNO3_a" : 0.}) micro.diag_all() # selecting all particles micro.diag_chem(_Chem_a_id["NH3_a"]) state.update({"NH3_a": np.frombuffer(micro.outbuf())[0]}) # t=0 : init & save _output(fout, opts, micro, state, 0, spectra) # timestepping for it in range(1,nt+1): # diagnostics # the reasons to use analytic solution: # - independent of dt # - same as in 2D kinematic model state["z"] += w * dt state["t"] = it * dt # pressure if pprof == "pprof_const_th_rv": # as in icicle model p_hydro = _p_hydro_const_th_rv(state["z"], p_0, th_0, r_0) elif pprof == "pprof_const_rhod": # as in Grabowski and Wang 2009 rho = 1.13 # kg/m3 1.13 state["p"] = _p_hydro_const_rho(state["z"], p_0, rho) elif pprof == "pprof_piecewise_const_rhod": # as in Grabowski and Wang 2009 but calculating pressure # for rho piecewise constant per each time step state["p"] = _p_hydro_const_rho(w*dt, state["p"], state["rhod"][0]) else: raise Exception("pprof should be pprof_const_th_rv, pprof_const_rhod, or pprof_piecewise_const_rhod") # dry air density if pprof == "pprof_const_th_rv": state["rhod"][0] = common.rhod(p_hydro, th_0, r_0) state["p"] = common.p( state["rhod"][0], state["r_v"][0], common.T(state["th_d"][0], state["rhod"][0]) ) else: state["rhod"][0] = common.rhod( state["p"], common.th_dry2std(state["th_d"][0], state["r_v"][0]), state["r_v"][0] ) # microphysics _micro_step(micro, state, info, opts, it, fout) # TODO: only if user wants to stop @ RH_max #if (state["RH"] < info["RH_max"]): break # output if (it % outfreq == 0): print str(round(it / (nt * 1.) * 100, 2)) + " %" rec = it/outfreq _output(fout, opts, micro, state, rec, spectra) _save_attrs(fout, info) _save_attrs(fout, opts) if wait != 0: for it in range (nt+1, nt+wait): state["t"] = it * dt _micro_step(micro, state, info, opts, it, fout) if (it % outfreq == 0): rec = it/outfreq _output(fout, opts, micro, state, rec, spectra)
def parcel(dt=.1, z_max=200., w=1., T_0=300., p_0=101300., r_0=.022, outfile="test.nc", pprof="pprof_piecewise_const_rhod", outfreq=100, sd_conc=64, kappa=.5, mean_r = .04e-6 / 2, gstdev = 1.4, n_tot = 60.e6, out_bin = '{"radii": {"rght": 0.0001, "moms": [0], "drwt": "wet", "nbin": 26, "lnli": "log", "left": 1e-09}}', SO2_g_0 = 0., O3_g_0 = 0., H2O2_g_0 = 0., chem_sys = 'open', chem_dsl = False, chem_dsc = False, chem_rct = False, chem_spn = 1, chem_rho = 1.8e3 ): """ Args: dt (Optional[float]): timestep [s] z_max (Optional[float]): maximum vertical displacement [m] w (Optional[float]): updraft velocity [m/s] T_0 (Optional[float]): initial temperature [K] p_0 (Optional[float]): initial pressure [Pa] r_0 (Optional[float]): initial water vapour mass mixing ratio [kg/kg] outfile (Optional[string]): output netCDF file name outfreq (Optional[int]): output interval (in number of time steps) sd_conc (Optional[int]): number of moving bins (super-droplets) kappa (Optional[float]): kappa hygroscopicity parameter (see doi:10.5194/acp-7-1961-2007) mean_r (Optional[float]): lognormal distribution mode diameter [m] gstdev (Optional[float]): lognormal distribution geometric standard deviation [1] n_tot (Optional[float]): lognormal distribution total concentration under standard conditions (T=20C, p=1013.25 hPa, rv=0) [m-3] out_bin (Optional[json str]): dict of dicts defining spectrum diagnostics, e.g.: {"radii": {"rght": 0.0001, "moms": [0], "drwt": "wet", "nbin": 26, "lnli": "log", "left": 1e-09}, "cloud": {"rght": 2.5e-05, "moms": [0, 1, 2, 3], "drwt": "wet", "nbin": 49, "lnli": "lin", "left": 5e-07}} will generate five output spectra: - 0-th spectrum moment for 26 bins spaced logarithmically between 0 and 1e-4 m for dry radius - 0,1,2 & 3-rd moments for 49 bins spaced linearly between .5e-6 and 25e-6 for wet radius (TODO - add chemistry output description) SO2_g_0 (Optional[float]): initial SO2 gas volume concentration (mole fraction) [1] O3_g_0 (Optional[float]): initial O3 gas volume concentration (mole fraction) [1] H2O2_g_0 (Optional[float]): initial H2O2 gas volume concentration (mole fraction) [1] chem_sys (Optional[string]): accepted values: 'open', 'closed' (in open/closed system gas volume concentration in the air doesn't/does change due to chemical reactions) chem_dsl (Optional[bool]): on/off for dissolving chem species into droplets chem_dsc (Optional[bool]): on/off for dissociation of chem species in droplets chem_rct (Optional[bool]): on/off for oxidation of S_IV to S_VI chem_spn (Optional[int]): number of spinup timesteps before enabling chemical reactions pprof (Optional[string]): method to calculate pressure profile used to calculate dry air density that is used by the super-droplet scheme valid options are: pprof_const_th_rv, pprof_const_rhod, pprof_piecewise_const_rhod """ # packing function arguments into "opts" dictionary args, _, _, _ = inspect.getargvalues(inspect.currentframe()) opts = dict(zip(args, [locals()[k] for k in args])) # parsing json specification of output spectra spectra = json.loads(opts["out_bin"]) # sanity checks for arguments _arguments_checking(opts, spectra) th_0 = T_0 * (common.p_1000 / p_0)**(common.R_d / common.c_pd) nt = int(z_max / (w * dt)) state = { "t" : 0, "z" : 0, "r_v" : np.array([r_0]), "p" : p_0, "th_d" : np.array([common.th_std2dry(th_0, r_0)]), "rhod" : np.array([common.rhod(p_0, th_0, r_0)]), "T" : None, "RH" : None } info = { "RH_max" : 0, "libcloud_Git_revision" : libcloud_version, "parcel_Git_revision" : parcel_version } micro = _micro_init(opts, state, info) with _output_init(micro, opts, spectra) as fout: # adding chem state vars if micro.opts_init.chem_switch: state.update({ "SO2_g" : SO2_g_0, "O3_g" : O3_g_0, "H2O2_g" : H2O2_g_0 }) state.update({ "SO2_a" : 0., "O3_a" : 0., "H2O2_a" : 0. }) # t=0 : init & save _output(fout, opts, micro, state, 0, spectra) # timestepping for it in range(1,nt+1): # diagnostics # the reasons to use analytic solution: # - independent of dt # - same as in 2D kinematic model state["z"] += w * dt state["t"] = it * dt # pressure if pprof == "pprof_const_th_rv": # as in icicle model p_hydro = _p_hydro_const_th_rv(state["z"], p_0, th_0, r_0) elif pprof == "pprof_const_rhod": # as in Grabowski and Wang 2009 rho = 1.13 # kg/m3 1.13 state["p"] = _p_hydro_const_rho(state["z"], p_0, rho) elif pprof == "pprof_piecewise_const_rhod": # as in Grabowski and Wang 2009 but calculating pressure # for rho piecewise constant per each time step state["p"] = _p_hydro_const_rho(w*dt, state["p"], state["rhod"][0]) else: assert(False) # dry air density if pprof == "pprof_const_th_rv": state["rhod"][0] = common.rhod(p_hydro, th_0, r_0) state["p"] = common.p( state["rhod"][0], state["r_v"][0], common.T(state["th_d"][0], state["rhod"][0]) ) else: state["rhod"][0] = common.rhod( state["p"], common.th_dry2std(state["th_d"][0], state["r_v"][0]), state["r_v"][0] ) # microphysics _micro_step(micro, state, info, opts, it) # TODO: only if user wants to stop @ RH_max #if (state["RH"] < info["RH_max"]): break # output if (it % outfreq == 0): rec = it/outfreq _output(fout, opts, micro, state, rec, spectra) _save_attrs(fout, info) _save_attrs(fout, opts)