From 9195e67a3ba6e541fc4257b2a2ecfcae27616449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agnieszka=20=C5=BBaba?= Date: Mon, 14 Jul 2025 21:34:58 +0200 Subject: [PATCH 1/5] fractionation factors for different S and temp --- .../Zaba_et_al/fractionation_factors.ipynb | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 examples/PySDM_examples/Zaba_et_al/fractionation_factors.ipynb diff --git a/examples/PySDM_examples/Zaba_et_al/fractionation_factors.ipynb b/examples/PySDM_examples/Zaba_et_al/fractionation_factors.ipynb new file mode 100644 index 000000000..fefc5150a --- /dev/null +++ b/examples/PySDM_examples/Zaba_et_al/fractionation_factors.ipynb @@ -0,0 +1,169 @@ +{ + "cells": [ + { + "cell_type": "code", + "id": "initial_id", + "metadata": { + "collapsed": true, + "ExecuteTime": { + "end_time": "2025-07-14T18:42:23.295115Z", + "start_time": "2025-07-14T18:42:23.287266Z" + } + }, + "source": [ + "import numpy as np\n", + "from matplotlib import pyplot\n", + "from functools import partial\n", + "from open_atmos_jupyter_utils import show_plot\n", + "\n", + "from PySDM import Formulae\n", + "from PySDM.physics import si" + ], + "outputs": [], + "execution_count": 71 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-07-14T19:16:41.463007Z", + "start_time": "2025-07-14T19:16:41.449038Z" + } + }, + "cell_type": "code", + "source": [ + "formulae = Formulae(\n", + " isotope_equilibrium_fractionation_factors=\"MerlivatAndNief1967+Majoube1970+Majoube1971\",\n", + " isotope_kinetic_fractionation_factors=\"JouzelAndMerlivat1984\",\n", + " isotope_diffusivity_ratios=\"Stewart1975\"\n", + ")\n", + "\n", + "saturation = np.linspace(.7, 1.1, 7)\n", + "temperature_C = np.linspace(-30, 0)\n", + "temperature = formulae.trivia.C2K(temperature_C) * si.K\n" + ], + "id": "5f8f76c80c1d2286", + "outputs": [], + "execution_count": 126 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-07-14T19:16:41.836941Z", + "start_time": "2025-07-14T19:16:41.833451Z" + } + }, + "cell_type": "code", + "source": [ + "alpha_liquid = formulae.isotope_equilibrium_fractionation_factors.alpha_l_2H(temperature)\n", + "alpha_kinetic = partial(formulae.isotope_kinetic_fractionation_factors.alpha_kinetic, alpha_equilibrium=alpha, D_ratio_heavy_to_light=formulae.isotope_diffusivity_ratios.ratio_2H_heavy_to_light(temperature))\n", + "alpha_ice = formulae.isotope_equilibrium_fractionation_factors.alpha_i_2H(temperature)" + ], + "id": "810fcbb7b502850d", + "outputs": [], + "execution_count": 127 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-07-14T19:34:08.839335Z", + "start_time": "2025-07-14T19:34:07.644009Z" + } + }, + "cell_type": "code", + "source": [ + "for S in saturation:\n", + " alpha = alpha_liquid * alpha_kinetic(saturation=S)\n", + " pyplot.plot(alpha, temperature_C, 'k', alpha=0.1)\n", + " pyplot.annotate(f'{S:.3g}', xy=(alpha[4], temperature_C[4]), rotation=55, color='k', alpha=0.5, size=10)\n", + "\n", + "pyplot.plot(alpha_kinetic(saturation=1)*alpha_ice, temperature_C, label='wrt ice')\n", + "print(alpha[3]/alpha[0])\n", + "pyplot.plot(alpha_kinetic(saturation=1)*alpha_liquid, temperature_C, label='wrt liquid')\n", + "pyplot.gca().set(\n", + " xlabel='Fractionation factor',\n", + " ylabel=\"Temperature [K]\",\n", + ")\n", + "pyplot.gca().invert_yaxis()\n", + "pyplot.legend()\n", + "show_plot()\n" + ], + "id": "2f1aeb9076b01e6f", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.9965711674381411\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/svg+xml": "\n\n\n \n \n \n \n 2025-07-14T21:34:08.818040\n image/svg+xml\n \n \n Matplotlib v3.10.0, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "HBox(children=(HTML(value=\"./tmp_l8_pbgl.pdf
\"), HTML(value…" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "a8f58c2a3af844b08fb503e47f0af6f2" + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 149 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-07-14T19:23:49.618983Z", + "start_time": "2025-07-14T19:23:49.615602Z" + } + }, + "cell_type": "code", + "source": "", + "id": "3a1b25d03fa7c846", + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": "", + "id": "79642bd18579086a" + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 93a965f425b5836a8ddb8557f2ddef86ffec26a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agnieszka=20=C5=BBaba?= Date: Tue, 15 Jul 2025 21:06:08 +0200 Subject: [PATCH 2/5] fix args naming --- .../Zaba_et_al/fractionation_factors.ipynb | 76 +++++++++---------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/examples/PySDM_examples/Zaba_et_al/fractionation_factors.ipynb b/examples/PySDM_examples/Zaba_et_al/fractionation_factors.ipynb index fefc5150a..7193ed0cb 100644 --- a/examples/PySDM_examples/Zaba_et_al/fractionation_factors.ipynb +++ b/examples/PySDM_examples/Zaba_et_al/fractionation_factors.ipynb @@ -6,8 +6,8 @@ "metadata": { "collapsed": true, "ExecuteTime": { - "end_time": "2025-07-14T18:42:23.295115Z", - "start_time": "2025-07-14T18:42:23.287266Z" + "end_time": "2025-07-15T18:53:32.653518Z", + "start_time": "2025-07-15T18:53:30.861075Z" } }, "source": [ @@ -20,13 +20,13 @@ "from PySDM.physics import si" ], "outputs": [], - "execution_count": 71 + "execution_count": 1 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-07-14T19:16:41.463007Z", - "start_time": "2025-07-14T19:16:41.449038Z" + "end_time": "2025-07-15T18:53:33.014638Z", + "start_time": "2025-07-15T18:53:32.737631Z" } }, "cell_type": "code", @@ -38,47 +38,58 @@ ")\n", "\n", "saturation = np.linspace(.7, 1.1, 7)\n", + "\n", + "# temperature_C might be replaced with temperature profile\n", "temperature_C = np.linspace(-30, 0)\n", "temperature = formulae.trivia.C2K(temperature_C) * si.K\n" ], "id": "5f8f76c80c1d2286", "outputs": [], - "execution_count": 126 + "execution_count": 2 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-07-14T19:16:41.836941Z", - "start_time": "2025-07-14T19:16:41.833451Z" + "end_time": "2025-07-15T18:53:34.101574Z", + "start_time": "2025-07-15T18:53:33.022297Z" } }, "cell_type": "code", "source": [ - "alpha_liquid = formulae.isotope_equilibrium_fractionation_factors.alpha_l_2H(temperature)\n", - "alpha_kinetic = partial(formulae.isotope_kinetic_fractionation_factors.alpha_kinetic, alpha_equilibrium=alpha, D_ratio_heavy_to_light=formulae.isotope_diffusivity_ratios.ratio_2H_heavy_to_light(temperature))\n", - "alpha_ice = formulae.isotope_equilibrium_fractionation_factors.alpha_i_2H(temperature)" + "alpha_l = formulae.isotope_equilibrium_fractionation_factors.alpha_l_2H(temperature)\n", + "alpha_l_kinetic = partial(\n", + " formulae.isotope_kinetic_fractionation_factors.alpha_kinetic,\n", + " alpha_equilibrium=alpha_l,\n", + " D_ratio_heavy_to_light=formulae.isotope_diffusivity_ratios.ratio_2H_heavy_to_light(temperature)\n", + ")\n", + "\n", + "alpha_i = formulae.isotope_equilibrium_fractionation_factors.alpha_i_2H(temperature)\n", + "alpha_i_kinetic = partial(\n", + " formulae.isotope_kinetic_fractionation_factors.alpha_kinetic,\n", + " alpha_equilibrium=alpha_i,\n", + " D_ratio_heavy_to_light=formulae.isotope_diffusivity_ratios.ratio_2H_heavy_to_light(temperature)\n", + ")" ], "id": "810fcbb7b502850d", "outputs": [], - "execution_count": 127 + "execution_count": 3 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-07-14T19:34:08.839335Z", - "start_time": "2025-07-14T19:34:07.644009Z" + "end_time": "2025-07-15T18:53:34.418783Z", + "start_time": "2025-07-15T18:53:34.110259Z" } }, "cell_type": "code", "source": [ "for S in saturation:\n", - " alpha = alpha_liquid * alpha_kinetic(saturation=S)\n", + " alpha = alpha_l * alpha_l_kinetic(saturation=S)\n", " pyplot.plot(alpha, temperature_C, 'k', alpha=0.1)\n", " pyplot.annotate(f'{S:.3g}', xy=(alpha[4], temperature_C[4]), rotation=55, color='k', alpha=0.5, size=10)\n", "\n", - "pyplot.plot(alpha_kinetic(saturation=1)*alpha_ice, temperature_C, label='wrt ice')\n", - "print(alpha[3]/alpha[0])\n", - "pyplot.plot(alpha_kinetic(saturation=1)*alpha_liquid, temperature_C, label='wrt liquid')\n", + "pyplot.plot(alpha_i_kinetic(saturation=1)*alpha_i, temperature_C, label='wrt ice')\n", + "pyplot.plot(alpha_l_kinetic(saturation=1)*alpha_l, temperature_C, label='wrt liquid')\n", "pyplot.gca().set(\n", " xlabel='Fractionation factor',\n", " ylabel=\"Temperature [K]\",\n", @@ -89,19 +100,12 @@ ], "id": "2f1aeb9076b01e6f", "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0.9965711674381411\n" - ] - }, { "data": { "text/plain": [ "
" ], - "image/svg+xml": "\n\n\n \n \n \n \n 2025-07-14T21:34:08.818040\n image/svg+xml\n \n \n Matplotlib v3.10.0, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" + "image/svg+xml": "\n\n\n \n \n \n \n 2025-07-15T20:53:34.400056\n image/svg+xml\n \n \n Matplotlib v3.10.0, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" }, "metadata": {}, "output_type": "display_data" @@ -109,40 +113,32 @@ { "data": { "text/plain": [ - "HBox(children=(HTML(value=\"./tmp_l8_pbgl.pdf
\"), HTML(value…" + "HBox(children=(HTML(value=\"./tmphss6ofj6.pdf
\"), HTML(value…" ], "application/vnd.jupyter.widget-view+json": { "version_major": 2, "version_minor": 0, - "model_id": "a8f58c2a3af844b08fb503e47f0af6f2" + "model_id": "99cfa7e0f64b411abb28c15e1bea5957" } }, "metadata": {}, "output_type": "display_data" } ], - "execution_count": 149 + "execution_count": 4 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-07-14T19:23:49.618983Z", - "start_time": "2025-07-14T19:23:49.615602Z" + "end_time": "2025-07-15T18:53:34.461114Z", + "start_time": "2025-07-15T18:53:34.459575Z" } }, "cell_type": "code", "source": "", - "id": "3a1b25d03fa7c846", + "id": "79642bd18579086a", "outputs": [], "execution_count": null - }, - { - "metadata": {}, - "cell_type": "code", - "outputs": [], - "execution_count": null, - "source": "", - "id": "79642bd18579086a" } ], "metadata": { From 3c7b987ed7ca90bae3984327dbaf7bb509d104db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agnieszka=20=C5=BBaba?= Date: Mon, 17 Nov 2025 16:40:58 +0100 Subject: [PATCH 3/5] move to HOWTOs, start description; add badges --- .../fractionation_factors.ipynb | 108 ++++++++++++++---- 1 file changed, 83 insertions(+), 25 deletions(-) rename examples/PySDM_examples/{Zaba_et_al => _HOWTOs}/fractionation_factors.ipynb (81%) diff --git a/examples/PySDM_examples/Zaba_et_al/fractionation_factors.ipynb b/examples/PySDM_examples/_HOWTOs/fractionation_factors.ipynb similarity index 81% rename from examples/PySDM_examples/Zaba_et_al/fractionation_factors.ipynb rename to examples/PySDM_examples/_HOWTOs/fractionation_factors.ipynb index 7193ed0cb..5e5065e42 100644 --- a/examples/PySDM_examples/Zaba_et_al/fractionation_factors.ipynb +++ b/examples/PySDM_examples/_HOWTOs/fractionation_factors.ipynb @@ -1,13 +1,53 @@ { "cells": [ + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "[![preview notebook](https://img.shields.io/static/v1?label=render%20on&logo=github&color=87ce3e&message=GitHub)](https://github.com/open-atmos/PySDM/blob/main/examples/PySDM_examples/_HOWTOs/fractionation_factors.ipynb)\n", + "[![launch on mybinder.org](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/open-atmos/PySDM.git/main?urlpath=lab/tree/examples/PySDM_examples/_HOWTOs/fractionation_factors.ipynb)\n", + "[![launch on Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/open-atmos/PySDM/blob/main/examples/PySDM_examples/_HOWTOs/fractionation_factors.ipynb)" + ], + "id": "be4d0663e92430ea" + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# Isotopic fractionation factors (kinetic and equilibrium) HOWTO\n", + "- $\\alpha(T)$ is a fractionation factor for water isotopologues, factors are different wrt ice and liquid phase\n", + "- effective, equilibrium and kinetic\n", + "- plot description" + ], + "id": "b7a9153ddefcdf76" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-17T15:35:49.920503Z", + "start_time": "2025-11-17T15:35:49.917010Z" + } + }, + "cell_type": "code", + "source": [ + "import sys\n", + "if 'google.colab' in sys.modules:\n", + " !pip --quiet install open-atmos-jupyter-utils\n", + " from open_atmos_jupyter_utils import pip_install_on_colab\n", + " pip_install_on_colab('PySDM-examples')" + ], + "id": "dbb2b5f1c8d451d6", + "outputs": [], + "execution_count": 3 + }, { "cell_type": "code", "id": "initial_id", "metadata": { "collapsed": true, "ExecuteTime": { - "end_time": "2025-07-15T18:53:32.653518Z", - "start_time": "2025-07-15T18:53:30.861075Z" + "end_time": "2025-11-17T15:39:18.823256Z", + "start_time": "2025-11-17T15:39:18.756973Z" } }, "source": [ @@ -20,13 +60,19 @@ "from PySDM.physics import si" ], "outputs": [], - "execution_count": 1 + "execution_count": 8 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "formulae, considered saturation range, temperature profile (here linear)", + "id": "7011f12adc2d5dbd" }, { "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T18:53:33.014638Z", - "start_time": "2025-07-15T18:53:32.737631Z" + "end_time": "2025-11-17T15:35:53.370217Z", + "start_time": "2025-11-17T15:35:52.792830Z" } }, "cell_type": "code", @@ -39,19 +85,24 @@ "\n", "saturation = np.linspace(.7, 1.1, 7)\n", "\n", - "# temperature_C might be replaced with temperature profile\n", "temperature_C = np.linspace(-30, 0)\n", - "temperature = formulae.trivia.C2K(temperature_C) * si.K\n" + "temperature = formulae.trivia.C2K(temperature_C) * si.K" ], "id": "5f8f76c80c1d2286", "outputs": [], - "execution_count": 2 + "execution_count": 5 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "fractionation factors for $^2$H in given temperature range (wrt ice and liquid, kinetic and equilibrium)", + "id": "e6d93020d01aefbd" }, { "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T18:53:34.101574Z", - "start_time": "2025-07-15T18:53:33.022297Z" + "end_time": "2025-11-17T15:35:55.364926Z", + "start_time": "2025-11-17T15:35:53.375406Z" } }, "cell_type": "code", @@ -72,29 +123,30 @@ ], "id": "810fcbb7b502850d", "outputs": [], - "execution_count": 3 + "execution_count": 6 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T18:53:34.418783Z", - "start_time": "2025-07-15T18:53:34.110259Z" + "end_time": "2025-11-17T15:35:56.081460Z", + "start_time": "2025-11-17T15:35:55.392476Z" } }, "cell_type": "code", "source": [ "for S in saturation:\n", - " alpha = alpha_l * alpha_l_kinetic(saturation=S)\n", - " pyplot.plot(alpha, temperature_C, 'k', alpha=0.1)\n", + " alpha_eff = alpha_l * alpha_l_kinetic(saturation=S)\n", + " pyplot.plot(alpha_eff, temperature_C, 'k', alpha=0.1)\n", " pyplot.annotate(f'{S:.3g}', xy=(alpha[4], temperature_C[4]), rotation=55, color='k', alpha=0.5, size=10)\n", "\n", - "pyplot.plot(alpha_i_kinetic(saturation=1)*alpha_i, temperature_C, label='wrt ice')\n", - "pyplot.plot(alpha_l_kinetic(saturation=1)*alpha_l, temperature_C, label='wrt liquid')\n", + "pyplot.plot(alpha_i_kinetic(saturation=1)*alpha_i, temperature_C, label=r'$\\alpha_\\text{eff}$ wrt ice')\n", + "pyplot.plot(alpha_l_kinetic(saturation=1)*alpha_l, temperature_C, label=r'$\\alpha_\\text{eff}$ wrt liquid')\n", "pyplot.gca().set(\n", " xlabel='Fractionation factor',\n", " ylabel=\"Temperature [K]\",\n", ")\n", "pyplot.gca().invert_yaxis()\n", + "pyplot.title(\"Effective fractionation factors wrt ice and liquid\")\n", "pyplot.legend()\n", "show_plot()\n" ], @@ -105,33 +157,39 @@ "text/plain": [ "
" ], - "image/svg+xml": "\n\n\n \n \n \n \n 2025-07-15T20:53:34.400056\n image/svg+xml\n \n \n Matplotlib v3.10.0, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" + "image/svg+xml": "\n\n\n \n \n \n \n 2025-11-17T16:35:56.047092\n image/svg+xml\n \n \n Matplotlib v3.10.0, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" }, "metadata": {}, - "output_type": "display_data" + "output_type": "display_data", + "jetTransient": { + "display_id": null + } }, { "data": { "text/plain": [ - "HBox(children=(HTML(value=\"./tmphss6ofj6.pdf
\"), HTML(value…" + "HBox(children=(HTML(value=\"./tmp45rn_gjh.pdf
\"), HTML(value…" ], "application/vnd.jupyter.widget-view+json": { "version_major": 2, "version_minor": 0, - "model_id": "99cfa7e0f64b411abb28c15e1bea5957" + "model_id": "2bf128d9b42b47e3880eba1c79df6520" } }, "metadata": {}, - "output_type": "display_data" + "output_type": "display_data", + "jetTransient": { + "display_id": null + } } ], - "execution_count": 4 + "execution_count": 7 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-07-15T18:53:34.461114Z", - "start_time": "2025-07-15T18:53:34.459575Z" + "end_time": "2025-11-17T15:35:56.120809Z", + "start_time": "2025-11-17T15:35:56.116965Z" } }, "cell_type": "code", From 69db94fc71efeb8be7ba77f52f377d272114b191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agnieszka=20=C5=BBaba?= Date: Sat, 20 Dec 2025 09:56:55 +0100 Subject: [PATCH 4/5] change saturation to relative humidity; fix test fig from J&M 84 --- .../jouzel_and_merlivat_1984.py | 8 +- .../PySDM_examples/Fisher_1991/fig_2.ipynb | 3003 +--------------- .../Jouzel_and_Merlivat_1984/fig_8_9.ipynb | 3052 +---------------- .../_HOWTOs/fractionation_factors.ipynb | 109 +- ...t_isotope_kinetic_fractionation_factors.py | 35 +- 5 files changed, 287 insertions(+), 5920 deletions(-) diff --git a/PySDM/physics/isotope_kinetic_fractionation_factors/jouzel_and_merlivat_1984.py b/PySDM/physics/isotope_kinetic_fractionation_factors/jouzel_and_merlivat_1984.py index f17186751..f0c6814c5 100644 --- a/PySDM/physics/isotope_kinetic_fractionation_factors/jouzel_and_merlivat_1984.py +++ b/PySDM/physics/isotope_kinetic_fractionation_factors/jouzel_and_merlivat_1984.py @@ -11,14 +11,14 @@ def __init__(self, _): pass @staticmethod - def alpha_kinetic(alpha_equilibrium, saturation, D_ratio_heavy_to_light): + def alpha_kinetic(alpha_equilibrium, relative_humidity, D_ratio_heavy_to_light): """eq. (11) Parameters ---------- alpha_equilibrium Equilibrium fractionation factor. - saturation + relative_humidity Over liquid water or ice. D_ratio_heavy_to_light Diffusivity ratio for heavy to light isotope. @@ -27,6 +27,6 @@ def alpha_kinetic(alpha_equilibrium, saturation, D_ratio_heavy_to_light): ---------- alpha_kinetic Kinetic fractionation factor for liquid water or ice.""" - return saturation / ( - alpha_equilibrium / D_ratio_heavy_to_light * (saturation - 1) + 1 + return relative_humidity / ( + alpha_equilibrium / D_ratio_heavy_to_light * (relative_humidity - 1) + 1 ) diff --git a/examples/PySDM_examples/Fisher_1991/fig_2.ipynb b/examples/PySDM_examples/Fisher_1991/fig_2.ipynb index ceaab1041..9a6df827b 100644 --- a/examples/PySDM_examples/Fisher_1991/fig_2.ipynb +++ b/examples/PySDM_examples/Fisher_1991/fig_2.ipynb @@ -21,15 +21,13 @@ }, { "cell_type": "code", - "execution_count": 1, "id": "31481014375c7d36", "metadata": { "ExecuteTime": { - "end_time": "2025-06-25T12:41:17.048483Z", - "start_time": "2025-06-25T12:41:17.041726Z" + "end_time": "2025-12-20T08:39:20.178984Z", + "start_time": "2025-12-20T08:39:20.175130Z" } }, - "outputs": [], "source": [ "import os, sys\n", "os.environ['NUMBA_THREADING_LAYER'] = 'workqueue' # PySDM & PyMPDATA don't work with TBB; OpenMP has extra dependencies on macOS\n", @@ -37,19 +35,19 @@ " !pip --quiet install open-atmos-jupyter-utils\n", " from open_atmos_jupyter_utils import pip_install_on_colab\n", " pip_install_on_colab('PySDM-examples', 'PySDM')" - ] + ], + "outputs": [], + "execution_count": 1 }, { "cell_type": "code", - "execution_count": 2, "id": "c36c2f5c-17c1-422e-9ab9-f7d612064199", "metadata": { "ExecuteTime": { - "end_time": "2025-06-25T12:41:21.768860Z", - "start_time": "2025-06-25T12:41:17.056517Z" + "end_time": "2025-12-20T08:39:22.493785Z", + "start_time": "2025-12-20T08:39:20.182948Z" } }, - "outputs": [], "source": [ "from matplotlib import pyplot\n", "import numpy as np\n", @@ -64,19 +62,19 @@ " vapour_mixing_ratio,\n", " ice_saturation_curve_4\n", ")" - ] + ], + "outputs": [], + "execution_count": 2 }, { "cell_type": "code", - "execution_count": 3, "id": "91bb290498429f53", "metadata": { "ExecuteTime": { - "end_time": "2025-06-25T12:41:21.875872Z", - "start_time": "2025-06-25T12:41:21.845639Z" + "end_time": "2025-12-20T08:39:22.528300Z", + "start_time": "2025-12-20T08:39:22.497806Z" } }, - "outputs": [], "source": [ "formulae= Formulae(\n", " isotope_meteoric_water_line=\"Dansgaard1964\",\n", @@ -94,39 +92,39 @@ "for isotope in isotopes:\n", " alpha_eq[isotope] = getattr(formulae.isotope_equilibrium_fractionation_factors, f'alpha_i_{isotope}')\n", " diffusivity_ratio[isotope] = getattr(formulae.isotope_diffusivity_ratios, f'ratio_{isotope}_heavy_to_light')" - ] + ], + "outputs": [], + "execution_count": 3 }, { "cell_type": "code", - "execution_count": 4, "id": "754af83e4ab216bc", "metadata": { "ExecuteTime": { - "end_time": "2025-06-25T12:41:21.884154Z", - "start_time": "2025-06-25T12:41:21.881306Z" + "end_time": "2025-12-20T08:39:22.533972Z", + "start_time": "2025-12-20T08:39:22.531976Z" } }, - "outputs": [], "source": [ "def alpha_kin(iso, T):\n", " return formulae.isotope_kinetic_fractionation_factors.alpha_kinetic(\n", " alpha_equilibrium = alpha_eq[iso](T),\n", " D_ratio_heavy_to_light=diffusivity_ratio[iso](T),\n", - " saturation = ice_saturation_curve_4(const=const, T=T)\n", + " relative_humidity = ice_saturation_curve_4(const=const, T=T)\n", " )" - ] + ], + "outputs": [], + "execution_count": 4 }, { "cell_type": "code", - "execution_count": 5, "id": "9ca4e3256065274b", "metadata": { "ExecuteTime": { - "end_time": "2025-06-25T12:41:21.894710Z", - "start_time": "2025-06-25T12:41:21.891746Z" + "end_time": "2025-12-20T08:39:22.540134Z", + "start_time": "2025-12-20T08:39:22.537463Z" } }, - "outputs": [], "source": [ "def d_delta_dT(T, delta):\n", " y = yf(T=T)\n", @@ -143,19 +141,19 @@ " / (alpha * (y + alpha * y_e))\n", " )\n", " return res" - ] + ], + "outputs": [], + "execution_count": 5 }, { "cell_type": "code", - "execution_count": 6, "id": "71979cfe7348344d", "metadata": { "ExecuteTime": { - "end_time": "2025-06-25T12:41:21.901806Z", - "start_time": "2025-06-25T12:41:21.899568Z" + "end_time": "2025-12-20T08:39:22.544815Z", + "start_time": "2025-12-20T08:39:22.542865Z" } }, - "outputs": [], "source": [ "delta_18O_0 = -15 * PER_MILLE\n", "delta_2H_0 = const.CRAIG_1961_SLOPE_COEFF * delta_18O_0\n", @@ -163,19 +161,19 @@ "\n", "y_e = 0\n", "yf = partial(vapour_mixing_ratio, formulae)\n" - ] + ], + "outputs": [], + "execution_count": 6 }, { "cell_type": "code", - "execution_count": 7, "id": "4e112378083e50f5", "metadata": { "ExecuteTime": { - "end_time": "2025-06-25T12:41:25.203838Z", - "start_time": "2025-06-25T12:41:21.907105Z" + "end_time": "2025-12-20T08:39:27.719208Z", + "start_time": "2025-12-20T08:39:22.547553Z" } }, - "outputs": [], "source": [ "result = solve_ivp(\n", " fun=d_delta_dT,\n", @@ -189,1297 +187,19 @@ " delta_2H=delta_2H,\n", " delta_18O=delta_18O\n", ")" - ] + ], + "outputs": [], + "execution_count": 7 }, { "cell_type": "code", - "execution_count": 8, "id": "153a6e26bc2be38a", "metadata": { "ExecuteTime": { - "end_time": "2025-06-25T12:41:25.731698Z", - "start_time": "2025-06-25T12:41:25.217926Z" + "end_time": "2025-12-20T08:39:28.456103Z", + "start_time": "2025-12-20T08:39:27.743940Z" } }, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " 2025-06-25T14:41:25.713352\n", - " image/svg+xml\n", - " \n", - " \n", - " Matplotlib v3.9.2, https://matplotlib.org/\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "\n" - ], - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d85508aab73e4fbc91cf47f982b6d8a7", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value=\"./fig_1.pdf
\"), HTML(value=\"./fig_1.pdf
\"), HTML(value=\"./fig_2.pdf
\"), HTML(value=\"./fig_2.pdf
\"), HTML(value=\"\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " 2025-06-26T01:25:44.970122\n", - " image/svg+xml\n", - " \n", - " \n", - " Matplotlib v3.10.0, https://matplotlib.org/\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "\n" - ], - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "8c15bde98c9c4698979a4cb47ad75d48", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value=\"./fig_8.pdf
\"), HTML(value=\"" + ], + "image/svg+xml": "\n\n\n \n \n \n \n 2025-12-20T09:39:08.062718\n image/svg+xml\n \n \n Matplotlib v3.10.0, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" + }, + "metadata": {}, + "output_type": "display_data", + "jetTransient": { + "display_id": null + } + }, + { + "data": { + "text/plain": [ + "HBox(children=(HTML(value=\"./fig_8.pdf
\"), HTML(value=\"./fig_9.pdf
\"), HTML(value=\"" + ], + "image/svg+xml": "\n\n\n \n \n \n \n 2025-12-20T09:39:10.483313\n image/svg+xml\n \n \n Matplotlib v3.10.0, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" + }, + "metadata": {}, + "output_type": "display_data", + "jetTransient": { + "display_id": null + } + }, + { + "data": { + "text/plain": [ + "HBox(children=(HTML(value=\"./fig_9.pdf
\"), HTML(value=\"" ], - "image/svg+xml": "\n\n\n \n \n \n \n 2025-11-17T16:35:56.047092\n image/svg+xml\n \n \n Matplotlib v3.10.0, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" + "image/svg+xml": "\n\n\n \n \n \n \n 2025-12-20T09:38:41.546360\n image/svg+xml\n \n \n Matplotlib v3.10.0, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" }, "metadata": {}, "output_type": "display_data", @@ -168,12 +175,12 @@ { "data": { "text/plain": [ - "HBox(children=(HTML(value=\"./tmp45rn_gjh.pdf
\"), HTML(value…" + "HBox(children=(HTML(value=\"./tmp9botejd8.pdf
\"), HTML(value…" ], "application/vnd.jupyter.widget-view+json": { "version_major": 2, "version_minor": 0, - "model_id": "2bf128d9b42b47e3880eba1c79df6520" + "model_id": "8efa2723e9c3471a947d3a9f7ce74f52" } }, "metadata": {}, @@ -183,18 +190,18 @@ } } ], - "execution_count": 7 + "execution_count": 5 }, { "metadata": { "ExecuteTime": { - "end_time": "2025-11-17T15:35:56.120809Z", - "start_time": "2025-11-17T15:35:56.116965Z" + "end_time": "2025-12-20T08:38:41.676493Z", + "start_time": "2025-12-20T08:38:41.673218Z" } }, "cell_type": "code", "source": "", - "id": "79642bd18579086a", + "id": "b03a73fd279fa0ce", "outputs": [], "execution_count": null } diff --git a/tests/unit_tests/physics/test_isotope_kinetic_fractionation_factors.py b/tests/unit_tests/physics/test_isotope_kinetic_fractionation_factors.py index 84feeb7ed..d3ba38628 100644 --- a/tests/unit_tests/physics/test_isotope_kinetic_fractionation_factors.py +++ b/tests/unit_tests/physics/test_isotope_kinetic_fractionation_factors.py @@ -22,20 +22,20 @@ def test_units_alpha_kinetic(): # arrange alpha_eq = 1 * physics.si.dimensionless D_ratio = 1 * physics.si.dimensionless - saturation_over_ice = 1 * physics.si.dimensionless + rh_over_ice = 1 * physics.si.dimensionless # act sut = JouzelAndMerlivat1984.alpha_kinetic( alpha_equilibrium=alpha_eq, D_ratio_heavy_to_light=D_ratio, - saturation=saturation_over_ice, + relative_humidity=rh_over_ice, ) # assert assert sut.check("[]") @staticmethod - def test_fig_9_from_jouzel_and_merlivat_1984(plot=False): + def test_fig_9_from_jouzel_and_merlivat_1984(plot=PLOT): """[Jouzel & Merlivat 1984](https://doi.org/10.1029/JD089iD07p11749)""" # arrange formulae = Formulae( @@ -44,7 +44,7 @@ def test_fig_9_from_jouzel_and_merlivat_1984(plot=False): isotope_diffusivity_ratios="Stewart1975", ) temperatures = formulae.trivia.C2K(np.asarray([-30, -20, -10])) - saturation = np.linspace(start=1, stop=1.35) + rh = np.linspace(start=1, stop=1.35) alpha_s = formulae.isotope_equilibrium_fractionation_factors.alpha_i_18O diffusivity_ratio_heavy_to_light = ( formulae.isotope_diffusivity_ratios.ratio_18O_heavy_to_light @@ -56,7 +56,7 @@ def test_fig_9_from_jouzel_and_merlivat_1984(plot=False): alpha_k = { temperature: sut( alpha_equilibrium=alpha_s[temperature], - saturation=saturation, + relative_humidity=rh, D_ratio_heavy_to_light=diffusivity_ratio_heavy_to_light(temperature), ) for temperature in temperatures @@ -68,12 +68,12 @@ def test_fig_9_from_jouzel_and_merlivat_1984(plot=False): } # plot - pyplot.xlim(saturation[0], saturation[-1]) + pyplot.xlim(rh[0], rh[-1]) pyplot.ylim(1.003, 1.022) - pyplot.xlabel("S") - pyplot.ylabel("alpha_k * alpha_s") + pyplot.xlabel("Si [1]") + pyplot.ylabel(r"$\alpha_\text{kin} \alpha_\text{eq}$ [1]") for k, v in alpha_s_times_alpha_k.items(): - pyplot.plot(saturation, v, label=k) + pyplot.plot(rh, v, label=k) pyplot.legend() if plot: pyplot.show() @@ -88,10 +88,10 @@ def test_fig_9_from_jouzel_and_merlivat_1984(plot=False): @staticmethod @pytest.mark.parametrize( - ("temperature_C", "saturation", "alpha"), + ("temperature_C", "relative_humidity", "alpha"), ((-10, 1, 1.021), (-10, 1.35, 1.0075), (-30, 1, 1.0174), (-30, 1.35, 1.004)), ) - def test_fig9_values(temperature_C, saturation, alpha): + def test_fig9_values(temperature_C, relative_humidity, alpha): # arrange formulae = Formulae( isotope_kinetic_fractionation_factors="JouzelAndMerlivat1984", @@ -105,7 +105,7 @@ def test_fig9_values(temperature_C, saturation, alpha): alpha_s = formulae.isotope_equilibrium_fractionation_factors.alpha_i_18O(T) alpha_k = formulae.isotope_kinetic_fractionation_factors.alpha_kinetic( alpha_equilibrium=alpha_s, - saturation=saturation, + relative_humidity=relative_humidity, D_ratio_heavy_to_light=diffusivity_ratio_18O(T), ) @@ -123,13 +123,14 @@ def test_alpha_kinetic_jouzel_merlivat_vs_craig_gordon( ): # arrange T = Formulae().trivia.C2K(temperature_C) - RH = np.linspace(0.3, 1) + rh = np.linspace(0.3, 1) formulae = Formulae( isotope_equilibrium_fractionation_factors="VanHook1968", isotope_diffusivity_ratios="HellmannAndHarvey2020", isotope_kinetic_fractionation_factors="JouzelAndMerlivat1984", ) - Si = formulae.saturation_vapour_pressure.pvs_ice(T) + vapour_partial_pressure = rh * formulae.saturation_vapour_pressure.pvs_water(T) + Si = vapour_partial_pressure / formulae.saturation_vapour_pressure.pvs_ice(T) alpha_eq = getattr( formulae.isotope_equilibrium_fractionation_factors, f"alpha_l_{isotope}" )(T) @@ -138,14 +139,14 @@ def test_alpha_kinetic_jouzel_merlivat_vs_craig_gordon( )(T) alpha_kin_jm = formulae.isotope_kinetic_fractionation_factors.alpha_kinetic( alpha_equilibrium=alpha_eq, - saturation=Si, + relative_humidity=Si, # TODO D_ratio_heavy_to_light=D_heavy_to_light, ) formulae = Formulae( isotope_kinetic_fractionation_factors="CraigGordon", ) alpha_kin_cg = formulae.isotope_kinetic_fractionation_factors.alpha_kinetic( - relative_humidity=RH, + relative_humidity=rh, turbulence_parameter_n=1, delta_diff=alpha_eq - 1, theta=1, @@ -155,7 +156,7 @@ def test_alpha_kinetic_jouzel_merlivat_vs_craig_gordon( n = (alpha_kin_jm + 1) / (alpha_kin_cg + 1) # plot - pyplot.plot(1 - RH, n) + pyplot.plot(1 - rh, n) pyplot.gca().set( xlabel="1-RH", ylabel="turbulence parameter n", From 49f1ace079d304b1391e9a024f600a698fcd96f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agnieszka=20=C5=BBaba?= Date: Sat, 20 Dec 2025 09:57:25 +0100 Subject: [PATCH 5/5] remove resolved TODO --- .../physics/test_isotope_kinetic_fractionation_factors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/physics/test_isotope_kinetic_fractionation_factors.py b/tests/unit_tests/physics/test_isotope_kinetic_fractionation_factors.py index d3ba38628..c9dfd44a7 100644 --- a/tests/unit_tests/physics/test_isotope_kinetic_fractionation_factors.py +++ b/tests/unit_tests/physics/test_isotope_kinetic_fractionation_factors.py @@ -139,7 +139,7 @@ def test_alpha_kinetic_jouzel_merlivat_vs_craig_gordon( )(T) alpha_kin_jm = formulae.isotope_kinetic_fractionation_factors.alpha_kinetic( alpha_equilibrium=alpha_eq, - relative_humidity=Si, # TODO + relative_humidity=Si, D_ratio_heavy_to_light=D_heavy_to_light, ) formulae = Formulae(