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