Пример #1
0
def test(RH_formula, step_count, substep_count, exact_substep, constp):
    print "[RH_formula = ", RH_formula, "]"
    print "step_count = ", step_count, " substep_count = ", substep_count, "exact substepping = ", exact_substep, "constp = ", constp

    opts_init.sstp_cond = substep_count
    opts_init.exact_sstp_cond = exact_substep
    opts_init.RH_formula = RH_formula

    rhod, th, rv, p = initial_state()
    rv_init = rv.copy()

    # in constp mode, th_std is expected instead of th_dry
    if constp == True:
        # dry/std conversions assume p = rhod (Rd + rv * Rv) T
        # which in general is not true in constp, but is true at init so we use it here
        th[0] = common.th_dry2std(th[0], rv[0])

    th_init = th.copy()
    prtcls = lgrngn.factory(backend, opts_init)
    if constp == False:
        prtcls.init(th, rv, rhod)
    else:
        prtcls.init(th, rv, rhod, p)
    ss = supersaturation(prtcls)
    print "initial supersaturation", ss

    exectime = 0
    # first step without condesnation just to see diag output
    opts.cond = False
    for step in arange(step_count):
        wrapped = wrapper(prtcls.step_sync, opts, th, rv, rhod)
        exectime += timeit.timeit(wrapped, number=1)
        prtcls.step_async(opts)
        opts.cond = True
#    print step, supersaturation(prtcls), temperature(prtcls), pressure(prtcls), th[0], rv[0]

    ss_post_cond = supersaturation(prtcls)
    print "supersaturation after condensation", ss_post_cond, th[0], rv[0]

    assert (abs(th[0] - exp_th[constp]) < 1e-4 * exp_th[constp])
    assert (abs(rv[0] - exp_rv[constp]) < 1e-3 * exp_rv[constp])
    rv_diff = rv_init.copy() - rv[0].copy()

    # change to subsaturated air - test evaporation
    rv[0] = 0.002
    rv_init = rv.copy()

    for step in arange(step_count):
        wrapped = wrapper(prtcls.step_sync, opts, th, rv, rhod)
        exectime += timeit.timeit(wrapped, number=1)
        prtcls.step_async(opts)


#      print step, supersaturation(prtcls), temperature(prtcls), pressure(prtcls), th[0], rv[0]

    ss_post_evap = supersaturation(prtcls)
    print "supersaturation after evaporation", ss_post_evap, th[0], rv[0]
    print 'execution time: ', exectime

    return ss_post_cond, th[0] - th_init[0], rv[0] - rv_init[0] - rv_diff[0]
Пример #2
0
def test(RH_formula, step_count, substep_count, exact_substep, constp):
    print "[RH_formula = ", RH_formula,"]"
    print "step_count = ", step_count, " substep_count = ", substep_count, "exact substepping = ", exact_substep, "constp = ", constp

    opts_init.sstp_cond=substep_count
    opts_init.exact_sstp_cond=exact_substep
    opts_init.RH_formula = RH_formula

    rhod, th, rv, p = initial_state()
    rv_init = rv.copy()

    # in constp mode, th_std is expected instead of th_dry
    if constp == True:
      # dry/std conversions assume p = rhod (Rd + rv * Rv) T
      # which in general is not true in constp, but is true at init so we use it here
      th[0] = common.th_dry2std(th[0], rv[0])

    th_init = th.copy()
    prtcls = lgrngn.factory(backend, opts_init)
    if constp == False:
      prtcls.init(th, rv, rhod)
    else:
      prtcls.init(th, rv, rhod, p)
    ss = supersaturation(prtcls)
    print "initial supersaturation", ss

    exectime = 0
    # first step without condesnation just to see diag output
    opts.cond = False
    for step in arange(step_count):
      wrapped = wrapper(prtcls.step_sync, opts, th, rv, rhod)
      exectime += timeit.timeit(wrapped, number=1)
      prtcls.step_async(opts)
      opts.cond = True
  #    print step, supersaturation(prtcls), temperature(prtcls), pressure(prtcls), th[0], rv[0]

    ss_post_cond = supersaturation(prtcls)
    print "supersaturation after condensation", ss_post_cond, th[0], rv[0]

    assert(abs(th[0] - exp_th[constp]) < 1e-4 * exp_th[constp])
    assert(abs(rv[0] - exp_rv[constp]) < 1e-3 * exp_rv[constp])
    rv_diff = rv_init.copy() - rv[0].copy()
  
    # change to subsaturated air - test evaporation
    rv[0]   = 0.002
    rv_init = rv.copy()

    for step in arange(step_count):
      wrapped = wrapper(prtcls.step_sync, opts, th, rv, rhod)
      exectime += timeit.timeit(wrapped, number=1)
      prtcls.step_async(opts)
