PySDM_examples.Spichtinger_et_al_2023.simulation
1import numpy as np 2 3from PySDM_examples.utils import BasicSimulation 4 5import PySDM.products as PySDM_products 6from PySDM.backends import CPU 7from PySDM.builder import Builder 8from PySDM.dynamics import ( 9 AmbientThermodynamics, 10 Condensation, 11 Freezing, 12 VapourDepositionOnIce, 13) 14from PySDM.environments import Parcel 15from PySDM.initialisation import discretise_multiplicities, equilibrate_wet_radii 16 17 18class Simulation(BasicSimulation): 19 def __init__(self, settings, backend=CPU): 20 21 dt = settings.dt 22 23 formulae = settings.formulae 24 25 env = Parcel( 26 mixed_phase=True, 27 dt=dt, 28 mass_of_dry_air=settings.mass_of_dry_air, 29 p0=settings.initial_pressure, 30 initial_water_vapour_mixing_ratio=settings.initial_water_vapour_mixing_ratio, 31 T0=settings.initial_temperature, 32 w=settings.w_updraft, 33 ) 34 35 builder = Builder( 36 backend=backend( 37 formulae=settings.formulae, 38 **( 39 {"override_jit_flags": {"parallel": False}} 40 if backend == CPU 41 else {} 42 ), 43 ), 44 n_sd=settings.n_sd, 45 environment=env, 46 ) 47 48 builder.add_dynamic(AmbientThermodynamics()) 49 builder.add_dynamic(Condensation()) 50 builder.add_dynamic(VapourDepositionOnIce()) 51 builder.add_dynamic( 52 Freezing( 53 singular=False, homogeneous_freezing=True, immersion_freezing=False 54 ) 55 ) 56 57 self.n_sd = settings.n_sd 58 self.multiplicities = discretise_multiplicities( 59 settings.specific_concentration * env.mass_of_dry_air 60 ) 61 self.r_dry = settings.r_dry 62 v_dry = settings.formulae.trivia.volume(radius=self.r_dry) 63 kappa = settings.kappa 64 65 self.r_wet = equilibrate_wet_radii( 66 r_dry=self.r_dry, 67 environment=builder.particulator.environment, 68 kappa_times_dry_volume=kappa * v_dry, 69 ) 70 71 attributes = { 72 "multiplicity": self.multiplicities, 73 "dry volume": v_dry, 74 "kappa times dry volume": kappa * v_dry, 75 "signed water mass": formulae.particle_shape_and_density.radius_to_mass( 76 self.r_wet 77 ), 78 } 79 80 products = [ 81 PySDM_products.Time(name="t"), 82 PySDM_products.AmbientRelativeHumidity(name="RH_ice", unit="%"), 83 PySDM_products.ParticleConcentration( 84 name="n_i", unit="1/m**3", radius_range=(-np.inf, 0) 85 ), 86 ] 87 88 self.n_output = settings.n_output 89 self.n_substeps = int(settings.t_duration / dt / self.n_output) 90 super().__init__(builder.build(attributes, products)) 91 92 def save(self, output): 93 cell_id = 0 94 output["t"].append(self.particulator.products["t"].get()) 95 output["ni"].append(self.particulator.products["n_i"].get()[cell_id]) 96 output["RHi"].append(self.particulator.products["RH_ice"].get()[cell_id]) 97 98 def run(self): 99 output = { 100 "t": [], 101 "ni": [], 102 "RHi": [], 103 } 104 105 self.save(output) 106 107 RHi_old = self.particulator.products["RH_ice"].get()[0].copy() 108 for _ in range(self.n_output): 109 110 self.particulator.run(self.n_substeps) 111 112 self.save(output) 113 114 RHi = self.particulator.products["RH_ice"].get()[0].copy() 115 dRHi = (RHi_old - RHi) / RHi_old 116 if dRHi > 0.0 and RHi < 130.0: 117 print("break") 118 break 119 RHi_old = RHi 120 121 return output["ni"][-1]
19class Simulation(BasicSimulation): 20 def __init__(self, settings, backend=CPU): 21 22 dt = settings.dt 23 24 formulae = settings.formulae 25 26 env = Parcel( 27 mixed_phase=True, 28 dt=dt, 29 mass_of_dry_air=settings.mass_of_dry_air, 30 p0=settings.initial_pressure, 31 initial_water_vapour_mixing_ratio=settings.initial_water_vapour_mixing_ratio, 32 T0=settings.initial_temperature, 33 w=settings.w_updraft, 34 ) 35 36 builder = Builder( 37 backend=backend( 38 formulae=settings.formulae, 39 **( 40 {"override_jit_flags": {"parallel": False}} 41 if backend == CPU 42 else {} 43 ), 44 ), 45 n_sd=settings.n_sd, 46 environment=env, 47 ) 48 49 builder.add_dynamic(AmbientThermodynamics()) 50 builder.add_dynamic(Condensation()) 51 builder.add_dynamic(VapourDepositionOnIce()) 52 builder.add_dynamic( 53 Freezing( 54 singular=False, homogeneous_freezing=True, immersion_freezing=False 55 ) 56 ) 57 58 self.n_sd = settings.n_sd 59 self.multiplicities = discretise_multiplicities( 60 settings.specific_concentration * env.mass_of_dry_air 61 ) 62 self.r_dry = settings.r_dry 63 v_dry = settings.formulae.trivia.volume(radius=self.r_dry) 64 kappa = settings.kappa 65 66 self.r_wet = equilibrate_wet_radii( 67 r_dry=self.r_dry, 68 environment=builder.particulator.environment, 69 kappa_times_dry_volume=kappa * v_dry, 70 ) 71 72 attributes = { 73 "multiplicity": self.multiplicities, 74 "dry volume": v_dry, 75 "kappa times dry volume": kappa * v_dry, 76 "signed water mass": formulae.particle_shape_and_density.radius_to_mass( 77 self.r_wet 78 ), 79 } 80 81 products = [ 82 PySDM_products.Time(name="t"), 83 PySDM_products.AmbientRelativeHumidity(name="RH_ice", unit="%"), 84 PySDM_products.ParticleConcentration( 85 name="n_i", unit="1/m**3", radius_range=(-np.inf, 0) 86 ), 87 ] 88 89 self.n_output = settings.n_output 90 self.n_substeps = int(settings.t_duration / dt / self.n_output) 91 super().__init__(builder.build(attributes, products)) 92 93 def save(self, output): 94 cell_id = 0 95 output["t"].append(self.particulator.products["t"].get()) 96 output["ni"].append(self.particulator.products["n_i"].get()[cell_id]) 97 output["RHi"].append(self.particulator.products["RH_ice"].get()[cell_id]) 98 99 def run(self): 100 output = { 101 "t": [], 102 "ni": [], 103 "RHi": [], 104 } 105 106 self.save(output) 107 108 RHi_old = self.particulator.products["RH_ice"].get()[0].copy() 109 for _ in range(self.n_output): 110 111 self.particulator.run(self.n_substeps) 112 113 self.save(output) 114 115 RHi = self.particulator.products["RH_ice"].get()[0].copy() 116 dRHi = (RHi_old - RHi) / RHi_old 117 if dRHi > 0.0 and RHi < 130.0: 118 print("break") 119 break 120 RHi_old = RHi 121 122 return output["ni"][-1]
Simulation(settings, backend=<class 'PySDM.backends.numba.Numba'>)
20 def __init__(self, settings, backend=CPU): 21 22 dt = settings.dt 23 24 formulae = settings.formulae 25 26 env = Parcel( 27 mixed_phase=True, 28 dt=dt, 29 mass_of_dry_air=settings.mass_of_dry_air, 30 p0=settings.initial_pressure, 31 initial_water_vapour_mixing_ratio=settings.initial_water_vapour_mixing_ratio, 32 T0=settings.initial_temperature, 33 w=settings.w_updraft, 34 ) 35 36 builder = Builder( 37 backend=backend( 38 formulae=settings.formulae, 39 **( 40 {"override_jit_flags": {"parallel": False}} 41 if backend == CPU 42 else {} 43 ), 44 ), 45 n_sd=settings.n_sd, 46 environment=env, 47 ) 48 49 builder.add_dynamic(AmbientThermodynamics()) 50 builder.add_dynamic(Condensation()) 51 builder.add_dynamic(VapourDepositionOnIce()) 52 builder.add_dynamic( 53 Freezing( 54 singular=False, homogeneous_freezing=True, immersion_freezing=False 55 ) 56 ) 57 58 self.n_sd = settings.n_sd 59 self.multiplicities = discretise_multiplicities( 60 settings.specific_concentration * env.mass_of_dry_air 61 ) 62 self.r_dry = settings.r_dry 63 v_dry = settings.formulae.trivia.volume(radius=self.r_dry) 64 kappa = settings.kappa 65 66 self.r_wet = equilibrate_wet_radii( 67 r_dry=self.r_dry, 68 environment=builder.particulator.environment, 69 kappa_times_dry_volume=kappa * v_dry, 70 ) 71 72 attributes = { 73 "multiplicity": self.multiplicities, 74 "dry volume": v_dry, 75 "kappa times dry volume": kappa * v_dry, 76 "signed water mass": formulae.particle_shape_and_density.radius_to_mass( 77 self.r_wet 78 ), 79 } 80 81 products = [ 82 PySDM_products.Time(name="t"), 83 PySDM_products.AmbientRelativeHumidity(name="RH_ice", unit="%"), 84 PySDM_products.ParticleConcentration( 85 name="n_i", unit="1/m**3", radius_range=(-np.inf, 0) 86 ), 87 ] 88 89 self.n_output = settings.n_output 90 self.n_substeps = int(settings.t_duration / dt / self.n_output) 91 super().__init__(builder.build(attributes, products))
def
run(self):
99 def run(self): 100 output = { 101 "t": [], 102 "ni": [], 103 "RHi": [], 104 } 105 106 self.save(output) 107 108 RHi_old = self.particulator.products["RH_ice"].get()[0].copy() 109 for _ in range(self.n_output): 110 111 self.particulator.run(self.n_substeps) 112 113 self.save(output) 114 115 RHi = self.particulator.products["RH_ice"].get()[0].copy() 116 dRHi = (RHi_old - RHi) / RHi_old 117 if dRHi > 0.0 and RHi < 130.0: 118 print("break") 119 break 120 RHi_old = RHi 121 122 return output["ni"][-1]