PySDM_examples.Lowe_et_al_2019.settings

 1from functools import lru_cache
 2
 3import numpy as np
 4from PySDM_examples.Lowe_et_al_2019.constants_def import LOWE_CONSTS
 5from pystrict import strict
 6
 7from PySDM import Formulae
 8from PySDM.backends import CPU
 9from PySDM.initialisation.aerosol_composition import DryAerosolMixture
10from PySDM.physics import si
11
12
13@lru_cache
14def backend(model):
15    return CPU(
16        formulae=Formulae(
17            surface_tension=model,
18            constants=LOWE_CONSTS,
19            diffusion_kinetics="LoweEtAl2019",
20            diffusion_thermics="LoweEtAl2019",
21            latent_heat_vapourisation="Lowe2019",
22            saturation_vapour_pressure="Lowe1977",
23            optical_albedo="Bohren1987",
24            optical_depth="Stephens1978",
25        ),
26        override_jit_flags={"parallel": False},
27    )
28
29
30@strict
31class Settings:
32    def __init__(
33        self,
34        dz: float,
35        n_sd_per_mode: int,
36        aerosol: DryAerosolMixture,
37        model: str,
38        w: float = 0.32 * si.m / si.s,
39    ):
40        assert model in ("Constant", "CompressedFilmOvadnevaite")
41        self.model = model
42        self.n_sd_per_mode = n_sd_per_mode
43        self.backend = backend(model)
44        self.formulae = self.backend.formulae
45        const = self.formulae.constants
46        self.aerosol = aerosol
47
48        max_altitude = 200 * si.m
49        self.w = w
50        self.t_max = max_altitude / self.w
51        self.dt = dz / self.w
52        self.output_interval = 1 * self.dt
53
54        self.p0 = 980 * si.mbar
55        self.T0 = 280 * si.K
56        pv0 = 0.999 * self.formulae.saturation_vapour_pressure.pvs_water(self.T0)
57        self.initial_water_vapour_mixing_ratio = const.eps * pv0 / (self.p0 - pv0)
58
59        self.cloud_radius_range = (0.5 * si.micrometre, np.inf)
60
61        self.mass_of_dry_air = 44
62
63        self.wet_radius_bins_edges = np.logspace(
64            np.log10(4 * si.um), np.log10(12 * si.um), 128 + 1, endpoint=True
65        )
66
67    @property
68    def rho0(self):
69        const = self.formulae.constants
70        rhod0 = (
71            self.formulae.trivia.p_d(self.p0, self.initial_water_vapour_mixing_ratio)
72            / self.T0
73            / const.Rd
74        )
75        return rhod0 * (1 + self.initial_water_vapour_mixing_ratio)
76
77    @property
78    def nt(self) -> int:
79        nt = self.t_max / self.dt
80        nt_int = round(nt)
81        np.testing.assert_almost_equal(nt, nt_int)
82        return nt_int
83
84    @property
85    def steps_per_output_interval(self) -> int:
86        return int(self.output_interval / self.dt)
87
88    @property
89    def output_steps(self) -> np.ndarray:
90        return np.arange(0, self.nt + 1, self.steps_per_output_interval)
@lru_cache
def backend(model):
14@lru_cache
15def backend(model):
16    return CPU(
17        formulae=Formulae(
18            surface_tension=model,
19            constants=LOWE_CONSTS,
20            diffusion_kinetics="LoweEtAl2019",
21            diffusion_thermics="LoweEtAl2019",
22            latent_heat_vapourisation="Lowe2019",
23            saturation_vapour_pressure="Lowe1977",
24            optical_albedo="Bohren1987",
25            optical_depth="Stephens1978",
26        ),
27        override_jit_flags={"parallel": False},
28    )
@strict
class Settings:
31@strict
32class Settings:
33    def __init__(
34        self,
35        dz: float,
36        n_sd_per_mode: int,
37        aerosol: DryAerosolMixture,
38        model: str,
39        w: float = 0.32 * si.m / si.s,
40    ):
41        assert model in ("Constant", "CompressedFilmOvadnevaite")
42        self.model = model
43        self.n_sd_per_mode = n_sd_per_mode
44        self.backend = backend(model)
45        self.formulae = self.backend.formulae
46        const = self.formulae.constants
47        self.aerosol = aerosol
48
49        max_altitude = 200 * si.m
50        self.w = w
51        self.t_max = max_altitude / self.w
52        self.dt = dz / self.w
53        self.output_interval = 1 * self.dt
54
55        self.p0 = 980 * si.mbar
56        self.T0 = 280 * si.K
57        pv0 = 0.999 * self.formulae.saturation_vapour_pressure.pvs_water(self.T0)
58        self.initial_water_vapour_mixing_ratio = const.eps * pv0 / (self.p0 - pv0)
59
60        self.cloud_radius_range = (0.5 * si.micrometre, np.inf)
61
62        self.mass_of_dry_air = 44
63
64        self.wet_radius_bins_edges = np.logspace(
65            np.log10(4 * si.um), np.log10(12 * si.um), 128 + 1, endpoint=True
66        )
67
68    @property
69    def rho0(self):
70        const = self.formulae.constants
71        rhod0 = (
72            self.formulae.trivia.p_d(self.p0, self.initial_water_vapour_mixing_ratio)
73            / self.T0
74            / const.Rd
75        )
76        return rhod0 * (1 + self.initial_water_vapour_mixing_ratio)
77
78    @property
79    def nt(self) -> int:
80        nt = self.t_max / self.dt
81        nt_int = round(nt)
82        np.testing.assert_almost_equal(nt, nt_int)
83        return nt_int
84
85    @property
86    def steps_per_output_interval(self) -> int:
87        return int(self.output_interval / self.dt)
88
89    @property
90    def output_steps(self) -> np.ndarray:
91        return np.arange(0, self.nt + 1, self.steps_per_output_interval)
Settings( dz: float, n_sd_per_mode: int, aerosol: PySDM.initialisation.aerosol_composition.dry_aerosol.DryAerosolMixture, model: str, w: float = 0.32)
33    def __init__(
34        self,
35        dz: float,
36        n_sd_per_mode: int,
37        aerosol: DryAerosolMixture,
38        model: str,
39        w: float = 0.32 * si.m / si.s,
40    ):
41        assert model in ("Constant", "CompressedFilmOvadnevaite")
42        self.model = model
43        self.n_sd_per_mode = n_sd_per_mode
44        self.backend = backend(model)
45        self.formulae = self.backend.formulae
46        const = self.formulae.constants
47        self.aerosol = aerosol
48
49        max_altitude = 200 * si.m
50        self.w = w
51        self.t_max = max_altitude / self.w
52        self.dt = dz / self.w
53        self.output_interval = 1 * self.dt
54
55        self.p0 = 980 * si.mbar
56        self.T0 = 280 * si.K
57        pv0 = 0.999 * self.formulae.saturation_vapour_pressure.pvs_water(self.T0)
58        self.initial_water_vapour_mixing_ratio = const.eps * pv0 / (self.p0 - pv0)
59
60        self.cloud_radius_range = (0.5 * si.micrometre, np.inf)
61
62        self.mass_of_dry_air = 44
63
64        self.wet_radius_bins_edges = np.logspace(
65            np.log10(4 * si.um), np.log10(12 * si.um), 128 + 1, endpoint=True
66        )
model
n_sd_per_mode
backend
formulae
aerosol
w
t_max
dt
output_interval
p0
T0
initial_water_vapour_mixing_ratio
cloud_radius_range
mass_of_dry_air
wet_radius_bins_edges
rho0
68    @property
69    def rho0(self):
70        const = self.formulae.constants
71        rhod0 = (
72            self.formulae.trivia.p_d(self.p0, self.initial_water_vapour_mixing_ratio)
73            / self.T0
74            / const.Rd
75        )
76        return rhod0 * (1 + self.initial_water_vapour_mixing_ratio)
nt: int
78    @property
79    def nt(self) -> int:
80        nt = self.t_max / self.dt
81        nt_int = round(nt)
82        np.testing.assert_almost_equal(nt, nt_int)
83        return nt_int
steps_per_output_interval: int
85    @property
86    def steps_per_output_interval(self) -> int:
87        return int(self.output_interval / self.dt)
output_steps: numpy.ndarray
89    @property
90    def output_steps(self) -> np.ndarray:
91        return np.arange(0, self.nt + 1, self.steps_per_output_interval)