Skip to content

Commit d8ba293

Browse files
authored
Merge pull request #658 from slayoo/freezing
cleanups, null default for freezing spectrum, README update
2 parents a383324 + dfcf4a7 commit d8ba293

File tree

16 files changed

+142
-47
lines changed

16 files changed

+142
-47
lines changed

PySDM/dynamics/freezing.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
from PySDM.physics import constants
2-
from PySDM.physics.heterogeneous_ice_nucleation_rate import Constant, ABIFM
1+
from PySDM.physics.heterogeneous_ice_nucleation_rate import Null
2+
33

44
class Freezing:
55
def __init__(self, *, singular=True):
66
self.singular = singular
77
self.enable = True
88
self.rand = None
99
self.rng = None
10+
self.particulator = None
1011

1112
def register(self, builder):
1213
self.particulator = builder.particulator
@@ -15,6 +16,7 @@ def register(self, builder):
1516
if self.singular:
1617
builder.request_attribute("freezing temperature")
1718
else:
19+
assert not isinstance(builder.formulae.heterogeneous_ice_nucleation_rate, Null)
1820
builder.request_attribute("immersed surface area")
1921
self.rand = self.particulator.Storage.empty(self.particulator.n_sd, dtype=float)
2022
self.rng = self.particulator.Random(self.particulator.n_sd, self.particulator.bck.formulae.seed)

PySDM/environments/box.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ def __getitem__(self, item):
1818
return self._ambient_air[item]
1919

2020
def __setitem__(self, key, value):
21-
self._ambient_air[key] = self.particulator.backend.Storage.from_ndarray(np.array([value]))
21+
if key not in self._ambient_air:
22+
self._ambient_air[key] = self.particulator.backend.Storage.from_ndarray(np.array([value]))
23+
else:
24+
self._ambient_air[key][:] = value
2225

2326
def register(self, builder):
2427
self.particulator = builder.particulator

PySDM/initialisation/multiplicities.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ def discretise_n(y_float):
1212
raise Exception(f"{percent_diff}% error in total real-droplet number due to casting multiplicities to ints")
1313

1414
if not (y_int > 0).all():
15-
raise Exception("int-casting resulted in multiplicity of zero")
15+
raise Exception(f"int-casting resulted in multiplicity of zero (min(y_float)={min(y_float)})")
1616

1717
return y_int

PySDM/initialisation/spectral_sampling.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import numpy as np
22
from typing import Tuple
3+
from scipy import optimize
34
from PySDM.physics import constants as const
45

56
default_cdf_range = (.00001, .99999)
@@ -10,7 +11,14 @@ def __init__(self, spectrum, size_range: [None, Tuple[float, float]] = None):
1011
self.spectrum = spectrum
1112

1213
if size_range is None:
13-
self.size_range = spectrum.percentiles(default_cdf_range)
14+
if hasattr(spectrum, 'percentiles'):
15+
self.size_range = spectrum.percentiles(default_cdf_range)
16+
else:
17+
self.size_range = [np.nan, np.nan]
18+
for i in (0, 1):
19+
result = optimize.root(lambda x: spectrum.cdf(x) - default_cdf_range[i], x0=spectrum.median())
20+
assert result.success
21+
self.size_range[i] = result.x
1422
else:
1523
assert len(size_range) == 2
1624
assert size_range[0] > 0
@@ -69,12 +77,13 @@ def sample(self, n_sd):
6977

7078
return self._sample(percentiles, self.spectrum)
7179

80+
7281
class UniformRandom(SpectralSampling):
7382
def __init__(self, spectrum, size_range=None, seed=const.default_random_seed):
7483
super().__init__(spectrum, size_range)
7584
self.rng = np.random.default_rng(seed)
7685

7786
def sample(self, n_sd):
7887
pdf_arg = self.rng.uniform(*self.size_range, n_sd)
79-
dr = (self.size_range[1] - self.size_range[0]) / n_sd
88+
dr = abs(self.size_range[1] - self.size_range[0]) / n_sd
8089
return pdf_arg, dr * self.spectrum.size_distribution(pdf_arg)

PySDM/physics/formulae.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def _pick(value: str, choices: dict):
6565
for name, cls in choices.items():
6666
if name == value:
6767
return cls()
68-
raise ValueError(f"Unknown setting: '{value}';, choices are: {tuple(choices.keys())}")
68+
raise ValueError(f"Unknown setting: '{value}'; choices are: {tuple(choices.keys())}")
6969

7070

7171
def _choices(module):
@@ -93,7 +93,7 @@ def __init__(self, *,
9393
state_variable_triplet: str = 'RhodThdQv',
9494
particle_advection: str = 'ImplicitInSpace',
9595
hydrostatics: str = 'Default',
96-
freezing_temperature_spectrum: str = 'Niemand_et_al_2012',
96+
freezing_temperature_spectrum: str = 'Null',
9797
heterogeneous_ice_nucleation_rate: str = 'Null'
9898
):
9999
self.seed = seed
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
from .niemand_et_al_2012 import Niemand_et_al_2012
1+
from .niemand_et_al_2012 import Niemand_et_al_2012
2+
from .bigg_1953 import Bigg_1953
3+
from .null import Null
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import numpy as np
2+
from PySDM.physics import constants as const
3+
4+
P_median = .5
5+
DT_median = np.nan
6+
7+
# TODO #599: there are two Bigg 1953 papers
8+
# TODO #599: relate DT to drop volume to A_insol? (the second paper!)
9+
10+
11+
class Bigg_1953:
12+
def __init__(self):
13+
assert np.isfinite(DT_median)
14+
15+
@staticmethod
16+
def pdf(T, A_insol):
17+
A = np.log(1 - P_median)
18+
B = DT_median - const.T0
19+
return - A * np.exp(A * np.exp(B + T) + B + T)
20+
21+
@staticmethod
22+
def cdf(T, A_insol):
23+
return np.exp(np.log(1 - P_median) * np.exp(DT_median - (const.T0 - T)))
24+
25+
@staticmethod
26+
def median():
27+
return const.T0 - DT_median
Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
1-
from PySDM.physics import constants as const, si
1+
from PySDM.physics import constants as const
22
import numpy as np
33

4-
a = -0.517
5-
b = 8.934
6-
A_insol = const.pi * (1*si.um)**2
4+
a = np.nan
5+
b = np.nan
6+
77

88
class Niemand_et_al_2012:
99
def __str__(self):
1010
return 'Niemand et al. 2012'
1111

12+
def __init__(self):
13+
assert np.isfinite(a)
14+
assert np.isfinite(b)
15+
1216
@staticmethod
13-
def pdf(T):
17+
def pdf(T, A_insol):
1418
ns_T = np.exp(a * (T - const.T0) + b)
1519
return -A_insol * a * ns_T * np.exp(-A_insol * ns_T)
1620

1721
@staticmethod
18-
def cdf(T):
22+
def cdf(T, A_insol):
1923
ns_T = np.exp(a * (T - const.T0) + b)
2024
return 1 - np.exp(-A_insol * ns_T) - np.exp(-A_insol*np.exp(-a * const.T0 + b))
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class Null:
2+
@staticmethod
3+
def cdf(T):
4+
pass

PySDM/physics/heterogeneous_ice_nucleation_rate/abifm.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
c = np.inf
66
unit = 1 / si.cm**2 / si.s
77

8+
89
class ABIFM:
910
@staticmethod
1011
def _check():

0 commit comments

Comments
 (0)