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 )