PySDM_examples.featured.Lowe_et_al_2019.settings

 1from functools import lru_cache
 2
 3import numpy as np
 4from PySDM_examples.featured.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    )
27
28
29@strict
30class Settings:
31    def __init__(
32        self,
33        dz: float,
34        n_sd_per_mode: int,
35        aerosol: DryAerosolMixture,
36        model: str,
37        w: float = 0.32 * si.m / si.s,
38    ):
39        assert model in ("Constant", "CompressedFilmOvadnevaite")
40        self.model = model
41        self.n_sd_per_mode = n_sd_per_mode
42        self.backend = backend(model)
43        self.formulae = self.backend.formulae
44        const = self.formulae.constants
45        self.aerosol = aerosol
46
47        max_altitude = 200 * si.m
48        self.w = w
49        self.t_max = max_altitude / self.w
50        self.dt = dz / self.w
51        self.output_interval = 1 * self.dt
52
53        self.p0 = 980 * si.mbar
54        self.T0 = 280 * si.K
55        pv0 = 0.999 * self.formulae.saturation_vapour_pressure.pvs_water(self.T0)
56        self.initial_water_vapour_mixing_ratio = const.eps * pv0 / (self.p0 - pv0)
57
58        self.cloud_radius_range = (0.5 * si.micrometre, np.inf)
59
60        self.mass_of_dry_air = 44
61
62        self.wet_radius_bins_edges = np.logspace(
63            np.log10(4 * si.um), np.log10(12 * si.um), 128 + 1, endpoint=True
64        )
65
66    @property
67    def rho0(self):
68        const = self.formulae.constants
69        rhod0 = (
70            self.formulae.trivia.p_d(self.p0, self.initial_water_vapour_mixing_ratio)
71            / self.T0
72            / const.Rd
73        )
74        return rhod0 * (1 + self.initial_water_vapour_mixing_ratio)
75
76    @property
77    def nt(self) -> int:
78        nt = self.t_max / self.dt
79        nt_int = round(nt)
80        np.testing.assert_almost_equal(nt, nt_int)
81        return nt_int
82
83    @property
84    def steps_per_output_interval(self) -> int:
85        return int(self.output_interval / self.dt)
86
87    @property
88    def output_steps(self) -> np.ndarray:
89        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    )
@strict
class Settings:
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)
Settings( dz: float, n_sd_per_mode: int, aerosol: PySDM.initialisation.aerosol_composition.dry_aerosol.DryAerosolMixture, model: str, w: float = 0.32)
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        )
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
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)
nt: int
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
steps_per_output_interval: int
84    @property
85    def steps_per_output_interval(self) -> int:
86        return int(self.output_interval / self.dt)
output_steps: numpy.ndarray
88    @property
89    def output_steps(self) -> np.ndarray:
90        return np.arange(0, self.nt + 1, self.steps_per_output_interval)