Skip to content

Commit 951cf14

Browse files
tluettmslayoo
andauthored
ice diffusion capacity: refactor for spherical & added columnar (+ several speedups in unrelated codes which started timeouting due to longer compilation time) (#1643)
Co-authored-by: Sylwester Arabas <[email protected]>
1 parent 156f86c commit 951cf14

File tree

19 files changed

+4932
-140
lines changed

19 files changed

+4932
-140
lines changed

.github/workflows/tests.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ jobs:
170170
run: |
171171
python -m pip uninstall -y jupyterlab-server # https://github.com/pypa/pip/issues/6275
172172
python -m pip install -e . -e ./examples
173+
python -m pip install pytest-timeout
173174
python -m pip install -r tests/devops_tests/requirements.txt
174175
- if: steps.cache.outputs.cache-hit != 'true'
175176
uses: actions/cache/save@v4
@@ -245,7 +246,7 @@ jobs:
245246
run: python -m pytest --basetemp=/tmp/pytest ${{ env.pytest_options }} tests/examples_tests/test_run* -k "not Rozanski_and_Sonntag_1982" --suite ${{ matrix.test-suite }}
246247

247248
- if: ( ! startsWith(matrix.platform, 'macos-13') )
248-
run: python -m pytest ${{ env.pytest_options }} --basetemp=/tmp/pytest tests/examples_tests/test_run* --suite ${{ matrix.test-suite }}
249+
run: 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 }}
249250

250251
- if: ( ! startsWith(matrix.platform, 'windows-') ) && matrix.test-suite == env.anim_test-suite && matrix.python-version == env.anim_python-version
251252
run: |

PySDM/backends/impl_numba/methods/deposition_methods.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def _deposition(self):
1616
formulae = self.formulae_flattened
1717

