Beispiel #1
0
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
Beispiel #4
0
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
Beispiel #7
0
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
Beispiel #8
0
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
Beispiel #9
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
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
Beispiel #11
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
Beispiel #12
0
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
Beispiel #13
0
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
Beispiel #14
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)
Beispiel #15
0
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"]
Beispiel #16
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)
Beispiel #17
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)