PySDM_examples.Grabowski_and_Pawlowska_2023.settings

 1import numpy as np
 2from pystrict import strict
 3
 4from PySDM import Formulae
 5from PySDM.dynamics import condensation
 6from PySDM.initialisation.spectra import Lognormal, Sum
 7from PySDM.physics import si
 8
 9condensation_tolerance = condensation.DEFAULTS.rtol_thd / 100
10
11
12@strict
13class Settings:
14    def __init__(
15        self,
16        *,
17        aerosol: str,
18        vertical_velocity: float,
19        dt: float,
20        n_sd: int,
21        initial_temperature: float = 283 * si.K,
22        initial_pressure: float = 900 * si.mbar,
23        initial_relative_humidity: float = 0.97,
24        displacement: float = 1000 * si.m,
25        mass_accommodation_coefficient: float = 0.3,
26        rtol_thd: float = condensation_tolerance,
27        rtol_x: float = condensation_tolerance
28    ):
29        self.formulae = Formulae(constants={"MAC": mass_accommodation_coefficient})
30        self.n_sd = n_sd
31        self.aerosol_modes_by_kappa = {
32            "pristine": {
33                1.28: Sum(
34                    (
35                        Lognormal(
36                            norm_factor=125 / si.cm**3, m_mode=11 * si.nm, s_geom=1.2
37                        ),
38                        Lognormal(
39                            norm_factor=65 / si.cm**3, m_mode=60 * si.nm, s_geom=1.7
40                        ),
41                    )
42                )
43            },
44            "polluted": {
45                1.28: Sum(
46                    (
47                        Lognormal(
48                            norm_factor=160 / si.cm**3, m_mode=29 * si.nm, s_geom=1.36
49                        ),
50                        Lognormal(
51                            norm_factor=380 / si.cm**3, m_mode=71 * si.nm, s_geom=1.57
52                        ),
53                    )
54                )
55            },
56        }[aerosol]
57
58        const = self.formulae.constants
59        self.vertical_velocity = vertical_velocity
60        self.initial_pressure = initial_pressure
61        self.initial_temperature = initial_temperature
62        pv0 = (
63            initial_relative_humidity
64            * self.formulae.saturation_vapour_pressure.pvs_water(initial_temperature)
65        )
66        self.initial_vapour_mixing_ratio = const.eps * pv0 / (initial_pressure - pv0)
67        self.t_max = displacement / vertical_velocity
68        self.timestep = dt
69        self.output_interval = self.timestep
70        self.rtol_thd = rtol_thd
71        self.rtol_x = rtol_x
72
73    @property
74    def initial_air_density(self):
75        const = self.formulae.constants
76        dry_air_density = (
77            self.formulae.trivia.p_d(
78                self.initial_pressure, self.initial_vapour_mixing_ratio
79            )
80            / self.initial_temperature
81            / const.Rd
82        )
83        return dry_air_density * (1 + self.initial_vapour_mixing_ratio)
84
85    @property
86    def nt(self) -> int:
87        nt = self.t_max / self.timestep
88        nt_int = round(nt)
89        np.testing.assert_almost_equal(nt, nt_int)
90        return nt_int
91
92    @property
93    def steps_per_output_interval(self) -> int:
94        return int(self.output_interval / self.timestep)
95
96    @property
97    def output_steps(self) -> np.ndarray:
98        return np.arange(0, self.nt + 1, self.steps_per_output_interval)
condensation_tolerance = 1e-08
@strict
class Settings:
13@strict
14class Settings:
15    def __init__(
16        self,
17        *,
18        aerosol: str,
19        vertical_velocity: float,
20        dt: float,
21        n_sd: int,
22        initial_temperature: float = 283 * si.K,
23        initial_pressure: float = 900 * si.mbar,
24        initial_relative_humidity: float = 0.97,
25        displacement: float = 1000 * si.m,
26        mass_accommodation_coefficient: float = 0.3,
27        rtol_thd: float = condensation_tolerance,
28        rtol_x: float = condensation_tolerance
29    ):
30        self.formulae = Formulae(constants={"MAC": mass_accommodation_coefficient})
31        self.n_sd = n_sd
32        self.aerosol_modes_by_kappa = {
33            "pristine": {
34                1.28: Sum(
35                    (
36                        Lognormal(
37                            norm_factor=125 / si.cm**3, m_mode=11 * si.nm, s_geom=1.2
38                        ),
39                        Lognormal(
40                            norm_factor=65 / si.cm**3, m_mode=60 * si.nm, s_geom=1.7
41                        ),
42                    )
43                )
44            },
45            "polluted": {
46                1.28: Sum(
47                    (
48                        Lognormal(
49                            norm_factor=160 / si.cm**3, m_mode=29 * si.nm, s_geom=1.36
50                        ),
51                        Lognormal(
52                            norm_factor=380 / si.cm**3, m_mode=71 * si.nm, s_geom=1.57
53                        ),
54                    )
55                )
56            },
57        }[aerosol]
58
59        const = self.formulae.constants
60        self.vertical_velocity = vertical_velocity
61        self.initial_pressure = initial_pressure
62        self.initial_temperature = initial_temperature
63        pv0 = (
64            initial_relative_humidity
65            * self.formulae.saturation_vapour_pressure.pvs_water(initial_temperature)
66        )
67        self.initial_vapour_mixing_ratio = const.eps * pv0 / (initial_pressure - pv0)
68        self.t_max = displacement / vertical_velocity
69        self.timestep = dt
70        self.output_interval = self.timestep
71        self.rtol_thd = rtol_thd
72        self.rtol_x = rtol_x
73
74    @property
75    def initial_air_density(self):
76        const = self.formulae.constants
77        dry_air_density = (
78            self.formulae.trivia.p_d(
79                self.initial_pressure, self.initial_vapour_mixing_ratio
80            )
81            / self.initial_temperature
82            / const.Rd
83        )
84        return dry_air_density * (1 + self.initial_vapour_mixing_ratio)
85
86    @property
87    def nt(self) -> int:
88        nt = self.t_max / self.timestep
89        nt_int = round(nt)
90        np.testing.assert_almost_equal(nt, nt_int)
91        return nt_int
92
93    @property
94    def steps_per_output_interval(self) -> int:
95        return int(self.output_interval / self.timestep)
96
97    @property
98    def output_steps(self) -> np.ndarray:
99        return np.arange(0, self.nt + 1, self.steps_per_output_interval)
Settings( *, aerosol: str, vertical_velocity: float, dt: float, n_sd: int, initial_temperature: float = 283.0, initial_pressure: float = 90000.0, initial_relative_humidity: float = 0.97, displacement: float = 1000.0, mass_accommodation_coefficient: float = 0.3, rtol_thd: float = 1e-08, rtol_x: float = 1e-08)
15    def __init__(
16        self,
17        *,
18        aerosol: str,
19        vertical_velocity: float,
20        dt: float,
21        n_sd: int,
22        initial_temperature: float = 283 * si.K,
23        initial_pressure: float = 900 * si.mbar,
24        initial_relative_humidity: float = 0.97,
25        displacement: float = 1000 * si.m,
26        mass_accommodation_coefficient: float = 0.3,
27        rtol_thd: float = condensation_tolerance,
28        rtol_x: float = condensation_tolerance
29    ):
30        self.formulae = Formulae(constants={"MAC": mass_accommodation_coefficient})
31        self.n_sd = n_sd
32        self.aerosol_modes_by_kappa = {
33            "pristine": {
34                1.28: Sum(
35                    (
36                        Lognormal(
37                            norm_factor=125 / si.cm**3, m_mode=11 * si.nm, s_geom=1.2
38                        ),
39                        Lognormal(
40                            norm_factor=65 / si.cm**3, m_mode=60 * si.nm, s_geom=1.7
41                        ),
42                    )
43                )
44            },
45            "polluted": {
46                1.28: Sum(
47                    (
48                        Lognormal(
49                            norm_factor=160 / si.cm**3, m_mode=29 * si.nm, s_geom=1.36
50                        ),
51                        Lognormal(
52                            norm_factor=380 / si.cm**3, m_mode=71 * si.nm, s_geom=1.57
53                        ),
54                    )
55                )
56            },
57        }[aerosol]
58
59        const = self.formulae.constants
60        self.vertical_velocity = vertical_velocity
61        self.initial_pressure = initial_pressure
62        self.initial_temperature = initial_temperature
63        pv0 = (
64            initial_relative_humidity
65            * self.formulae.saturation_vapour_pressure.pvs_water(initial_temperature)
66        )
67        self.initial_vapour_mixing_ratio = const.eps * pv0 / (initial_pressure - pv0)
68        self.t_max = displacement / vertical_velocity
69        self.timestep = dt
70        self.output_interval = self.timestep
71        self.rtol_thd = rtol_thd
72        self.rtol_x = rtol_x
formulae
n_sd
aerosol_modes_by_kappa
vertical_velocity
initial_pressure
initial_temperature
initial_vapour_mixing_ratio
t_max
timestep
output_interval
rtol_thd
rtol_x
initial_air_density
74    @property
75    def initial_air_density(self):
76        const = self.formulae.constants
77        dry_air_density = (
78            self.formulae.trivia.p_d(
79                self.initial_pressure, self.initial_vapour_mixing_ratio
80            )
81            / self.initial_temperature
82            / const.Rd
83        )
84        return dry_air_density * (1 + self.initial_vapour_mixing_ratio)
nt: int
86    @property
87    def nt(self) -> int:
88        nt = self.t_max / self.timestep
89        nt_int = round(nt)
90        np.testing.assert_almost_equal(nt, nt_int)
91        return nt_int
steps_per_output_interval: int
93    @property
94    def steps_per_output_interval(self) -> int:
95        return int(self.output_interval / self.timestep)
output_steps: numpy.ndarray
97    @property
98    def output_steps(self) -> np.ndarray:
99        return np.arange(0, self.nt + 1, self.steps_per_output_interval)