Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
5e8e021
add tests for new trivia fun. thanks to ChatGPT
AgnieszkaZaba Jan 8, 2026
9d92ecd
remove unused args
AgnieszkaZaba Jan 8, 2026
8166406
replace arrays with tuples in parameterisation; add dimensional analysis
AgnieszkaZaba Jan 8, 2026
2d6a6c7
refactor name isotopic vs isotope
AgnieszkaZaba Jan 10, 2026
1ae50be
update docstrings
AgnieszkaZaba Jan 12, 2026
b3b934b
add molality definition and isotopic fraction (in addition to isotopi…
AgnieszkaZaba Jan 12, 2026
5915473
add Gat to bibliography
AgnieszkaZaba Jan 12, 2026
05b540b
remove Gat's 2 factor
AgnieszkaZaba Jan 12, 2026
1fc5c5a
define new way for calculating Mv
AgnieszkaZaba Jan 13, 2026
6edb47c
fix doi
AgnieszkaZaba Jan 13, 2026
001a340
update trivia tests
AgnieszkaZaba Jan 13, 2026
fb3f2b8
fix doi 2
AgnieszkaZaba Jan 13, 2026
473b9b8
add new citation Hayes (maybe try paper from 2001? - dont have access…
AgnieszkaZaba Jan 13, 2026
78aa65b
keep old Mv formula for debugging
AgnieszkaZaba Jan 13, 2026
a52d26d
Merge branch 'main' into iso-trivia
AgnieszkaZaba Jan 13, 2026
130dcbc
add test for reversed formulae
AgnieszkaZaba Jan 13, 2026
ca83163
change citation to use archived one
AgnieszkaZaba Jan 14, 2026
f836415
clean debug; line-too-long
AgnieszkaZaba Jan 14, 2026
cf568f7
revert new Mv formula
AgnieszkaZaba Jan 14, 2026
dbfb22e
update bibliography
AgnieszkaZaba Jan 14, 2026
95b2bd5
remove unintended change
AgnieszkaZaba Jan 15, 2026
1d82678
new test for Mv formula
AgnieszkaZaba Jan 15, 2026
6e56d8b
fix usages in docs
AgnieszkaZaba Jan 15, 2026
a65fda5
dont use ~ in url
AgnieszkaZaba Jan 15, 2026
4c031b3
add new characters to regex
AgnieszkaZaba Jan 15, 2026
e490b96
check if clearing jetTransient flag will help
AgnieszkaZaba Jan 15, 2026
4c5b1b6
revert all changes in notebook (I hope)
AgnieszkaZaba Jan 15, 2026
359fbf6
debug
AgnieszkaZaba Jan 16, 2026
1e0c827
do not run pylint for debugging
AgnieszkaZaba Jan 16, 2026
a649426
revert Mv change
AgnieszkaZaba Jan 16, 2026
fc61d8a
Merge remote-tracking branch 'origin/iso-trivia' into iso-trivia
AgnieszkaZaba Jan 16, 2026
16368e7
Revert "do not run pylint for debugging"
AgnieszkaZaba Jan 16, 2026
8ae14d2
Revert "debug"
AgnieszkaZaba Jan 16, 2026
4cff0ae
Revert "revert all changes in notebook (I hope)"
AgnieszkaZaba Jan 16, 2026
06e22a1
Revert "check if clearing jetTransient flag will help"
AgnieszkaZaba Jan 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions PySDM/physics/constants_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,6 @@ def compute_derived_values(c: dict):
water molar mass is computed from molecular masses and VSMOW isotope abundances
(and neglecting molecular binding energies)
for discussion, see:
- caption of Table 2.1 in [Gat 2010](https://doi.org/10.1142/p027)
- [IAPWS Guidelines](http://www.iapws.org/relguide/fundam.pdf)
"""

Expand All @@ -788,22 +787,41 @@ def compute_derived_values(c: dict):
c["Mv"] = (
(
1
- 2 * Trivia.mixing_ratio_to_specific_content(c["VSMOW_R_2H"])
- 2 * Trivia.mixing_ratio_to_specific_content(c["VSMOW_R_3H"])
- 1 * Trivia.mixing_ratio_to_specific_content(c["VSMOW_R_17O"])
- 1 * Trivia.mixing_ratio_to_specific_content(c["VSMOW_R_18O"])
- 2
* Trivia.isotopic_fraction_assuming_single_heavy_isotope(
isotopic_ratio=c["VSMOW_R_2H"]
)
- 2
* Trivia.isotopic_fraction_assuming_single_heavy_isotope(
isotopic_ratio=c["VSMOW_R_3H"]
)
- Trivia.isotopic_fraction_assuming_single_heavy_isotope(
isotopic_ratio=c["VSMOW_R_17O"]
)
- Trivia.isotopic_fraction_assuming_single_heavy_isotope(
isotopic_ratio=c["VSMOW_R_18O"]
)
)
* c["M_1H2_16O"]
+ 2
* Trivia.mixing_ratio_to_specific_content(c["VSMOW_R_2H"])
* Trivia.isotopic_fraction_assuming_single_heavy_isotope(
isotopic_ratio=c["VSMOW_R_2H"]
)
* c["M_2H_1H_16O"]
+ 2
* Trivia.mixing_ratio_to_specific_content(c["VSMOW_R_3H"])
* Trivia.isotopic_fraction_assuming_single_heavy_isotope(
isotopic_ratio=c["VSMOW_R_3H"]
)
* c["M_3H_1H_16O"]
+ 1 * Trivia.mixing_ratio_to_specific_content(c["VSMOW_R_17O"]) * c["M_1H2_17O"]
+ 1 * Trivia.mixing_ratio_to_specific_content(c["VSMOW_R_18O"]) * c["M_1H2_18O"]
+ Trivia.isotopic_fraction_assuming_single_heavy_isotope(
isotopic_ratio=c["VSMOW_R_17O"]
)
* c["M_1H2_17O"]
+ Trivia.isotopic_fraction_assuming_single_heavy_isotope(
isotopic_ratio=c["VSMOW_R_18O"]
)
* c["M_1H2_18O"]
)

c["eps"] = c["Mv"] / c["Md"]
c["Rd"] = c["R_str"] / c["Md"]
c["Rv"] = c["R_str"] / c["Mv"]
Expand Down
74 changes: 71 additions & 3 deletions PySDM/physics/trivia.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,18 @@ def isotopic_enrichment_to_delta_SMOW(E, delta_0_SMOW):
def mixing_ratio_to_specific_content(mixing_ratio):
return mixing_ratio / (1 + mixing_ratio)

@staticmethod
def isotopic_fraction_assuming_single_heavy_isotope(*, isotopic_ratio):
"""
isotopic ratio = n1/n2
isotopic fraction = n1/n_total = n1 / (n1 + n2) = isotopic_ratio / (1 + isotopic_ratio)
"""
return isotopic_ratio / (1 + isotopic_ratio)

@staticmethod
def isotopic_ratio_assuming_single_heavy_isotope(isotopic_fraction):
return isotopic_fraction / (1 - isotopic_fraction)

@staticmethod
def dn_dlogr(r, dn_dr):
return np.log(10) * r * dn_dr
Expand Down Expand Up @@ -172,12 +184,12 @@ def tau(Bo, dm_dt_over_m):
@staticmethod
def moles_heavy_atom(
*,
atoms_per_heavy_molecule,
mass_total,
mass_other_heavy_isotopes,
molar_mass_light_molecule,
molar_mass_heavy_molecule,
molecular_isotope_ratio,
atoms_per_heavy_molecule,
molecular_isotopic_ratio,
):
"""
Calculate moles of heavy atoms (e.g. deuterium, oxygen-17, oxygen-18)
Expand All @@ -187,8 +199,64 @@ def moles_heavy_atom(
return (
(mass_total - mass_other_heavy_isotopes)
/ (
molar_mass_light_molecule / molecular_isotope_ratio
molar_mass_light_molecule / molecular_isotopic_ratio
+ molar_mass_heavy_molecule
)
/ atoms_per_heavy_molecule
)

@staticmethod
def molecular_isotopic_ratio(
*,
moles_heavy_molecule,
mass_total,
mass_other_heavy_isotopes,
molar_mass_light_molecule,
molar_mass_heavy_molecule,
):
"""
Molecular isotope ratio (e.g. moles of HDO to moles of H2O):
n_{heavy molecule}/n_{light molecule},
in contrast to (atomic) isotopic ratio as in VSMOW standard:
n_{heavy atom}/n_{light atom};

calculated with:
m_light = m_total - m_considered_heavy_isotope - m_other_heavy_isotopes
"""
return (
moles_heavy_molecule
* molar_mass_light_molecule
/ (
mass_total
- moles_heavy_molecule * molar_mass_heavy_molecule
- mass_other_heavy_isotopes
)
)

@staticmethod
def molality_in_dry_air(
isotopic_fraction, density_dry_air, total_vap_concentration
):
"""
n'/m_d [number of moles of isotopic molecules]/[mass of dry air] - molality in dry air
n/V - total vapour concentration

molality_in_dry_air = n'/m_d =
= n'/(rho_d * V) = isotopic_concentration / rho_d
isotopic_concentration = n'/V = n/V * n'/n =
= total vapour concentration * isotopic_fraction

where n'/n is an isotopic fraction (referred to as isotopic concentration (C)
on p. 10 in [Gat 2010](https://doi.org/10.1142/p027)
"""
return total_vap_concentration * isotopic_fraction / density_dry_air

@staticmethod
def isotopic_fraction(
molality_in_dry_air, density_dry_air, total_vap_concentration
):
"""
isotopic_fraction: n'/n = n'/m_d / (n/V) * rho_d
= molality in dry air / total vapour concentration * dry air density
"""
return molality_in_dry_air / total_vap_concentration * density_dry_air
9 changes: 8 additions & 1 deletion docs/bibliography.json
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@
},
"https://doi.org/10.1142/p027": {
"usages": [
"PySDM/physics/constants_defaults.py"
"PySDM/physics/trivia.py"
],
"label": "Gat 2010",
"title": "Isotope Hydrology: A Study of the Water Cycle"
Expand Down Expand Up @@ -1004,5 +1004,12 @@
],
"label": "Bartman 2020 (MSc thesis)",
"title": "PySDM v1.0: Pythonic particle-based cloud microphysics package"
},
"https://web.archive.org/web/20220629123450/https://web.gps.caltech.edu/~als/research-articles/other_stuff/hayes-2004-3.pdf" : {
"usages": [
"tests/unit_tests/physics/test_constants.py"
],
"label": "Hayes 2004",
"title": "An Introduction to Isotopic Calculations"
}
}
2 changes: 1 addition & 1 deletion docs/generate_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def check_urls(urls_from_json):
r"\b(https://digitallibrary\.un\.org/record/(?:[0-9])+)\b",
r"\b(http://mi\.mathnet\.ru/dan(?:[0-9])+)\b",
r"\b(https://archive\.org/details/(?:[0-9a-z_\.-])+)\b",
r"\b(https://web\.archive\.org/web/(?:[0-9])+/https://(?:[0-9a-zA-Z_\.-/])+)\b",
r"\b(https://web\.archive\.org/web/(?:[0-9])+/https://(?:[0-9a-zA-Z_\.\-/~%])+)\b",
r"\b(https://www\.ap\.uj\.edu\.pl/diplomas/attachments/file/download/(?:[0-9])+)\b",
):
urls = re.findall(pattern, text)
Expand Down
Loading
Loading