From 7c9af22d5106b84b202bf38b324d7dbfde876d7e Mon Sep 17 00:00:00 2001
From: XANTRONIX Industrial <xan@xantronix.com>
Date: Fri, 7 Mar 2025 13:58:58 -0500
Subject: [PATCH] Implement mixing_ratio_temp()

---
 lib/xmet/thermo.py | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/lib/xmet/thermo.py b/lib/xmet/thermo.py
index b48bbe9..2631782 100644
--- a/lib/xmet/thermo.py
+++ b/lib/xmet/thermo.py
@@ -1,3 +1,5 @@
+import math
+
 from typing import Callable
 
 LAPSE_RATE_DRY   = 9.8 / 1000 # degrees C per km
@@ -10,6 +12,9 @@ PRESSURE_STEP =   50
 def kelvin(c: float) -> float:
     return 273.15 + c
 
+def celsius(k: float) -> float:
+    return k - 273.15
+
 def vapor_pressure(dewpoint: float) -> float:
     """
     Return the pressure, in millibar, of vapor in a parcel of a given
@@ -42,6 +47,23 @@ def saturated_mixing_ratio(temp: float, pressure: float) -> float:
 
     return (0.62197 * es) / (pressure - es)
 
+def mixing_ratio_temp(ratio: float, pressure: float) -> float:
+    """
+    Return the temperature, in degrees celsius, of a given mixing ratio at a
+    specified pressure, in millibar.
+    """
+    c1 = 0.0498646455
+    c2 = 2.4082965
+    c3 = 7.07475
+    c4 = 38.9114
+    c5 = 0.0915
+    c6 = 1.2035
+
+    x = math.log10(ratio * pressure / (622.0 + ratio))
+
+    return celsius(math.pow(10.0, ((c1 * x) + c2)) - c3 + \
+             (c4 * math.pow((math.pow(10, (c5 * x)) - c6), 2)))
+
 def lcl(temp: float, dewpoint: float) -> float:
     """
     Return the height, in meters, at which a parcel of the given temperature