PySDM_examples.Kreidenweis_et_al_2003.settings

 1import numpy as np
 2from chempy import Substance
 3from pystrict import strict
 4
 5from PySDM import Formulae
 6from PySDM.dynamics.impl.chemistry_utils import AQUEOUS_COMPOUNDS
 7from PySDM.initialisation import spectra
 8from PySDM.initialisation.sampling import spectral_sampling as spec_sampling
 9from PySDM.physics import si
10from PySDM.physics.constants import PPB, PPM
11
12
13@strict
14class Settings:
15    def __init__(
16        self,
17        dt: float,
18        n_sd: int,
19        n_substep: int,
20        spectral_sampling: spec_sampling.SpectralSampling = spec_sampling.Logarithmic,
21    ):
22        self.formulae = Formulae(
23            saturation_vapour_pressure="AugustRocheMagnus",
24            constants={"g_std": 10 * si.m / si.s**2},
25        )
26        const = self.formulae.constants
27        self.DRY_RHO = 1800 * si.kg / (si.m**3)
28        self.dry_molar_mass = Substance.from_formula("NH4HSO4").mass * si.gram / si.mole
29
30        self.system_type = "closed"
31
32        self.t_max = (2400 + 196) * si.s
33        self.output_interval = 10 * si.s
34        self.dt = dt
35
36        self.w = 0.5 * si.m / si.s
37
38        self.n_sd = n_sd
39        self.n_substep = n_substep
40
41        self.p0 = 950 * si.mbar
42        self.T0 = 285.2 * si.K
43        pv0 = 0.95 * self.formulae.saturation_vapour_pressure.pvs_water(self.T0)
44        self.initial_water_vapour_mixing_ratio = const.eps * pv0 / (self.p0 - pv0)
45        self.kappa = 0.61
46
47        self.cloud_radius_range = (0.5 * si.micrometre, 25 * si.micrometre)
48
49        self.mass_of_dry_air = 44
50
51        # note: rho is not specified in the paper
52        rho0 = 1
53
54        self.r_dry, self.n_in_dv = spectral_sampling(
55            spectrum=spectra.Lognormal(
56                norm_factor=566 / si.cm**3 / rho0 * self.mass_of_dry_air,
57                m_mode=0.08 * si.um / 2,
58                s_geom=2,
59            )
60        ).sample(n_sd)
61
62        self.ENVIRONMENT_MOLE_FRACTIONS = {
63            "SO2": 0.2 * PPB,
64            "O3": 50 * PPB,
65            "H2O2": 0.5 * PPB,
66            "CO2": 360 * PPM,
67            "HNO3": 0.1 * PPB,
68            "NH3": 0.1 * PPB,
69        }
70
71        self.starting_amounts = {
72            "moles_"
73            + k: (
74                self.formulae.trivia.volume(self.r_dry)
75                * self.DRY_RHO
76                / self.dry_molar_mass
77                if k in ("N_mIII", "S_VI")
78                else np.zeros(self.n_sd)
79            )
80            for k in AQUEOUS_COMPOUNDS
81        }
82
83        self.dry_radius_bins_edges = (
84            np.logspace(np.log10(0.01 * si.um), np.log10(1 * si.um), 51, endpoint=True)
85            / 2
86        )
87
88    @property
89    def nt(self):
90        nt = self.t_max / self.dt
91        assert nt == int(nt)
92        return int(nt)
93
94    @property
95    def steps_per_output_interval(self) -> int:
96        return int(self.output_interval / self.dt)
@strict
class Settings:
14@strict
15class Settings:
16    def __init__(
17        self,
18        dt: float,
19        n_sd: int,
20        n_substep: int,
21        spectral_sampling: spec_sampling.SpectralSampling = spec_sampling.Logarithmic,
22    ):
23        self.formulae = Formulae(
24            saturation_vapour_pressure="AugustRocheMagnus",
25            constants={"g_std": 10 * si.m / si.s**2},
26        )
27        const = self.formulae.constants
28        self.DRY_RHO = 1800 * si.kg / (si.m**3)
29        self.dry_molar_mass = Substance.from_formula("NH4HSO4").mass * si.gram / si.mole
30
31        self.system_type = "closed"
32
33        self.t_max = (2400 + 196) * si.s
34        self.output_interval = 10 * si.s
35        self.dt = dt
36
37        self.w = 0.5 * si.m / si.s
38
39        self.n_sd = n_sd
40        self.n_substep = n_substep
41
42        self.p0 = 950 * si.mbar
43        self.T0 = 285.2 * si.K
44        pv0 = 0.95 * self.formulae.saturation_vapour_pressure.pvs_water(self.T0)
45        self.initial_water_vapour_mixing_ratio = const.eps * pv0 / (self.p0 - pv0)
46        self.kappa = 0.61
47
48        self.cloud_radius_range = (0.5 * si.micrometre, 25 * si.micrometre)
49
50        self.mass_of_dry_air = 44
51
52        # note: rho is not specified in the paper
53        rho0 = 1
54
55        self.r_dry, self.n_in_dv = spectral_sampling(
56            spectrum=spectra.Lognormal(
57                norm_factor=566 / si.cm**3 / rho0 * self.mass_of_dry_air,
58                m_mode=0.08 * si.um / 2,
59                s_geom=2,
60            )
61        ).sample(n_sd)
62
63        self.ENVIRONMENT_MOLE_FRACTIONS = {
64            "SO2": 0.2 * PPB,
65            "O3": 50 * PPB,
66            "H2O2": 0.5 * PPB,
67            "CO2": 360 * PPM,
68            "HNO3": 0.1 * PPB,
69            "NH3": 0.1 * PPB,
70        }
71
72        self.starting_amounts = {
73            "moles_"
74            + k: (
75                self.formulae.trivia.volume(self.r_dry)
76                * self.DRY_RHO
77                / self.dry_molar_mass
78                if k in ("N_mIII", "S_VI")
79                else np.zeros(self.n_sd)
80            )
81            for k in AQUEOUS_COMPOUNDS
82        }
83
84        self.dry_radius_bins_edges = (
85            np.logspace(np.log10(0.01 * si.um), np.log10(1 * si.um), 51, endpoint=True)
86            / 2
87        )
88
89    @property
90    def nt(self):
91        nt = self.t_max / self.dt
92        assert nt == int(nt)
93        return int(nt)
94
95    @property
96    def steps_per_output_interval(self) -> int:
97        return int(self.output_interval / self.dt)
Settings( dt: float, n_sd: int, n_substep: int, spectral_sampling: PySDM.initialisation.sampling.spectral_sampling.SpectralSampling = <class 'PySDM.initialisation.sampling.spectral_sampling.Logarithmic'>)
16    def __init__(
17        self,
18        dt: float,
19        n_sd: int,
20        n_substep: int,
21        spectral_sampling: spec_sampling.SpectralSampling = spec_sampling.Logarithmic,
22    ):
23        self.formulae = Formulae(
24            saturation_vapour_pressure="AugustRocheMagnus",
25            constants={"g_std": 10 * si.m / si.s**2},
26        )
27        const = self.formulae.constants
28        self.DRY_RHO = 1800 * si.kg / (si.m**3)
29        self.dry_molar_mass = Substance.from_formula("NH4HSO4").mass * si.gram / si.mole
30
31        self.system_type = "closed"
32
33        self.t_max = (2400 + 196) * si.s
34        self.output_interval = 10 * si.s
35        self.dt = dt
36
37        self.w = 0.5 * si.m / si.s
38
39        self.n_sd = n_sd
40        self.n_substep = n_substep
41
42        self.p0 = 950 * si.mbar
43        self.T0 = 285.2 * si.K
44        pv0 = 0.95 * self.formulae.saturation_vapour_pressure.pvs_water(self.T0)
45        self.initial_water_vapour_mixing_ratio = const.eps * pv0 / (self.p0 - pv0)
46        self.kappa = 0.61
47
48        self.cloud_radius_range = (0.5 * si.micrometre, 25 * si.micrometre)
49
50        self.mass_of_dry_air = 44
51
52        # note: rho is not specified in the paper
53        rho0 = 1
54
55        self.r_dry, self.n_in_dv = spectral_sampling(
56            spectrum=spectra.Lognormal(
57                norm_factor=566 / si.cm**3 / rho0 * self.mass_of_dry_air,
58                m_mode=0.08 * si.um / 2,
59                s_geom=2,
60            )
61        ).sample(n_sd)
62
63        self.ENVIRONMENT_MOLE_FRACTIONS = {
64            "SO2": 0.2 * PPB,
65            "O3": 50 * PPB,
66            "H2O2": 0.5 * PPB,
67            "CO2": 360 * PPM,
68            "HNO3": 0.1 * PPB,
69            "NH3": 0.1 * PPB,
70        }
71
72        self.starting_amounts = {
73            "moles_"
74            + k: (
75                self.formulae.trivia.volume(self.r_dry)
76                * self.DRY_RHO
77                / self.dry_molar_mass
78                if k in ("N_mIII", "S_VI")
79                else np.zeros(self.n_sd)
80            )
81            for k in AQUEOUS_COMPOUNDS
82        }
83
84        self.dry_radius_bins_edges = (
85            np.logspace(np.log10(0.01 * si.um), np.log10(1 * si.um), 51, endpoint=True)
86            / 2
87        )
formulae
DRY_RHO
dry_molar_mass
system_type
t_max
output_interval
dt
w
n_sd
n_substep
p0
T0
initial_water_vapour_mixing_ratio
kappa
cloud_radius_range
mass_of_dry_air
ENVIRONMENT_MOLE_FRACTIONS
starting_amounts
dry_radius_bins_edges
nt
89    @property
90    def nt(self):
91        nt = self.t_max / self.dt
92        assert nt == int(nt)
93        return int(nt)
steps_per_output_interval: int
95    @property
96    def steps_per_output_interval(self) -> int:
97        return int(self.output_interval / self.dt)