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