1818
@numba.njit(**{**self.default_jit_flags, **{"parallel": False}})
19-
def body( # pylint: disable=too-many-arguments
19+
def body( # pylint: disable=too-many-arguments,unused-argument
2020
*,
2121
multiplicity,
2222
signed_water_mass,
@@ -47,22 +47,15 @@ def body( # pylint: disable=too-many-arguments
4747
signed_water_mass[i]
4848
)
4949

50-
diameter = radius * 2.0
51-
5250
temperature = current_temperature[cid]
5351
pressure = current_total_pressure[cid]
5452
rho = current_dry_air_density[cid]
5553
pvs_ice = formulae.saturation_vapour_pressure__pvs_ice(temperature)
5654
latent_heat_sub = formulae.latent_heat_sublimation__ls(temperature)
5755

58-
capacity = formulae.diffusion_ice_capacity__capacity(diameter)
56+
capacity = formulae.diffusion_ice_capacity__capacity(ice_mass)
5957

60-
mass_ventilation_factor = formulae.ventilation__ventilation_coefficient(
61-
sqrt_re_times_cbrt_sc=formulae.trivia__sqrt_re_times_cbrt_sc(
62-
Re=reynolds_number[i],
63-
Sc=schmidt_number[cid],
64-
)
65-
)
58+
mass_ventilation_factor = 1 # TODO #1655
6659
heat_ventilation_factor = mass_ventilation_factor # TODO #1588
6760

6861
Dv_const = formulae.diffusion_thermics__D(temperature, pressure)
@@ -95,6 +88,7 @@ def body( # pylint: disable=too-many-arguments
9588
D=diffusion_coefficient * mass_ventilation_factor,
9689
pvs=pvs_ice,
9790
)
91+
9892
howell_factor_x_diffcoef_x_rhovsice_x_icess = (
9993
formulae.drop_growth__r_dr_dt(
10094
RH_eq=1,

PySDM/physics/constants_defaults.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,22 +90,24 @@
9090
N_A = sci.N_A / si.mole
9191
""" Avogadro constant (value from SciPy) """
9292

93-
# mass and heat accommodation coefficients for condensation
9493
MAC = 1.0
9594
""" mass accommodation coefficient of unity as recommended in
9695
[Laaksonen et al. 2005](https://doi.org/10.5194/acp-5-461-2005) """
9796
HAC = 1.0
9897
""" thermal accommodation coefficient of unity as recommended in
9998
[Laaksonen et al. 2005](https://doi.org/10.5194/acp-5-461-2005) """
10099

101-
# mass and heat accommodation coefficients for vapour deposition on ice
102100
MAC_ice = 0.5
103101
""" mass accommodation coefficient for vapour deposition as recommended in
104102
[Kaercher & Lohmann 2002](https://doi.org/10.1029/2001JD000470) """
105-
HAC_ice = 0.7
103+
HAC_ice = 1.0
106104
""" thermal accommodation coefficient for vapour deposition as recommended in
107105
[Pruppacher & Klett](https://doi.org/10.1007/978-0-306-48100-0) """
108106

107+
C_cunn = 0.7
108+
""" Cunningham correction factor as used in
109+
[Spichtinger & Gierens 2009](https://doi.org/10.5194/acp-9-685-2009) """
110+
109111
ARM_C1 = 6.1094 * si.hectopascal
110112
""" [August](https://doi.org/10.1002/andp.18280890511) Roche Magnus formula coefficients
111113
(values from [Alduchov & Eskridge 1996](https://doi.org/10.1175%2F1520-0450%281996%29035%3C0601%3AIMFAOS%3E2.0.CO%3B2))
@@ -527,6 +529,28 @@
527529
CRAIG_1961_INTERCEPT_COEFF = 10 * PER_MILLE
528530
""" 〃 """
529531

532+
capacity_columnar_ice_B1 = 0.3
533+
""" eq. A11 & A12 in [Spichtinger et al. 2023](https://doi.org/10.5194/acp-23-2035-2023) """
534+
capacity_columnar_ice_B2 = 0.43
535+
""" 〃 """
536+
capacity_columnar_ice_A1 = 0.015755 * si.m / si.kg**capacity_columnar_ice_B1
537+
""" 〃 """
538+
capacity_columnar_ice_A2 = 0.33565 * si.m / si.kg**capacity_columnar_ice_B2
539+
""" 〃 """
540+
541+
columnar_ice_mass_transition = 2.146e-13 * si.kg
542+
""" tab. 1 in [Spichtinger & Gierens 2009](https://doi.org/10.5194/acp-9-685-2009) """
543+
columnar_ice_length_beta_1 = 3.0
544+
""" 〃 """
545+
columnar_ice_length_beta_2 = 2.2
546+
""" 〃 """
547+
columnar_ice_length_alpha_1 = 526.1 * si.kg / si.m**columnar_ice_length_beta_1
548+
""" 〃 """
549+
columnar_ice_length_alpha_2 = 0.04142 * si.kg / si.m**columnar_ice_length_beta_2
550+
""" 〃 """
551+
columnar_bulk_ice_density = 0.81e3 * si.kg / si.m**3
552+
""" 〃 """
553+
530554
asymmetry_g = 0.85 # forward scattering from cloud droplets
531555
""" [Bohren 1987](https://doi.org/10.1119/1.15109) """
532556

PySDM/physics/diffusion_ice_capacity/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
"""
44

55
from .spherical import Spherical
6+
from .columnar import Columnar
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""
2+
capacity for columnar ice crystals approximated as prolate ellipsoids
3+
eq. A11 & A12 in Spichtinger et al. 2023 (https://doi.org/10.5194/acp-23-2035-2023)
4+
"""
5+
6+
import numpy as np
7+
8+
9+
class Columnar: # pylint: disable=too-few-public-methods
10+
11+
def __init__(self, _):
12+
pass
13+
14+
@staticmethod
15+
def capacity(const, mass):
16+
return (
17+
const.capacity_columnar_ice_A1 * mass**const.capacity_columnar_ice_B1
18+
+ const.capacity_columnar_ice_A2 * mass**const.capacity_columnar_ice_B2
19+
)
20+
21+
@staticmethod
22+
def reference_capacity(
23+
const, polar_diameter, eccentricity
24+
): # pylint: disable=unused-argument
25+
return (
26+
polar_diameter
27+
* eccentricity
28+
/ np.log((1 + eccentricity) / (1 - eccentricity))
29+
)

PySDM/physics/diffusion_ice_capacity/spherical.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
capacity for approximation of ice crystals as spheres
33
"""
44

5+
import numpy as np
6+
57

68
class Spherical: # pylint: disable=too-few-public-methods
79

810
def __init__(self, _):
911
pass
1012

1113
@staticmethod
12-
def capacity(const, diameter):
13-
return diameter / const.TWO
14+
def capacity(const, mass):
15+
return np.power(mass / const.PI_4_3 / const.rho_i, const.ONE_THIRD)

PySDM/physics/diffusion_ice_kinetics/standard.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,15 @@ def lambdaK(const, T, p):
2323
@staticmethod
2424
def D(const, D, r, lmbd, T):
2525
return D / (
26-
r / (r + lmbd)
26+
r / (r + lmbd * const.C_cunn)
2727
+ 4.0 * D / const.MAC_ice / np.sqrt(8.0 * const.Rv * T / const.PI) / r
2828
)
2929

3030
@staticmethod
3131
def K(const, K, r, lmbd, T, rho): # pylint: disable=too-many-arguments
3232
return K / (
3333
r / (r + lmbd)
34-
+ 4.0
35-
* K
34+
+ K
3635
/ const.HAC_ice
3736
/ np.sqrt(8.0 * const.Rd * T / const.PI)
3837
/ const.c_pd

PySDM/physics/particle_shape_and_density/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
from .liquid_spheres import LiquidSpheres
66
from .mixed_phase_spheres import MixedPhaseSpheres
77
from .porous_spheroids import PorousSpheroid
8+
from .columnar_ice import ColumnarIce
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""
2+
for columnar ice crystals as in
3+
[Spichtinger & Gierens 2009](https://doi.org/10.5194/acp-9-685-2009)
4+
"""
5+
6+
import numpy as np
7+
from .porous_spheroids import PorousSpheroid
8+
9+
10+
class ColumnarIce(PorousSpheroid):
11+
12+
@staticmethod
13+
def polar_radius_empirical_parametrisation(const, mass):
14+
"""Sec. 3.1.2 in [Spichtinger & Gierens 2009].
15+
Note that the notation in the paper is incorrect.
16+
"""
17+
return np.where(
18+
mass < const.columnar_ice_mass_transition,
19+
(mass / const.columnar_ice_length_alpha_1)
20+
** (1 / const.columnar_ice_length_beta_1)
21+
/ 2,
22+
(mass / const.columnar_ice_length_alpha_2)
23+
** (1 / const.columnar_ice_length_beta_2)
24+
/ 2,
25+
)
26+
27+
@staticmethod
28+
def aspect_ratio_empirical_parametrisation(const, mass):
29+
"""Eq. 17 in [Spichtinger & Gierens 2009]"""
30+
return np.where(
31+
mass < const.columnar_ice_mass_transition,
32+
1,
33+
np.sqrt(
34+
np.sqrt(27)
35+
* const.columnar_bulk_ice_density
36+
/ 8.0
37+
/ const.columnar_ice_length_alpha_2
38+
** (3 / const.columnar_ice_length_beta_2)
39+
)
40+
* mass
41+
** (
42+
(3 - const.columnar_ice_length_beta_2)
43+
/ 2
44+
/ const.columnar_ice_length_beta_2
45+
),
46+
)
Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,33 @@
11
"""
2-
for mixed-phase microphysics as in
2+
for porous spheriods as in
33
[Shima et al. 2020](https://doi.org/10.5194/gmd-13-4107-2020)
4+
and prolate spheriods as in
5+
[Spichtinger & Gierens 2009](https://doi.org/10.5194/acp-9-685-2009)
46
"""
57

8+
import numpy as np
9+
610

711
class PorousSpheroid: # pylint: disable=too-few-public-methods
12+
def __init__(self, _):
13+
pass
14+
815
@staticmethod
916
def supports_mixed_phase(_=None):
1017
return True
18+
19+
@staticmethod
20+
def aspect_ratio(polar_radius, equatorial_radius):
21+
return polar_radius / equatorial_radius
22+
23+
@staticmethod
24+
def equatorial_radius(polar_radius, aspect_ratio):
25+
return polar_radius / aspect_ratio
26+
27+
@staticmethod
28+
def polar_radius(equatorial_radius, aspect_ratio):
29+
return equatorial_radius * aspect_ratio
30+
31+
@staticmethod
32+
def eccentricity(aspect_ratio):
33+
return np.sqrt(1 - aspect_ratio**-2.0)

0 commit comments

Comments
 (0)