#      print step, supersaturation(prtcls), temperature(prtcls), pressure(prtcls), th[0], rv[0]

    ss_post_evap = supersaturation(prtcls)
    print "supersaturation after evaporation", ss_post_evap, th[0], rv[0]
    print 'execution time: ', exectime
    
    return ss_post_cond, th[0] - th_init[0], rv[0] - rv_init[0] - rv_diff[0]
Пример #3
0
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
Пример #4
0
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
Пример #5
0
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
Пример #6
0
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)
Пример #7
0
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)
Пример #8
0
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)
Пример #9
0
# lgrngn-specific parameters
sd_conc = 44


def lognormal(lnr):
    mean_r = .08e-6 / 2
    stdev = 2
    n_tot = 566e6
    return n_tot * exp(-pow(
        (lnr - log(mean_r)), 2) / 2 / pow(log(stdev), 2)) / log(stdev) / sqrt(
            2 * pi)


kappa = .61  #TODO - check
# rho = 1.8 # TODO

chem_gas = {
    chem_species_t.SO2: 200e-12,
    chem_species_t.O3: 50e-9,
    chem_species_t.H2O2: 500e-12
}

# running all three
for rhs in [
        rhs_blk_2m(dt),
        rhs_lgrngn(dt, sd_conc, {kappa: lognormal}, chem_gas)
]:
    parcel(p_d, th_d, r_v, w, dt, nt, rhs)
    print p_d, arr_t([th_dry2std(th_d[0], r_v[0])]), r_v
Пример #10
0
print(git_revision)

print("common.p_vs(273.16)=", common.p_vs(273.16))
assert abs(common.p_vs(273.16) - 611.73) < .001
#</listing-1>

print("R_d =", common.R_d)
print("c_pd =", common.c_pd)
print("g =", common.g)
print("p_1000 =", common.p_1000)
print("eps =", common.eps)
print("rho_w =", common.rho_w)

th = 300
rv = .01

print(common.th_dry2std(th, rv))
assert common.th_std2dry(common.th_dry2std(th, rv), rv) == th

rd3 = (.2e-6)**3
assert common.rw3_cr(rd3, .5, 300) > rd3
assert common.S_cr(rd3, .5, 300) > 1

# just testing if pressure at 200m is lower than at 100m
assert common.p_hydro(100, 300, .01, 0, 100000) > common.p_hydro(
    200, 300, .01, 0, 100000)

# just testing if the density is > 1 kg / m3
assert common.rhod(100000, 300, 0) > 1
Пример #11
0
# blk_2m-specific parameter
# TODO: spectrum

# lgrngn-specific parameters
sd_conc = 44
def lognormal(lnr):
  mean_r = .08e-6 / 2
  stdev = 2
  n_tot = 566e6
  return n_tot * exp(
    -pow((lnr - log(mean_r)), 2) / 2 / pow(log(stdev),2)
  ) / log(stdev) / sqrt(2*pi);
kappa = .61 #TODO - check 
# rho = 1.8 # TODO

chem_gas = {
  chem_species_t.SO2  : 200e-12,
  chem_species_t.O3   : 50e-9,
  chem_species_t.H2O2 : 500e-12
}

# running all three
for rhs in [
  rhs_blk_2m(dt), 
  rhs_lgrngn(dt, sd_conc, {kappa:lognormal}, chem_gas)
]:
  parcel(p_d, th_d, r_v, w, dt, nt, rhs)
  print p_d, arr_t([th_dry2std(th_d[0], r_v[0])]), r_v

