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 )