Skip to content

Commit 169dc5d

Browse files
tluettmslayooAgnieszkaZaba
authored
Homogeneous freezing example + FIX for mark updated attributes in homogeneous freezing and thaw + expanded unit test of record freezing temperature (#1682)
Co-authored-by: Sylwester Arabas <sylwester.arabas@agh.edu.pl> Co-authored-by: Agnieszka Żaba <azaba@agh.edu.pl>
1 parent eb594ea commit 169dc5d

25 files changed

Lines changed: 3957 additions & 17 deletions

File tree

.github/workflows/tests.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ jobs:
185185
test-suite: "tests/smoke_tests/parcel_d"
186186
fail-fast: true
187187
runs-on: ${{ matrix.platform }}
188-
timeout-minutes: ${{ startsWith(matrix.platform, 'windows-') && 35 || 22 }}
188+
timeout-minutes: ${{ startsWith(matrix.platform, 'windows-') && 35 || 25 }}
189189
steps:
190190
- uses: actions/checkout@v4.1.6
191191
with:
@@ -212,7 +212,8 @@ jobs:
212212
python-version: ["3.12"]
213213
test-suite:
214214
- "isotopes_chemistry_extraterrestrial"
215-
- "coagulation_freezing"
215+
- "homogeneous_freezing"
216+
- "coagulation_immersion_freezing"
216217
- "condensation_a"
217218
- "condensation_b"
218219
- "condensation_c"
@@ -237,7 +238,12 @@ jobs:
237238
test-suite: "multi-process_d"
238239
- platform: "macos-14"
239240
test-suite: "multi-process_e"
240-
fail-fast: true
241+
# TODO #1870
242+
- platform: "ubuntu-24.04"
243+
test-suite: "homogeneous_freezing"
244+
- platform: "windows-latest"
245+
test-suite: "homogeneous_freezing"
246+
fail-fast: false
241247
runs-on: ${{ matrix.platform }}
242248
timeout-minutes: ${{ startsWith(matrix.platform, 'windows-') && 35 || 30 }}
243249
steps:
@@ -288,7 +294,7 @@ jobs:
288294
python -m pytest ${{ env.pytest_options }} tests/examples_tests/test_tests_completeness.py
289295
- run: |
290296
python -m pip install pytest-timeout
291-
python -m pytest ${{ env.pytest_options }} --basetemp=/tmp/pytest --timeout_method=thread --timeout=${{ startsWith(matrix.platform, 'windows-') && 1000 || 900 }} tests/examples_tests/test_run* --suite ${{ matrix.test-suite }}
297+
python -m pytest ${{ env.pytest_options }} --basetemp=/tmp/pytest --timeout_method=thread --timeout=${{ startsWith(matrix.platform, 'windows-') && 1200 || 900 }} tests/examples_tests/test_run* --suite ${{ matrix.test-suite }}
292298
293299
- if: ( ! startsWith(matrix.platform, 'windows-') ) && contains(matrix.test-suite, env.anim_test-suite) && matrix.python-version == env.anim_python-version
294300
run: |

PySDM/backends/impl_numba/test_helpers/scipy_ode_condensation_solver.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def _condensation(
8383
RH_max=RH_max.data,
8484
success=success.data,
8585
)
86-
particulator.attributes.mark_updated("water mass")
86+
particulator.attributes.mark_updated("signed water mass")
8787

8888

8989
@lru_cache()

PySDM/particulator.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ def homogeneous_freezing_time_dependent(self, *, rand: Storage):
573573
temperature=self.environment["T"],
574574
relative_humidity_ice=self.environment["RH_ice"],
575575
)
576+
self.attributes.mark_updated("signed water mass")
576577

577578
def homogeneous_freezing_threshold(self):
578579
self.backend.homogeneous_freezing_threshold(
@@ -583,6 +584,7 @@ def homogeneous_freezing_threshold(self):
583584
temperature=self.environment["T"],
584585
relative_humidity_ice=self.environment["RH_ice"],
585586
)
587+
self.attributes.mark_updated("signed water mass")
586588

587589
def thaw_instantaneous(self):
588590
self.backend.thaw_instantaneous(
@@ -592,3 +594,4 @@ def thaw_instantaneous(self):
592594
cell=self.attributes["cell id"],
593595
temperature=self.environment["T"],
594596
)
597+
self.attributes.mark_updated("signed water mass")

PySDM/physics/constants_defaults.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,16 @@
356356
KOOP_MURRAY_C6 = -7.46953e-7 / si.K**6
357357
""" 〃 """
358358