Пример #12
0
def test(RH_formula, step_count, substep_count, exact_substep, constp):
    print("[RH_formula = ", RH_formula, "]")
    print("step_count = ", step_count, " substep_count = ", substep_count,
          "exact substepping = ", exact_substep, "constp = ", constp)

    opts_init.sstp_cond = substep_count
    opts_init.exact_sstp_cond = exact_substep
    opts_init.RH_formula = RH_formula

    rhod, th, rv, p = initial_state()
    rhod_ss, th_ss, rv_ss, p_ss = supersat_state()

    # in constp mode, th_std is expected instead of th_dry
    if constp == True:
        # dry/std conversions assume p = rhod (Rd + rv * Rv) T
        # which in general is not true in constp, but is true at init so we use it here
        th[0] = common.th_dry2std(th[0], rv[0])
        th_ss[0] = common.th_dry2std(th_ss[0], rv_ss[0])

    prtcls = lgrngn.factory(backend, opts_init)

    if constp == False:
        prtcls.init(th, rv, rhod)
    else:
        prtcls.init(th, rv, rhod, p_ss)

    # go to supersaturated air, density changes to test density substepping too
    rhod[0] = rhod_ss
    th[0] = th_ss
    rv[0] = rv_ss
    rv_init = rv.copy()
    th_init = th.copy()

    exectime = 0
    opts.cond = 0
    for step in arange(step_count):
        wrapped = wrapper(prtcls.step_sync, opts, th, rv, rhod)
        exectime += timeit.timeit(wrapped, number=1)
        prtcls.step_async(opts)
        if step == 9:
            # some parameters are analyzed after 10 steps, before small CCNs evaporate
            act_conc_post_cond = act_conc(prtcls)
            mean_r_post_cond = mean_r(prtcls)
            second_r_post_cond = second_r(prtcls)
            third_r_post_cond = third_r(prtcls)
        if step == 0:
            print("initial supersaturation", supersaturation(prtcls))
            opts.cond = 1
#      print step, supersaturation(prtcls), th[0], rv[0], mean_r(prtcls), second_r(prtcls), third_r(prtcls), act_conc(prtcls)

    ss_post_cond = supersaturation(prtcls)
    print("supersaturation after condensation", ss_post_cond, th[0], rv[0],
          mean_r(prtcls), second_r(prtcls), third_r(prtcls), act_conc(prtcls))

    assert (abs(th[0] - exp_th[constp]) < 1e-4 * exp_th[constp])
    assert (abs(rv[0] - exp_rv[constp]) < 1e-3 * exp_rv[constp])
    rv_diff = rv_init.copy() - rv[0].copy()
    th_diff = th_init.copy() - th[0].copy()

    # change to subsaturated air - test evaporation
    rhod[0] = 1.1
    th[0] = 305
    rv[0] = 0.0085
    rv_init = rv.copy()
    th_init = th.copy()

    for step in arange(step_count):
        wrapped = wrapper(prtcls.step_sync, opts, th, rv, rhod)
        exectime += timeit.timeit(wrapped, number=1)
        prtcls.step_async(opts)

#     print step, supersaturation(prtcls), th[0], rv[0], mean_r(prtcls), second_r(prtcls), third_r(prtcls), act_conc(prtcls)

    ss_post_evap = supersaturation(prtcls)
    print("supersaturation after evaporation", ss_post_evap, th[0], rv[0],
          mean_r(prtcls), second_r(prtcls), third_r(prtcls), act_conc(prtcls),
          gccn_conc(prtcls))
    # after evaporation, only larger mode particles should have r > 0.5 microns
    assert (act_conc(prtcls) == gccn_conc(prtcls))
    print('execution time: ', exectime)

    return ss_post_cond, th[0] - th_init[0] - th_diff[0], rv[0] - rv_init[
        0] - rv_diff[
            0], act_conc_post_cond, mean_r_post_cond, second_r_post_cond, third_r_post_cond
