Compare commits

...

2 commits

Author SHA1 Message Date
45e616b39f Use virtual temperature to fix CAPE calculation 2025-03-14 21:10:39 -04:00
cd6bb30167 Implement Series.nearest()
Implement Series.nearest() to allow finding value by nearest key in a
Series object
2025-03-14 20:54:01 -04:00
3 changed files with 28 additions and 10 deletions

View file

@ -50,3 +50,8 @@ class Series(dict):
if sign is intersection: if sign is intersection:
return v1, pair[0] return v1, pair[0]
def nearest(self, key):
k = sorted(self.keys(), key=lambda k: abs(k-key))[0]
return self[k]

View file

@ -260,7 +260,7 @@ class SkewTGraph():
if self.opts.draw_cape_mixing_ratio: if self.opts.draw_cape_mixing_ratio:
cr.set_source_rgb(0.8, 0.8, 1.0) cr.set_source_rgb(0.8, 0.8, 1.0)
self.draw_series(cr, x, y, params.saturated_mr_line) self.draw_series(cr, x, y, params.mixing_ratio_line)
def draw(self, def draw(self,
cr: cairo.Context, cr: cairo.Context,

View file

@ -10,6 +10,7 @@ from xmet.thermo import follow_dry_adiabat, \
follow_moist_adiabat, \ follow_moist_adiabat, \
follow_saturated_mixing_ratio, \ follow_saturated_mixing_ratio, \
pressure_height, \ pressure_height, \
virtual_temp, \
kelvin kelvin
LAPSE_RATE_DRY = 9.8 # degrees C per 1000m LAPSE_RATE_DRY = 9.8 # degrees C per 1000m
@ -233,19 +234,31 @@ class SoundingParams():
return 9.8076 * cape return 9.8076 * cape
def load_sounding(self, sounding: Sounding): def load_sounding(self, sounding: Sounding):
surface = sounding.samples[0]
tv = virtual_temp(surface.temp,
surface.dewpoint,
surface.pressure)
temp_line = sounding.follow_temp() temp_line = sounding.follow_temp()
dry_adiabat = follow_dry_adiabat(sounding.samples[0].temp, dewpoint_line = sounding.follow_dewpoint()
sounding.samples[0].pressure) dry_adiabat = follow_dry_adiabat(tv, surface.pressure)
saturated_mr_line = follow_saturated_mixing_ratio(sounding.samples[0].dewpoint, mixing_ratio_line = follow_saturated_mixing_ratio(surface.dewpoint,
sounding.samples[0].pressure) surface.pressure)
lcl = dry_adiabat.intersect(saturated_mr_line, SeriesIntersection.LESSER) lcl = dry_adiabat.intersect(mixing_ratio_line,
SeriesIntersection.LESSER)
moist_adiabat = follow_moist_adiabat(*lcl) tv2 = virtual_temp(temp_line.nearest(lcl[1]),
dewpoint_line.nearest(lcl[1]),
lcl[1])
moist_adiabat = follow_moist_adiabat(tv2, lcl[1])
lfc = temp_line.intersect(moist_adiabat, SeriesIntersection.LESSER) lfc = temp_line.intersect(moist_adiabat, SeriesIntersection.LESSER)
el = temp_line.intersect(moist_adiabat, SeriesIntersection.GREATER, lfc[1]-100) el = temp_line.intersect(moist_adiabat, SeriesIntersection.GREATER,
lfc[1])
self.lcl = lcl self.lcl = lcl
self.lfc = lfc self.lfc = lfc
@ -254,7 +267,7 @@ class SoundingParams():
self.temp_line = temp_line self.temp_line = temp_line
self.dry_adiabat = dry_adiabat self.dry_adiabat = dry_adiabat
self.saturated_mr_line = saturated_mr_line self.mixing_ratio_line = mixing_ratio_line
self.moist_adiabat = moist_adiabat self.moist_adiabat = moist_adiabat
@staticmethod @staticmethod