Skip to content

Commit f14a446

Browse files
new formula for isotopic kinetic fractionation factor: Bolot 2013 (#1611)
1 parent 36811d9 commit f14a446

File tree

6 files changed

+171
-67
lines changed

6 files changed

+171
-67
lines changed

PySDM/physics/drop_growth/howell_1949.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,17 @@ class Howell1949(Fick): # pylint: disable=too-few-public-methods
1414

1515
@staticmethod
1616
def Fk(const, T, K, lv):
17-
"""thermodynamic term associated with heat conduction"""
17+
"""Thermodynamic term associated with heat conduction.
18+
19+
Parameters
20+
----------
21+
T
22+
Temperature.
23+
K
24+
Thermal diffusivity with heat ventilation factor.
25+
lv
26+
Latent heat of evaporation or sublimation.
27+
"""
1828
return const.rho_w * lv / T / K * (lv / T / const.Rv)
1929

2030
@staticmethod
Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"""
2-
kinetic fractionation factor from [Jouzel & Merlivat 1984](https://doi.org/10.1029/JD089iD07p11749)
3-
(as eq. 3e for n=1 in [Stewart 1975](https://doi.org/10.1029/JC080i009p01133))
2+
kinetic fractionation factor [Jouzel & Merlivat 1984](https://doi.org/10.1029/JD089iD07p11749),
3+
as eq. 3e for n=1 in [Stewart 1975](https://doi.org/10.1029/JC080i009p01133)
4+
and eq. 1 in [Bolot 2013](https://doi.org/10.5194/acp-13-7903-2013),
5+
where alpha_kinetic is multiplied by alpha equilibrium (eq. 1 defines effective alpha).
46
"""
57

68

@@ -9,13 +11,22 @@ def __init__(self, _):
911
pass
1012

1113
@staticmethod
12-
def alpha_kinetic(
13-
alpha_equilibrium, saturation_over_ice, diffusivity_ratio_heavy_to_light
14-
):
15-
"""eq. (11)"""
16-
return saturation_over_ice / (
17-
alpha_equilibrium
18-
/ diffusivity_ratio_heavy_to_light
19-
* (saturation_over_ice - 1)
20-
+ 1
14+
def alpha_kinetic(alpha_equilibrium, saturation, D_ratio_heavy_to_light):
15+
"""eq. (11)
16+
17+
Parameters
18+
----------
19+
alpha_equilibrium
20+
Equilibrium fractionation factor.
21+
saturation
22+
Over liquid water or ice.
23+
D_ratio_heavy_to_light
24+
Diffusivity ratio for heavy to light isotope.
25+
26+
Returns
27+
----------
28+
alpha_kinetic
29+
Kinetic fractionation factor for liquid water or ice."""
30+
return saturation / (
31+
alpha_equilibrium / D_ratio_heavy_to_light * (saturation - 1) + 1
2132
)

docs/bibliography.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@
529529
"https://doi.org/10.5194/acp-13-7903-2013": {
530530
"usages": [
531531
"examples/PySDM_examples/Bolot_et_al_2013/__init__.py",
532+
"PySDM/physics/isotope_kinetic_fractionation_factors/jouzel_and_merlivat_1984.py",
532533
"tests/unit_tests/physics/test_isotope_equilibrium_fractionation_factors.py"
533534
],
534535
"label": "Bolot et al. 2013 (Atmos. Chem. Phys. 13)",

examples/PySDM_examples/Fisher_1991/fig_2.ipynb

Lines changed: 50 additions & 24 deletions
Large diffs are not rendered by default.

examples/PySDM_examples/Jouzel_and_Merlivat_1984/fig_8_9.ipynb

Lines changed: 22 additions & 22 deletions
Large diffs are not rendered by default.

tests/unit_tests/physics/test_isotope_kinetic_fractionation_factors.py

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
from PySDM.physics.dimensional_analysis import DimensionalAnalysis
1212
from PySDM.physics.isotope_kinetic_fractionation_factors import JouzelAndMerlivat1984
1313

14+
PLOT = False
15+
1416

1517
class TestIsotopeKineticFractionationFactors:
1618
@staticmethod
17-
def test_units():
19+
def test_units_alpha_kinetic():
1820
"""checks that alphas are dimensionless"""
1921
with DimensionalAnalysis():
2022
# arrange
@@ -25,8 +27,8 @@ def test_units():
2527
# act
2628
sut = JouzelAndMerlivat1984.alpha_kinetic(
2729
alpha_equilibrium=alpha_eq,
28-
diffusivity_ratio_heavy_to_light=D_ratio,
29-
saturation_over_ice=saturation_over_ice,
30+
D_ratio_heavy_to_light=D_ratio,
31+
saturation=saturation_over_ice,
3032
)
3133

3234
# assert
@@ -54,10 +56,8 @@ def test_fig_9_from_jouzel_and_merlivat_1984(plot=False):
5456
alpha_k = {
5557
temperature: sut(
5658
alpha_equilibrium=alpha_s[temperature],
57-
saturation_over_ice=saturation,
58-
diffusivity_ratio_heavy_to_light=diffusivity_ratio_heavy_to_light(
59-
temperature
60-
),
59+
saturation=saturation,
60+
D_ratio_heavy_to_light=diffusivity_ratio_heavy_to_light(temperature),
6161
)
6262
for temperature in temperatures
6363
}
@@ -105,12 +105,68 @@ def test_fig9_values(temperature_C, saturation, alpha):
105105
alpha_s = formulae.isotope_equilibrium_fractionation_factors.alpha_i_18O(T)
106106
alpha_k = formulae.isotope_kinetic_fractionation_factors.alpha_kinetic(
107107
alpha_equilibrium=alpha_s,
108-
saturation_over_ice=saturation,
109-
diffusivity_ratio_heavy_to_light=diffusivity_ratio_18O(T),
108+
saturation=saturation,
109+
D_ratio_heavy_to_light=diffusivity_ratio_18O(T),
110110
)
111111

112112
# act
113113
sut = alpha_s * alpha_k
114114

115115
# assert
116116
np.testing.assert_approx_equal(actual=sut, desired=alpha, significant=3)
117+
118+
@staticmethod
119+
@pytest.mark.parametrize("isotope", ("2H", "18O", "17O"))
120+
@pytest.mark.parametrize("temperature_C", (-30, -20, -1))
121+
def test_alpha_kinetic_jouzel_merlivat_vs_craig_gordon(
122+
isotope, temperature_C, plot=PLOT
123+
):
124+
# arrange
125+
T = Formulae().trivia.C2K(temperature_C)
126+
RH = np.linspace(0.3, 1)
127+
formulae = Formulae(
128+
isotope_equilibrium_fractionation_factors="VanHook1968",
129+
isotope_diffusivity_ratios="HellmannAndHarvey2020",
130+
isotope_kinetic_fractionation_factors="JouzelAndMerlivat1984",
131+
)
132+
Si = formulae.saturation_vapour_pressure.pvs_ice(T)
133+
alpha_eq = getattr(
134+
formulae.isotope_equilibrium_fractionation_factors, f"alpha_l_{isotope}"
135+
)(T)
136+
D_heavy_to_light = getattr(
137+
formulae.isotope_diffusivity_ratios, f"ratio_{isotope}_heavy_to_light"
138+
)(T)
139+
alpha_kin_jm = formulae.isotope_kinetic_fractionation_factors.alpha_kinetic(
140+
alpha_equilibrium=alpha_eq,
141+
saturation=Si,
142+
D_ratio_heavy_to_light=D_heavy_to_light,
143+
)
144+
formulae = Formulae(
145+
isotope_kinetic_fractionation_factors="CraigGordon",
146+
)
147+
alpha_kin_cg = formulae.isotope_kinetic_fractionation_factors.alpha_kinetic(
148+
relative_humidity=RH,
149+
turbulence_parameter_n=1,
150+
delta_diff=alpha_eq - 1,
151+
theta=1,
152+
)
153+
154+
# act
155+
n = (alpha_kin_jm + 1) / (alpha_kin_cg + 1)
156+
157+
# plot
158+
pyplot.plot(1 - RH, n)
159+
pyplot.gca().set(
160+
xlabel="1-RH",
161+
ylabel="turbulence parameter n",
162+
)
163+
pyplot.grid()
164+
165+
if plot:
166+
pyplot.show()
167+
else:
168+
pyplot.clf()
169+
170+
# assert
171+
np.testing.assert_equal(n > 0.5, True)
172+
np.testing.assert_equal(n < 1, True)

0 commit comments

Comments
 (0)