Пример #13
0
def test(RH_formula, step_count, substep_count, exact_substep, constp):
    print "[RH_formula = ", RH_formula,"]"
    print "step_count = ", step_count, " substep_count = ", substep_count, "exact substepping = ", exact_substep, "constp = ", constp

    opts_init.sstp_cond=substep_count
    opts_init.exact_sstp_cond=exact_substep
    opts_init.RH_formula = RH_formula

    rhod, th, rv, p = initial_state()
    rhod_ss, th_ss, rv_ss, p_ss = supersat_state()

    # in constp mode, th_std is expected instead of th_dry
    if constp == True:
      # dry/std conversions assume p = rhod (Rd + rv * Rv) T
      # which in general is not true in constp, but is true at init so we use it here
      th[0] = common.th_dry2std(th[0], rv[0])
      th_ss[0] = common.th_dry2std(th_ss[0], rv_ss[0])

    prtcls = lgrngn.factory(backend, opts_init)

    if constp == False:
      prtcls.init(th, rv, rhod)
    else:
      prtcls.init(th, rv, rhod, p_ss)

    # go to supersaturated air, density changes to test density substepping too
    rhod[0] = rhod_ss
    th[0]   = th_ss
    rv[0]   = rv_ss
    rv_init = rv.copy()
    th_init = th.copy()

    exectime = 0
    opts.cond = 0
    for step in arange(step_count):
      wrapped = wrapper(prtcls.step_sync, opts, th, rv, rhod)
      exectime += timeit.timeit(wrapped, number=1)
      prtcls.step_async(opts)
      if step == 9:
        # some parameters are analyzed after 10 steps, before small CCNs evaporate
        act_conc_post_cond = act_conc(prtcls)
        mean_r_post_cond = mean_r(prtcls)
        second_r_post_cond = second_r(prtcls)
        third_r_post_cond = third_r(prtcls)
      if step == 0:
        print "initial supersaturation", supersaturation(prtcls)
        opts.cond = 1
#      print step, supersaturation(prtcls), th[0], rv[0], mean_r(prtcls), second_r(prtcls), third_r(prtcls), act_conc(prtcls)
    
    ss_post_cond = supersaturation(prtcls)
    print "supersaturation after condensation", ss_post_cond, th[0], rv[0], mean_r(prtcls), second_r(prtcls), third_r(prtcls), act_conc(prtcls)

    assert(abs(th[0] - exp_th[constp]) < 1e-4 * exp_th[constp])
    assert(abs(rv[0] - exp_rv[constp]) < 1e-3 * exp_rv[constp])
    rv_diff = rv_init.copy() - rv[0].copy()
    th_diff = th_init.copy() - th[0].copy()
  
    # change to subsaturated air - test evaporation
    rhod[0] = 1.1
    th[0]   = 305
    rv[0]   = 0.0085
    rv_init = rv.copy()
    th_init = th.copy()

    for step in arange(step_count):
      wrapped = wrapper(prtcls.step_sync, opts, th, rv, rhod)
      exectime += timeit.timeit(wrapped, number=1)
      prtcls.step_async(opts)
 #     print step, supersaturation(prtcls), th[0], rv[0], mean_r(prtcls), second_r(prtcls), third_r(prtcls), act_conc(prtcls)

    ss_post_evap = supersaturation(prtcls)
    print "supersaturation after evaporation", ss_post_evap, th[0], rv[0], mean_r(prtcls), second_r(prtcls), third_r(prtcls), act_conc(prtcls), gccn_conc(prtcls)
    # after evaporation, only larger mode particles should have r > 0.5 microns
    assert(act_conc(prtcls) == gccn_conc(prtcls))
    print 'execution time: ', exectime
    
    return ss_post_cond, th[0] - th_init[0] - th_diff[0], rv[0] - rv_init[0] - rv_diff[0], act_conc_post_cond, mean_r_post_cond, second_r_post_cond, third_r_post_cond
Пример #14
0
from libcloudphxx import common, git_revision

print git_revision

print "common.p_vs(273.16)=", common.p_vs(273.16)
assert abs(common.p_vs(273.16) - 611.73) < .001
#</listing-1>

print "R_d =", common.R_d
print "c_pd =", common.c_pd
print "g =", common.g
print "p_1000 =", common.p_1000
print "eps =", common.eps
print "rho_w =", common.rho_w

th = 300
rv = .01

print common.th_dry2std(th, rv)	
assert common.th_std2dry(common.th_dry2std(th, rv), rv) == th

rd3 = (.2e-6)**3
assert common.rw3_cr(rd3, .5, 300) > rd3
assert common.S_cr(rd3, .5, 300) > 1

# just testing if pressure at 200m is lower than at 100m
assert common.p_hydro(100, 300, .01, 0, 100000) > common.p_hydro(200, 300, .01, 0, 100000)

# just testing if the density is > 1 kg / m3
assert common.rhod(100000, 300, 0) > 1