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