forked from AndrewILWilliams/PB05
-
Notifications
You must be signed in to change notification settings - Fork 0
/
saturation_thermodynamics.py
115 lines (73 loc) · 3.25 KB
/
saturation_thermodynamics.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import numpy as np
import constants as const
def get_saturation_thermodynamics(T,p,thermo_type='simple'):
#thermo_type = 'simple' or 'era' are implemented
Rd = const.rd
Rv = const.rv
gc_ratio = Rd/Rv
if thermo_type == 'era':
# ECMWF formulation described by Simmons et al. (1999: QJRMS, 125,
# 353--386), which uses saturation over ice for temperatures
# less than 250 K and a quadratic interpolation between
# saturation over ice and over liquid water for temperatures
# between 250 K and 273 K
# coefficients in Tetens saturation vapor pressure es = es0 * exp(a3 * (T-T0)/(T-a4))
es0 = 611.21 # saturation vapor pressure at T0 (Pa)
T0 = 273.16 # (K)
Ti = T0 - 23 # (K)
a3l = 17.502 # liquid water (Buck 1981)
a4l = 32.19 # (K)
a3i = 22.587 # ice (Alduchov and Eskridge 1996)
a4i = -0.7 # (K)
# saturation vapor pressure over liquid and ice
esl = es0 * np.exp(a3l * (T - T0)/(T - a4l))
esi = es0 * np.exp(a3i * (T - T0)/(T - a4i))
# latent heat of sublimation
Ls0 = 2.834e6 # latent heat of sublimation (J / kg) [+- 0.01 error for 173 K < T < 273 K]
# set up output arrays
Ls = Ls0 * np.ones(T.shape)
# latent heat of vaporization
Lv0 = 2.501e6 # latent heat of vaporization at triple point (J / kg)
cpl = 4190 # heat capacity of liquid water (J / kg / K)
cpv = 1870 #heat capacity of water vapor (J / kg / K)
Lv = Lv0 - (cpl - cpv) * (T - T0)
# compute saturation vapor pressure and latent heat over liquid/ice mixture
#iice = T <= Ti
#iliquid = T >= T0
#imixed = (T > Ti) & (T < T0)
iice = np.where(T <= Ti)
iliquid = np.where(T >= T0)
imixed = np.where((T > Ti) & (T < T0))
#print(iice)
#print(iliquid)
#print(imixed)
#print(len(iice))
#print(len(iliquid))
#print(len(imixed))
es = np.nan * np.ones(T.shape)
L = np.nan * np.ones(T.shape)
a = np.nan * np.ones(T.shape)
es = esl
L = Lv
es = np.where(T <= Ti, esi, es)
L = np.where(T <= Ti, Ls, Lv)
a = np.where((T > Ti) & (T < T0), ( (T - Ti)/(T0 - Ti) )**2, a)
es = np.where((T > Ti) & (T < T0), (1-a) * esi + a * esl, es)
L = np.where((T > Ti) & (T < T0), (1-a) * Ls + a * Lv, L)
elif thermo_type == 'simple':
# simple formulation
# assuming constant latent heat of vaporization and only one
# vapor-liquid phase transition
# used in O'Gorman & Schneider 2008 iGCM
T0 = 273.16 # K
es0 = 610.78 # Pa
L = const.Lv
# saturation vapor pressure
es = es0 * np.exp(L/Rv*(1.0/T0 - 1.0/T));
else:
raise ValueError("Unknown type of computing saturation quantities.")
# saturation mixing ratio
rs = gc_ratio * es / (p - es);
# saturation specific humidity
qs = rs / (1 + rs);
return es, qs, rs, L