PySDM_examples.deJong_Mackay_et_al_2023.simulation_0D

  1from collections import namedtuple
  2
  3import numpy as np
  4
  5from PySDM.backends import CPU
  6from PySDM.particulator import Particulator
  7from PySDM.dynamics import Coalescence, Collision
  8from PySDM.environments import Box
  9from PySDM.formulae import Formulae
 10from PySDM.initialisation.sampling.spectral_sampling import (
 11    ConstantMultiplicity,
 12    Logarithmic,
 13)
 14from PySDM.physics import si
 15from PySDM.products.collision.collision_rates import (
 16    BreakupRatePerGridbox,
 17    CoalescenceRatePerGridbox,
 18    CollisionRateDeficitPerGridbox,
 19    CollisionRatePerGridbox,
 20)
 21from PySDM.products.size_spectral import (
 22    NumberSizeSpectrum,
 23    ParticleVolumeVersusRadiusLogarithmSpectrum,
 24)
 25
 26
 27def run_box_breakup(
 28    settings, steps=None, backend_class=CPU, sample_in_radius=False, return_nv=False
 29):
 30    environment = Box(
 31        dv=settings.dv, dt=settings.dt, backend=backend_class(settings.formulae)
 32    )
 33    environment["rhod"] = 1.0
 34    attributes = {}
 35    if sample_in_radius:
 36        diams, attributes["multiplicity"] = Logarithmic(
 37            settings.spectrum
 38        ).sample_deterministic(settings.n_sd)
 39        radii = diams / 2
 40        attributes["volume"] = Formulae().trivia.volume(radius=radii)
 41    else:
 42        attributes["volume"], attributes["multiplicity"] = ConstantMultiplicity(
 43            settings.spectrum
 44        ).sample_deterministic(settings.n_sd)
 45    products = (
 46        ParticleVolumeVersusRadiusLogarithmSpectrum(
 47            radius_bins_edges=settings.radius_bins_edges, name="dv/dlnr"
 48        ),
 49        NumberSizeSpectrum(radius_bins_edges=settings.radius_bins_edges, name="N(v)"),
 50        CollisionRatePerGridbox(name="cr"),
 51        CollisionRateDeficitPerGridbox(name="crd"),
 52        CoalescenceRatePerGridbox(name="cor"),
 53        BreakupRatePerGridbox(name="br"),
 54    )
 55    core = Particulator(
 56        n_sd=settings.n_sd,
 57        environment=environment,
 58        dynamics=(
 59            Collision(
 60                collision_kernel=settings.kernel,
 61                coalescence_efficiency=settings.coal_eff,
 62                breakup_efficiency=settings.break_eff,
 63                fragmentation_function=settings.fragmentation,
 64                adaptive=settings.adaptive,
 65                warn_overflows=settings.warn_overflows,
 66            ),
 67        ),
 68        attributes=attributes,
 69        products=products,
 70    )
 71
 72    if steps is None:
 73        steps = settings.output_steps
 74    y = np.ndarray((len(steps), len(settings.radius_bins_edges) - 1))
 75    if return_nv:
 76        y2 = np.ndarray((len(steps), len(settings.radius_bins_edges) - 1))
 77    else:
 78        y2 = None
 79
 80    rates = np.zeros((len(steps), 4))
 81    # run
 82    for i, step in enumerate(steps):
 83        core.run(step - core.n_steps)
 84        y[i] = core.products["dv/dlnr"].get()[0]
 85        if return_nv:
 86            (y2[i],) = core.products["N(v)"].get()
 87        (rates[i, 0],) = core.products["cr"].get()
 88        (rates[i, 1],) = core.products["crd"].get()
 89        (rates[i, 2],) = core.products["cor"].get()
 90        (rates[i, 3],) = core.products["br"].get()
 91
 92    x = (settings.radius_bins_edges[:-1] / si.micrometres,)[0]
 93
 94    return namedtuple("_", ("x", "y", "y2", "rates"))(x=x, y=y, y2=y2, rates=rates)
 95
 96
 97def run_box_NObreakup(settings, steps=None, backend_class=CPU):
 98    environment = Box(
 99        dv=settings.dv, dt=settings.dt, backend=backend_class(settings.formulae)
100    )
101    environment["rhod"] = 1.0
102    attributes = {}
103    attributes["volume"], attributes["multiplicity"] = ConstantMultiplicity(
104        settings.spectrum
105    ).sample_deterministic(settings.n_sd)
106    products = (
107        ParticleVolumeVersusRadiusLogarithmSpectrum(
108            radius_bins_edges=settings.radius_bins_edges, name="dv/dlnr"
109        ),
110        CollisionRatePerGridbox(name="cr"),
111        CollisionRateDeficitPerGridbox(name="crd"),
112        CoalescenceRatePerGridbox(name="cor"),
113    )
114    core = Particulator(
115        n_sd=settings.n_sd,
116        environment=environment,
117        dynamics=(
118            Coalescence(
119                collision_kernel=settings.kernel,
120                coalescence_efficiency=settings.coal_eff,
121                adaptive=settings.adaptive,
122            ),
123        ),
124        attributes=attributes,
125        products=products,
126    )
127
128    if steps is None:
129        steps = settings.output_steps
130    y = np.ndarray((len(steps), len(settings.radius_bins_edges) - 1))
131    rates = np.zeros((len(steps), 4))
132    # run
133    for i, step in enumerate(steps):
134        core.run(step - core.n_steps)
135        (y[i],) = core.products["dv/dlnr"].get()
136        (rates[i, 0],) = core.products["cr"].get()
137        (rates[i, 1],) = core.products["crd"].get()
138        (rates[i, 2],) = core.products["cor"].get()
139
140    x = (settings.radius_bins_edges[:-1] / si.micrometres,)[0]
141
142    return (x, y, rates)
def run_box_breakup( settings, steps=None, backend_class=functools.partial(<function _cached_backend>, backend_class=<class 'PySDM.backends.Numba'>), sample_in_radius=False, return_nv=False):
28def run_box_breakup(
29    settings, steps=None, backend_class=CPU, sample_in_radius=False, return_nv=False
30):
31    environment = Box(
32        dv=settings.dv, dt=settings.dt, backend=backend_class(settings.formulae)
33    )
34    environment["rhod"] = 1.0
35    attributes = {}
36    if sample_in_radius:
37        diams, attributes["multiplicity"] = Logarithmic(
38            settings.spectrum
39        ).sample_deterministic(settings.n_sd)
40        radii = diams / 2
41        attributes["volume"] = Formulae().trivia.volume(radius=radii)
42    else:
43        attributes["volume"], attributes["multiplicity"] = ConstantMultiplicity(
44            settings.spectrum
45        ).sample_deterministic(settings.n_sd)
46    products = (
47        ParticleVolumeVersusRadiusLogarithmSpectrum(
48            radius_bins_edges=settings.radius_bins_edges, name="dv/dlnr"
49        ),
50        NumberSizeSpectrum(radius_bins_edges=settings.radius_bins_edges, name="N(v)"),
51        CollisionRatePerGridbox(name="cr"),
52        CollisionRateDeficitPerGridbox(name="crd"),
53        CoalescenceRatePerGridbox(name="cor"),
54        BreakupRatePerGridbox(name="br"),
55    )
56    core = Particulator(
57        n_sd=settings.n_sd,
58        environment=environment,
59        dynamics=(
60            Collision(
61                collision_kernel=settings.kernel,
62                coalescence_efficiency=settings.coal_eff,
63                breakup_efficiency=settings.break_eff,
64                fragmentation_function=settings.fragmentation,
65                adaptive=settings.adaptive,
66                warn_overflows=settings.warn_overflows,
67            ),
68        ),
69        attributes=attributes,
70        products=products,
71    )
72
73    if steps is None:
74        steps = settings.output_steps
75    y = np.ndarray((len(steps), len(settings.radius_bins_edges) - 1))
76    if return_nv:
77        y2 = np.ndarray((len(steps), len(settings.radius_bins_edges) - 1))
78    else:
79        y2 = None
80
81    rates = np.zeros((len(steps), 4))
82    # run
83    for i, step in enumerate(steps):
84        core.run(step - core.n_steps)
85        y[i] = core.products["dv/dlnr"].get()[0]
86        if return_nv:
87            (y2[i],) = core.products["N(v)"].get()
88        (rates[i, 0],) = core.products["cr"].get()
89        (rates[i, 1],) = core.products["crd"].get()
90        (rates[i, 2],) = core.products["cor"].get()
91        (rates[i, 3],) = core.products["br"].get()
92
93    x = (settings.radius_bins_edges[:-1] / si.micrometres,)[0]
94
95    return namedtuple("_", ("x", "y", "y2", "rates"))(x=x, y=y, y2=y2, rates=rates)
def run_box_NObreakup( settings, steps=None, backend_class=functools.partial(<function _cached_backend>, backend_class=<class 'PySDM.backends.Numba'>)):
 98def run_box_NObreakup(settings, steps=None, backend_class=CPU):
 99    environment = Box(
100        dv=settings.dv, dt=settings.dt, backend=backend_class(settings.formulae)
101    )
102    environment["rhod"] = 1.0
103    attributes = {}
104    attributes["volume"], attributes["multiplicity"] = ConstantMultiplicity(
105        settings.spectrum
106    ).sample_deterministic(settings.n_sd)
107    products = (
108        ParticleVolumeVersusRadiusLogarithmSpectrum(
109            radius_bins_edges=settings.radius_bins_edges, name="dv/dlnr"
110        ),
111        CollisionRatePerGridbox(name="cr"),
112        CollisionRateDeficitPerGridbox(name="crd"),
113        CoalescenceRatePerGridbox(name="cor"),
114    )
115    core = Particulator(
116        n_sd=settings.n_sd,
117        environment=environment,
118        dynamics=(
119            Coalescence(
120                collision_kernel=settings.kernel,
121                coalescence_efficiency=settings.coal_eff,
122                adaptive=settings.adaptive,
123            ),
124        ),
125        attributes=attributes,
126        products=products,
127    )
128
129    if steps is None:
130        steps = settings.output_steps
131    y = np.ndarray((len(steps), len(settings.radius_bins_edges) - 1))
132    rates = np.zeros((len(steps), 4))
133    # run
134    for i, step in enumerate(steps):
135        core.run(step - core.n_steps)
136        (y[i],) = core.products["dv/dlnr"].get()
137        (rates[i, 0],) = core.products["cr"].get()
138        (rates[i, 1],) = core.products["crd"].get()
139        (rates[i, 2],) = core.products["cor"].get()
140
141    x = (settings.radius_bins_edges[:-1] / si.micrometres,)[0]
142
143    return (x, y, rates)