359+
KOOP_MURRAY_DAW_C0 = -273.111686
360+
""" homogeneous ice nucleation rate for pure water droplets adapted
361+
for DAW ([Spichtinger et al. 2023](https://doi.org/10.5194/acp-23-2035-2023)) """
362+
KOOP_MURRAY_DAW_C1 = 1689.25134
363+
""" 〃 """
364+
KOOP_MURRAY_DAW_C2 = -2449.65042
365+
""" 〃 """
366+
KOOP_MURRAY_DAW_UNIT = 1 / si.m**3 / si.s
367+
""" 〃 """
368+
359369
J_HET = np.nan
360370
J_HOM = np.nan
361371
""" constant ice nucleation rates """

PySDM/physics/homogeneous_ice_nucleation_rate/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
from .koop import Koop2000
88
from .koop_corr import Koop_Correction
99
from .koop_murray import KoopMurray2016
10+
from .koop_murray_dwa_adaption import KoopMurray2016_DWA
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""
2+
Koop and Murray homogeneous nucleation rate parameterization for pure water droplets
3+
adapted for water activity formulation
4+
([Spichtinger et al. 2023](https://doi.org/10.5194/acp-23-2035-2023))
5+
"""
6+
7+
import numpy as np
8+
9+
10+
class KoopMurray2016_DWA:
11+
def __init__(self, const):
12+
pass
13+
14+
@staticmethod
15+
def d_a_w_ice_within_range(const, da_w_ice):
16+
return da_w_ice >= const.KOOP_MIN_DA_W_ICE
17+
18+
@staticmethod
19+
def d_a_w_ice_maximum(const, da_w_ice):
20+
return np.where(
21+
da_w_ice > const.KOOP_MAX_DA_W_ICE, const.KOOP_MAX_DA_W_ICE, da_w_ice
22+
)
23+
24+
@staticmethod
25+
def j_hom(const, T, da_w_ice): # pylint: disable=unused-argument
26+
return (
27+
10
28+
** (
29+
const.KOOP_MURRAY_DAW_C0
30+
+ const.KOOP_MURRAY_DAW_C1 * da_w_ice
31+
+ const.KOOP_MURRAY_DAW_C2 * da_w_ice**2.0
32+
)
33+
* const.KOOP_MURRAY_DAW_UNIT
34+
)

docs/bibliography.json

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,7 @@
948948
"PySDM/physics/constants_defaults.py",
949949
"PySDM/physics/diffusion_ice_capacity/columnar.py",
950950
"PySDM/physics/homogeneous_ice_nucleation_rate/koop_corr.py",
951+
"PySDM/physics/homogeneous_ice_nucleation_rate/koop_murray_dwa_adaption.py",
951952
"examples/PySDM_examples/Spichtinger_et_al_2023/__init__.py",
952953
"examples/PySDM_examples/Spichtinger_et_al_2023/data/reference_bulk.py",
953954
"examples/PySDM_examples/Spichtinger_et_al_2023/fig_B1.ipynb",
@@ -1014,14 +1015,22 @@
10141015
"label": "Bartman 2020 (MSc thesis)",
10151016
"title": "PySDM v1.0: Pythonic particle-based cloud microphysics package"
10161017
},
1017-
"https://web.archive.org/web/20220629123450/https://web.gps.caltech.edu/~als/research-articles/other_stuff/hayes-2004-3.pdf" : {
1018+
"https://web.archive.org/web/20220629123450/https://web.gps.caltech.edu/~als/research-articles/other_stuff/hayes-2004-3.pdf" : {
10181019
"usages": [
10191020
"tests/unit_tests/physics/test_constants.py"
10201021
],
10211022
"label": "Hayes 2004",
10221023
"title": "An Introduction to Isotopic Calculations"
10231024
},
1024-
"https://doi.org/10.1175/1520-0469%281974%29031%3C1040%3ASTTDCE%3E2.0.CO%3B2" : {
1025+
"https://doi.org/10.1039/c003297b": {
1026+
"usages": [
1027+
"examples/PySDM_examples/Murray_et_al_2010/fig_3.ipynb",
1028+
"examples/PySDM_examples/Murray_et_al_2010/__init__.py"
1029+
],
1030+
"title": "Kinetics of the homogeneous freezing of water",
1031+
"label": "Murray et al. 2010 (Phys. Chem. Chem. Phys. 12)"
1032+
},
1033+
"https://doi.org/10.1175/1520-0469%281974%29031%3C1040%3ASTTDCE%3E2.0.CO%3B2": {
10251034
"usages": [
10261035
"PySDM/dynamics/collisions/collision_kernels/long1974.py",
10271036
"examples/PySDM_examples/Long_1974/__init__.py",
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""
2+
Homogeneous freezing example
3+
4+
.. include:: ./fig_1_2_3.ipynb
5+
.. include:: ./fig_4_5_6_S3_S4.ipynb
6+
.. include:: ./fig_S1_S2.ipynb
7+
.. include:: ./simple_homogenous_freezing_example.ipynb
8+
"""
9+
10+
from .settings import Settings
11+
from .simulation import Simulation
12+
from .plot import (
13+
plot_thermodynamics_and_bulk,
14+
plot_freezing_temperatures_histogram,
15+
plot_freezing_temperatures_histogram_allinone,
16+
plot_freezing_temperatures_2d_histogram_seaborn,
17+
)
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
"""commons for homogeneous freezing notebooks"""
2+
3+
from PySDM_examples.Luettmer_homogeneous_freezing.settings import Settings
4+
from PySDM_examples.Luettmer_homogeneous_freezing.simulation import Simulation
5+
from PySDM import Formulae
6+
from PySDM.physics.constants import si
7+
from PySDM.backends import CPU
8+
9+
formulae = Formulae(
10+
particle_shape_and_density="MixedPhaseSpheres",
11+
)
12+
13+
14+
def run_simulations(setting):
15+
16+
simulation = {
17+
"settings": setting,
18+
"ensemble_member_outputs": [],
19+
}
20+
for _ in range(setting["number_of_ensemble_runs"]):
21+
model_setup = Settings(**simulation["settings"])
22+
model_setup.formulae.seed += 1
23+
model = Simulation(model_setup)
24+
simulation["ensemble_member_outputs"].append(model.run())
25+
26+
return simulation
27+
28+
29+
def hom_pure_droplet_freezing_backend():
30+
cmn = {"override_jit_flags": {"parallel": False}}
31+
backends = {
32+
"threshold": CPU(
33+
formulae=Formulae(
34+
particle_shape_and_density="MixedPhaseSpheres",
35+
homogeneous_ice_nucleation_rate="Null",
36+
saturation_vapour_pressure="MurphyKoop2005",
37+
),
38+
**cmn,
39+
),
40+
"KoopMurray2016": CPU(
41+
formulae=Formulae(
42+
particle_shape_and_density="MixedPhaseSpheres",
43+
homogeneous_ice_nucleation_rate="KoopMurray2016",
44+
saturation_vapour_pressure="MurphyKoop2005",
45+
),
46+
**cmn,
47+
),
48+
"Spichtinger2023": CPU(
49+
formulae=Formulae(
50+
particle_shape_and_density="MixedPhaseSpheres",
51+
homogeneous_ice_nucleation_rate="Koop_Correction",
52+
saturation_vapour_pressure="MurphyKoop2005",
53+
),
54+
**cmn,
55+
),
56+
"Koop2000": CPU(
57+
formulae=Formulae(
58+
particle_shape_and_density="MixedPhaseSpheres",
59+
homogeneous_ice_nucleation_rate="Koop2000",
60+
saturation_vapour_pressure="MurphyKoop2005",
61+
),
62+
**cmn,
63+
),
64+
"KoopMurray2016_DWA": CPU(
65+
formulae=Formulae(
66+
particle_shape_and_density="MixedPhaseSpheres",
67+
homogeneous_ice_nucleation_rate="KoopMurray2016_DWA",
68+
saturation_vapour_pressure="MurphyKoop2005",
69+
),
70+
**cmn,
71+
),
72+
}
73+
return backends
74+
75+
76+
def hom_pure_droplet_freezing_standard_setup():
77+
standard = {
78+
"n_sd": int(1e3),
79+
"w_updraft": 1.0 * si.meter / si.second,
80+
"T0": 245 * si.kelvin,
81+
"dz": 1.0 * si.meter,
82+
"n_ccn": 750 / si.cm**3,
83+
"r_ccn": 15 * si.nanometer,
84+
"type_droplet_distribution": "monodisperse",
85+
"RH_0": 0.995,
86+
"p0": 500 * si.hectopascals,
87+
"deposition_enable": True,
88+
"number_of_ensemble_runs": 1,
89+
"silent": True,
90+
}
91+
return standard

0 commit comments

Comments
 (0)