Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
| Download

📚 The CoCalc Library - books, templates and other resources

Views: 96140
License: OTHER
1
2
# coding: utf-8
3
4
# # Analytical solutions of leaf energy balance
5
# Based on the following paper:
6
# Schymanski, S.J. and Or, D. (2016): [Leaf-scale experiments reveal important omission in the Penman-Monteith equation.](http://www.hydrol-earth-syst-sci-discuss.net/hess-2016-363/) Hydrology and Earth System Sciences Discussions, p.1–33. doi: 10.5194/hess-2016-363.
7
#
8
# Author: Stan Schymanski ([email protected])
9
#
10
# This worksheet relies on definitions provided in Worksheets [Worksheet_setup](Worksheet_setup.ipynb) and [leaf_enbalance_eqs](Leaf_enbalance_eqs.ipynb).
11
12
# In[1]:
13
14
get_ipython().run_cell_magic(u'capture', u'storage', u"# The above redirects all output of the below commands to the variable 'storage' instead of displaying it.\n# It can be viewed by typing: 'storage()'\n# Setting up worksheet and importing equations for explicit leaf energy balance\nload('temp/Worksheet_setup.sage')\nload_session('temp/leaf_enbalance_eqs.sobj')\nfun_loadvars(vardict=dict_vars) # re-loading variable definitions")
15
16
17
# ## Definition of additional variables
18
# In addition to variables defined in Worksheet Leaf_enbalance_eqs, we need a few more, as defined below.
19
# All variables are also listed in a [Table](#Table-of-symbols) at the end of this document.
20
21
# In[2]:
22
23
var2('beta_B', 'Bowen ratio (sensible/latent heat flux)', 1/1, latexname = '\\beta_B')
24
var2('Delta_eTa', 'Slope of saturation vapour pressure at air temperature', pascal/kelvin, latexname = '\\Delta_{eTa}')
25
var2('epsilon', 'Water to air molecular weight ratio (0.622)', value = 0.622)
26
var2('E_w', 'Latent heat flux from a wet surface',joule/second/meter^2)
27
var2('f_u', 'Wind function in Penman approach, f(u) adapted to energetic units', joule/(meter^2*pascal*second))
28
var2('gamma_v', 'Psychrometric constant', pascal/kelvin)
29
var2('n_MU', 'n=2 for hypostomatous, n=1 for amphistomatous leaves')
30
var2('r_a', 'One-sided boundary layer resistance to heat transfer ($r_H$ in \citet[][P. 231]{monteith_principles_2013})', second/meter)
31
var2('r_v', 'Leaf BL resistance to water vapour, \citep[][Eq. 13.16]{monteith_principles_2013}', second/meter, latexname = 'r_{v}')
32
var2('r_s', 'Stomatal resistance to water vapour \citep[][P. 231]{monteith_principles_2013}', second/meter)
33
var2('S', 'Factor representing stomatal resistance in \citet{penman_physical_1952}')
34
35
36
# ## Penman (1948)
37
# In order to obtain analytical expressions for the different leaf energy balance components, one would need to solve the leaf energy balance equation for leaf temperature first. However, due to the non-linearities of the blackbody radiation and the saturation vapour pressure equations, an analytical solution has not been found yet. \citet{penman_natural_1948} proposed a work-around, which we reproduced below, adapted to our notation and to a wet leaf, while Penman's formulations referred to a wet soil surface. He formulated evaporation from a wet surface as a diffusive process driven by the vapour pressure difference near the wet surface and in the free air:
38
# ##### {eq_Ew_fu}
39
# $$E_{w} = f_u (P_{wl} - P_{wa})$$
40
#
41
# where $E_w$ (J~s$^{-1}$~m$^{-2}$) is the latent heat flux from a wet surface and $f_u$ is commonly referred to as the wind function. Penman then defined the Bowen ratio as (Eq. 10 in \citet{penman_natural_1948}):
42
# ##### {eq_beta_B}
43
# $$\beta_B = H_l/E_w = \gamma_v \frac{T_l - T_a}{P_{wl} - P_{wa}}$$
44
#
45
# where $H_l$ is the sensible heat flux and $\gamma_v$ is the psychrometric constant, referring to the ratio between the transfer coefficients for sensible heat and that for water vapour.
46
47
# In[3]:
48
49
eq_Ew_fu = E_w == f_u*(P_wl - P_wa)
50
units_check(eq_Ew_fu).simplify_full()
51
52
53
# In[4]:
54
55
eq_beta_B = beta_B == gamma_v*(T_l - T_a)/(P_wl - P_wa)
56
units_check(eq_beta_B).full_simplify()
57
58
59
# In order to eliminate $T_l$, Penman introduced a term for the ratio of the vapour pressure difference between the surface and the saturation vapour pressure at air temperature ($P_{was}$) to the temperature difference between the surface and the air:
60
# ##### {eq_Penman_ass}
61
# $$ \Delta_{eTa} = \frac{P_{wl} - P_{was}}{T_l - T_a}$$
62
#
63
# and he proposed to approximate this term by the slope of the saturation vapour pressure curve evaluated at air temperature, which can be obtained by substitution of $T_a$ for $T_l$ and differentiation of Eq. eq_Pwl with respect to $T_a$:
64
# ##### {eq_Deltaeta_Ta}
65
# $$\Delta_{eTa} = \frac{611 \lambda_E M_w \exp \left( \frac{\lambda_E M_w}{R_{mol}} \left( \frac{1}{273} - \frac{1}{T_a} \right) \right)}{R_{mol} T_a^2}$$
66
#
67
# For further discussion of the meaning of this assumption, please refer to \citet{mallick_surface_2014}.
68
69
# In[5]:
70
71
eq_Penman_ass = Delta_eTa == (P_wl - P_was)/(T_l - T_a)
72
units_check(eq_Penman_ass).simplify_full()
73
74
75
# In[6]:
76
77
eq_Pwas_Ta = P_was == eq_Pwl.rhs()(T_l = T_a)
78
eq_Pwas_Ta.show()
79
80
81
# In[7]:
82
83
eq_Deltaeta_T = Delta_eTa == diff(eq_Pwl.rhs()(T_l = T_a), T_a)
84
show(eq_Deltaeta_T)
85
86
87
# Susbstitution of Eq. {eq_Penman_ass} in Eq. {eq_beta_B} yields (Eq. 15 in \citet{bowen_ratio_1926}):
88
# ##### {eq_betaB_Pwas}
89
# $$\beta_B = \frac{\gamma_v}{\Delta_{eTa}}\frac{(P_{wl} - P_{was})}{(P_{wl} - P_{wa})}$$
90
#
91
# Substituting $E_w$ for $E_l$ and inserting $H_l = \beta_B E_w$ (Eq. {eq_beta_B}) into the energy balance equation (Eq. {eq_Rs_enbal}) and solving for $E_w$ gives:
92
# ##### {eq_Ew_betaB}
93
# $$E_w = \frac{R_s - R_{ll}}{\beta_B + 1}$$
94
#
95
# Substitution of Eq. {eq_betaB_Pwas} into Eq. {eq_Ew_betaB}, equating with Eq. {eq_Ew_fu} and solving for $P_{wl}$ gives:
96
# ##### {eq_Pwl_fu}
97
# $$P_{wl} = \frac{f_u (\Delta_{eTa} P_{wa} + \gamma_v P_{was}) + \Delta_{eTa} (R_s - R_{ll})}
98
# {f_u (\Delta_{eTa} + \gamma_v)}$$
99
#
100
# Now, insertion of Eq. {eq_Pwl_fu} into Eq. {eq_Ew_fu} gives the so-called "Penman equation" :
101
# ##### {eq_Ew_P}
102
# $$E_w = \frac{\Delta_{eTa}(R_s - R_{ll}) + f_u \gamma_v (P_{was} - P_{wa})}
103
# {\Delta_{eTa} + \gamma_v}$$
104
#
105
#
106
# Eq. {eq_Ew_P} is equivalent to Eq 16 in \citet{penman_natural_1948}, but Eq. 17 in \citet{penman_natural_1948}, which should be equivalent to Eq. {eq_Pwl_fu}, has $P_{wl}$ ($e_s$ in Penman's notation) on both sides, so it seems to contain an error. In his derivations, Penman expressed $R_s - R_{ll}$ as "net radiant energy available at surface" and pointed out that the above two equations can be used to estimate $E_l$ and $T_l$ from air conditions only. This neglects the fact that $R_{ll}$ is also a function of the leaf temperature. To estimate surface temperature, Eq. {eq_Pwl_fu} can be inserted into Eq. {eq_Penman_ass} and solved for $T_l$, yielding:
107
# ##### {eq_Tl_P}
108
# $$T_l = \frac{R_s - R_{ll} + f_u (\gamma_v T_a + \Delta_{eTa} T_a + P_{wa} - P_{was})}{f_u(\gamma_v + \Delta_{eTa})}$$
109
#
110
111
# In[8]:
112
113
soln = solve([eq_beta_B, eq_Penman_ass], beta_B, T_l)
114
eq_betaB_Pwas = soln[0][0].factor()
115
units_check(eq_betaB_Pwas).simplify_full()
116
117
118
# In[9]:
119
120
eq_Ew_betaB = solve(eq_Rs_enbal(E_l = E_w, H_l = beta_B*E_w), E_w)[0]
121
units_check(eq_Ew_betaB).simplify_full()
122
123
124
# In[10]:
125
126
soln = solve([eq_betaB_Pwas, eq_Ew_betaB, eq_Ew_fu], P_wl, E_w, beta_B)
127
print soln
128
eq_Pwl_fu = soln[0][0].factor()
129
eq_Ew_P = soln[0][1]
130
units_check(eq_Pwl_fu)
131
units_check(eq_Ew_P)
132
133
134
# In[11]:
135
136
soln = solve(eq_Penman_ass.subs(eq_Pwl_fu), T_l)
137
eq_Tl_P = soln[0]
138
units_check(eq_Tl_P)
139
140
141
# In[12]:
142
143
eq_Tl_P.subs(eq_Pwl(P_wl = P_was, T_l = T_a)).show()
144
145
146
# In[13]:
147
148
soln = solve([eq_Penman_ass, eq_Pwl_fu], T_l, P_wl)
149
#for eq in flatten(soln):
150
# eq.show()
151
eq_Tl_P = soln[0][0]
152
print units_check(eq_Tl_P)
153
eq_Pwl_P_wet = soln[0][1]
154
units_check(eq_Pwl_P_wet)
155
156
157
# In[14]:
158
159
# Alternative approach to get T_l, followoing Eq. 17 in Penman (1948), which is eq_Pwl_P_wet
160
soln = solve(eq_Pwl.rhs() == eq_Pwl_P_wet.rhs(), T_l)
161
eq_Tl_P1 = soln[0].simplify_full()
162
show(eq_Tl_P1)
163
164
165
# ## Introduction of stomatal resistance by \citet{penman_physical_1952}
166
# To account for stomatal resistance to vapour diffusion, \citet{penman_physical_1952} introduced an additional multiplicator ($S$) in Eq. {eq_Ew_fu} \citep[Appendix 13]{penman_physical_1952}:
167
# ##### {eq_El_fu_S}
168
# $$E_l = f_u S (P_{wl} - P_{wa})$$
169
#
170
# where $S=1$ for a wet surface (leading to Eq. {eq_Ew_fu}) and $S<1$ in the presence of significant stomatal resistance.
171
#
172
# In accordance with Eqs. {eq_Ew_fu} and {eq_beta_B}, $H_l$ can be expressed as \citep[Appendix 13]{penman_physical_1952}:
173
# ##### {eq_Hl_Tl_P52}
174
# $$H_l = \gamma_v f_u (T_l - T_a)$$
175
#
176
# Substitution of Penman's simplifying assumption ($T_l - T_a = (P_{wl} - P_{was})/\Delta_{eT}$, Eq. {eq_Penman_ass}) is the first step to eliminating $T_l$:
177
# ##### {eq_Hl_Pwl_P52}
178
# $$H_l = \frac{\gamma_v f_u (P_{wl} - P_{was})}{\Delta_{eTa}}$$
179
#
180
# A series of algebraic manipulations involving Eqs. {eq_El_fu_S}, {eq_Hl_Pwl_P52} and {eq_Rs_enbal} and the resulting Eq. {eq_El_P52} is given in \citet[Appendix 13]{penman_physical_1952}. When solving Eqs. {eq_El_fu_S}, {eq_Hl_Pwl_P52} and {eq_Rs_enbal} for $E_l$, $H_l$ and $P_{wl}$, we obtained:
181
#
182
# ##### {eq_El_P52}
183
# $$E_l = \frac{S \Delta_{eTa}(R_s - R_{ll}) + S \gamma_v f_u (P_{was} - P_{wa})}{S \Delta_{eT} + \gamma_v} $$
184
#
185
# ##### {eq_Hl_P52}
186
# $$H_{l} = \frac{\gamma_{v} \left(R_s - {R_{ll}}\right) + S \gamma_{v} f_{u} \left({P_{wa}} - {P_{was}}\right)}
187
# {S \Delta_{eTa} + \gamma_{v}}$$
188
#
189
# ##### {eq_Pwl_P52}
190
# $$P_{wl} = \frac{\left(\Delta_{eTa}/f_u\right) \left(R_s - {R_{ll}}\right)+ \left({S \Delta_{eTa}} {P_{wa}} + \gamma_{v} {P_{was}}\right)}
191
# {{S \Delta_{eTa}} + \gamma_{v}}$$
192
# \end{equation}
193
194
# In[15]:
195
196
eq_El_fu_S = E_l == f_u*S*(P_wl - P_wa)
197
units_check(eq_El_fu_S)
198
199
200
# In[16]:
201
202
eq_Hl_Tl_P52 = solve((H_l/E_w == eq_beta_B.rhs()).subs(eq_Ew_fu), H_l)[0]
203
units_check(eq_Hl_Tl_P52)
204
205
206
# In[17]:
207
208
soln = solve([eq_Hl_Tl_P52, eq_Penman_ass], H_l, T_l)
209
for eq in flatten(soln):
210
eq.show()
211
eq_Hl_Pwl_P52 = soln[0][0]
212
units_check(eq_Hl_Pwl_P52)
213
214
215
# In[18]:
216
217
soln = solve([eq_Hl_Pwl_P52,eq_El_fu_S, eq_Rs_enbal], E_l, H_l, P_wl)
218
[eq_El_P52, eq_Hl_P52, eq_Pwl_P52] = flatten(soln)
219
for eq in flatten(soln):
220
print units_check(eq)
221
222
223
# ### Analytical solutions for leaf temperature, $f_u$, $\gamma_v$ and $S$
224
#
225
# Equation {eq_Pwl_P52} can be inserted into Eq. {eq_Penman_ass} and solved for leaf temperature to yield:
226
# ##### {eq_Tl_p52}
227
# $$T_{l} = T_{a} + \frac{R_{s} - R_{ll} - S f_{u}(P_{was}-P_{wa})}
228
# {f_{u} \left(S \Delta_{eT} + \gamma_{v}\right) }$$
229
#
230
#
231
# \citet{penman_physical_1952} proposed to obtain values of $f_u$ and $S$ for a plant canopy empirically and described ways how to do this. However, for a single leaf, $f_u$ and $S$ could also be obtained analytically from our detailed mass and heat transfer model.
232
#
233
# Comparison of Eq. {eq_El_fu_S} with Eq. {eq_Elmol_conv} (after substituting Eq. {eq_El}) reveals that $S$ is equivalent to:
234
# ##### {eq_S_gtwmol_fu}
235
# $$S = \frac{M_{w} g_{tw,mol} \lambda_{E}}{P_{a} f_{u}}$$
236
#
237
# where $f_u$ was defined by \citet{penman_natural_1948} as the transfer coeffient for wet surface evaporation, i.e. a function of the boundary layer conductance only.
238
#
239
# To find a solution for $f_u$, we first formulate $E_w$ as transpiration from a leaf where $g_{tw} = g_{bw}$, using Eqs. {eq_El}, {eq_Elmol_conv} and {eq_gtwmol_gtw_iso}:
240
# ##### {eq_Ew_conv}
241
# $$E_w = \frac{\lambda_E M_w g_{bw}}{R_{mol} T_a} (P_{wl} - P_{wa})$$
242
#
243
# Comparison of Eq. {eq_Ew_conv} with {eq_Ew_fu} gives $f_u$ as a function of $g_{bw}$:
244
# ##### {eq_fu_gbw}
245
# $$f_u = g_{bw}\frac{\lambda_E M_w}{R_{mol} T_a}$$
246
#
247
# Comparison between Eq. {eq_Hl_Tl_P52} and Eq. {eq_Hl} reveals that
248
# ##### {eq_gammav_hc_fu}
249
# $$\gamma_v = \frac{a_{sh} h_c}{f_u},$$
250
#
251
# and insertion of Eqs. {eq_fu_gbw} and {eq_gbw_hc} give $\gamma_v$ as a function of $a_{sh}$ and $a_s$:
252
# ##### {eq_gammav_as}
253
# $$\gamma_{v} =a_{sh}/a_s \frac{{N_{Le}}^{\frac{2}{3}} {R_{mol}} T_{a} \rho_{a} c_{pa}}{\lambda_{E} M_{w}}$$
254
#
255
# Now, we can insert Eqs. {eq_fu_gbw}, {eq_gtwmol_gtw_iso} and {eq_gtw} into Eq. {eq_S_gtwmol_fu} to obtain $S$ as a function of $g_{sw}$ and $g_{bw}$:
256
# ##### {eq_S_gsw_gbw}
257
# $$S = \frac{g_{sw}}{g_{bw} + g_{sw}}$$
258
#
259
# The above equation illustrates that $S$ is not just a function of stomatal conductance, but also the leaf boundary layer conductance, explaining why \citet{penman_physical_1952} found that $S$ depends on wind speed.
260
261
# In[19]:
262
263
soln = solve([eq_Penman_ass, eq_Pwl_P52], T_l, P_wl)
264
eq_Tl_P52 = soln[0][0]
265
latex(eq_Tl_P52)
266
units_check(eq_Tl_P52)
267
268
269
# In[20]:
270
271
eq_S_gtwmol_fu = solve([eq_El_fu_S.subs(eq_El), eq_Elmol_conv], S, E_lmol)[0][0]
272
units_check(eq_S_gtwmol_fu)
273
274
275
# In[21]:
276
277
eq_Hl_Tl_P52.show()
278
279
280
# In[22]:
281
282
eq_Hl.show()
283
284
285
# In[23]:
286
287
eq_gammav_hc_fu = solve(eq_Hl_Tl_P52.rhs() == eq_Hl.rhs(), gamma_v)[0]
288
units_check(eq_gammav_hc_fu)
289
290
291
# In[24]:
292
293
eq_El_fu_S.show()
294
295
296
# In[25]:
297
298
eq_Ew_conv = eq_El.subs(eq_Elmol_conv).subs(eq_gtwmol_gtw_iso)(g_tw = g_bw, E_l = E_w)
299
units_check(eq_Ew_conv)
300
301
302
# In[26]:
303
304
eq_fu_gbw = solve(eq_Ew_conv.rhs() == eq_Ew_fu.rhs(), f_u)[0]
305
units_check(eq_fu_gbw)
306
307
308
# In[27]:
309
310
eq_gammav_hc_fu = solve(eq_Hl_Tl_P52.rhs() == eq_Hl.rhs(), gamma_v)[0]
311
units_check(eq_gammav_hc_fu)
312
313
314
# In[28]:
315
316
eq_gammav_as = eq_gammav_hc_fu.subs(eq_fu_gbw).subs(eq_gbw_hc)
317
units_check(eq_gammav_as)
318
319
320
# In[29]:
321
322
eq_S_gbw_gsw = eq_S_gtwmol_fu.subs(eq_fu_gbw).subs(eq_gtwmol_gtw_iso).subs(eq_gtw).simplify_full()
323
units_check(eq_S_gbw_gsw)
324
325
326
# In[30]:
327
328
eq_El_P52.subs(eq_S_gbw_gsw, eq_fu_gbw).subs(g_bw = 1/r_bw, g_sw = 1/r_sw).simplify_full().show()
329
330
331
# In[31]:
332
333
eq_El_P52.subs(eq_S_gbw_gsw, eq_fu_gbw).subs(eq_gammav_as).simplify_full().show()
334
335
336
# In[32]:
337
338
eq_El_P52.subs(eq_S_gbw_gsw, eq_fu_gbw).subs(g_sw = 1/r_sw, g_bw = 1/r_bw).simplify_full().show()
339
340
341
# In[33]:
342
343
eq_El_P52.subs(eq_S_gbw_gsw, eq_fu_gbw).subs(g_sw = 1/r_sw, g_bw = 1/r_bw).subs(eq_gammav_as).simplify_full().show()
344
345
346
# In[34]:
347
348
eq_El_P52.subs(eq_S_gbw_gsw, eq_fu_gbw, eq_gammav_as).simplify_full().show()
349
350
351
# ## Penman-Monteith equation
352
# \citet{monteith_evaporation_1965} re-derived Eq. {eq_Ew_P} using a different set of arguments than Penman in his original derivation and arrived to an equivalent equation (Eq. 8 in \citet{monteith_evaporation_1965}):
353
# ##### {eq_Ew_PM1}
354
# $$E_w = \frac{\Delta_{eTa}(R_s - R_{ll}) + \rho_a c_{pa} (P_{was} - P_{wa})/r_a}
355
# {\Delta_{eTa} + \gamma_v} ,$$
356
#
357
# where $r_a$ is the leaf boundary layer resistance to sensible heat flux.
358
# Eq. {eq_Ew_PM1} is consistent with Eq. {eq_Ew_P} if Penman's wind function ($f_u$) is replaced by:
359
# ##### {eq_fu_ra_M}
360
# $$f_u = \frac{\rho_a c_{pa}}{\gamma_v r_a}.$$
361
#
362
#
363
# Monteith pointed out that the ratio between the conductance to sensible heat and the conductance to water vapour transfer, expressed in the psychrometric constant ($\gamma_v$) would be affected by stomatal resistance ($r_{sw}$) and hence proposed to replace the psychrometric constant by $\gamma_v^*$:
364
# ##### {eq_gammavs_M65}
365
# $$\gamma_v^* = \gamma_v(1 + \frac{r_s}{r_a}),$$
366
#
367
# leading to the so-called Penman-Monteith equation for transpiration:
368
# ##### {eq_El_PM2}
369
# $$E_l = \frac{\Delta_{eTa}(R_s - R_{ll}) + \rho_a c_{pa} (P_{was} - P_{wa})/r_a}
370
# {\Delta_{eTa} + \gamma_v \left(1 + \frac{r_{s}}{r_a}\right)} $$
371
#
372
#
373
# More recently, \citet{monteith_principles_2013} pointed out that the difference between leaves with stomata on only one side and those with stomata on both sides can also be considered by further modifying $\gamma_v^*$ to:
374
# ##### {eq_gammavs_MU}
375
# $$\gamma_v^* = n_{MU} \gamma_v (1 + r_s/r_a)$$
376
#
377
# where $n_{MU} = 1$ for leaves with stomata on both sides and $n_{MU} = 2$ for leaves with stomata on one side, i.e. $n_{MU} = a_{sh}/a_s$ in our notation.
378
# Insertion of Eq. {eq_gammavs_MU} into Eq. {eq_Ew_PM1} yields what we will call the Monteith-Unsworth (MU) equation, which only differs from the Penman-Monteith equation by the additional factor $n_{MU}$:
379
# ##### {eq_El_MU2}
380
# $$E_l = \frac{\Delta_{eTa}(R_s - R_{ll}) + \rho_a c_{pa} (P_{was} - P_{wa})/r_a}
381
# {\Delta_{eTa} + \gamma_v n_{MU} \left(1 + \frac{r_{s}}{r_a}\right)} $$
382
#
383
# \citet{monteith_principles_2013} also provide a definition of $\gamma_v$ as:
384
# ##### {eq_gammav_MU}
385
# $$\gamma_v = \frac{c_{pa} P_a}{\lambda_E \epsilon}$$
386
#
387
# where $\epsilon$ is the ratio of molecular weights of water vapour and air (given by \citet{monteith_principles_2013} as 0.622).
388
# Note that Equation {eq_gammavs_MU} was derived based on the assumption that $r_a$ refers to one-sided resistance to sensible heat transfer \citep[P. 231]{monteith_principles_2013}, but $r_a$ in Eq. {eq_Ew_PM1} refers to total leaf boundary layer resistance for sensible heat flux, which, for a planar leaf, is half the one-sided value. This inconsistency will be further discussed in Section {sec_PM-incons}.
389
#
390
# The molar mass of air is $M_a = \rho_a V_a/n_a$, while according to the ideal gas law, $V_a/n_a = R_{mol} T_a/P_a$, which yields for $\epsilon = M_w/M_a$:
391
# ##### {eq_epsilon}
392
# $$\epsilon = \frac{M_w P_a}{R_{mol} T_a \rho_a}$$
393
#
394
# Inserting Eqs. {eq_rhoa_Pwa_Ta}, {eq_PN2} and {eq_PO2} in the above, $T_a$ cancels out, and at standard atmospheric pressure of 101325 Pa, we obtain values for $\epsilon$ between 0.624 and 0.631 for vapour pressure ranging from 0 to 3000 Pa, compared to the value of 0.622 mentioned by \citet{monteith_principles_2013}.
395
396
# In[35]:
397
398
eq_fu_ra_M = f_u == rho_a*c_pa/(gamma_v*r_a)
399
units_check(eq_fu_ra_M)
400
401
402
# In[36]:
403
404
eq_Ew_PM1 = eq_Ew_P.subs(eq_fu_ra_M)
405
units_check(eq_Ew_PM1)
406
407
408
# In[37]:
409
410
eq_gammavs_M65 = gamma_v == gamma_v*(1 + r_s/r_a)
411
units_check(eq_gammavs_M65)
412
413
414
# In[38]:
415
416
eq_El_PM2 = eq_Ew_PM1.subs(eq_gammavs_M65)(E_w = E_l)
417
units_check(eq_El_PM2)
418
419
420
# In[39]:
421
422
eq_gammavs_MU = gamma_v == n_MU*gamma_v*(1 + r_s/r_a)
423
units_check(eq_gammavs_MU)
424
425
426
# In[40]:
427
428
eq_El_MU2 = eq_Ew_PM1.subs(eq_gammavs_MU)(E_w = E_l)
429
units_check(eq_El_MU2)
430
431
432
# In[41]:
433
434
eq_gammav_MU = gamma_v == c_pa*P_a/(lambda_E*epsilon)
435
units_check(eq_gammav_MU)
436
437
438
# In[42]:
439
440
# Molar mass of air is M_a = rho_a*V_a/n_a, while V_a/n_a = R_mol*T_a/P_a, according to the ideal gas law
441
eq_epsilon = epsilon == M_w/(rho_a*R_mol*T_a/P_a)
442
units_check(eq_epsilon)
443
444
445
# In[43]:
446
447
eq_epsilon.subs(eq_rhoa).show()
448
P = plot(eq_epsilon.rhs().subs(eq_rhoa).subs(cdict)(P_a = 101325), (P_wa, 0, 3000))
449
P.axes_labels(['$P_{wa}$ (Pa)', '$\epsilon$'])
450
P
451
452
453
# ### Relationships between resistances and conductances
454
# As opposed to the formulations in Section {sec:enbal}, where sensible and latent heat transfer coefficients ($h_c$ and $g_{tw}$ respectively) translate leaf-air differences in temperature or vapour concentration to fluxes, resistances in the PM equation are defined in the context of \citep[Eqs. 13.16 and 13.20]{monteith_principles_2013}:
455
# ##### {eq_El_MU}
456
# \begin{equation}
457
# E_l = \frac{a_s \lambda_E\rho_a\epsilon}{P_a (r_v + r_s)} (P_{wl} - P_{wa})
458
# \end{equation}
459
# and
460
# ##### {eq_Hl_MU}
461
# \begin{equation}
462
# H_l = \frac{a_{sh} \rho_a c_{pa}}{r_a}(T_l - T_a),
463
# \end{equation}
464
# where $r_v$ and $r_s$ are the one-sided leaf boundary layer and stomatal resistances to water vapour respectively, and $r_a$ is the one-sided leaf boundary layer resistance to sensible heat transfer. Note that the introduction of $a_s$, $a_{sh}$ and $r_s$ in Eqs. {eq_El_MU} and {eq_Hl_MU} is based on the description on P. 231 in \citet{monteith_principles_2013}, where the authors also assumed that $r_v \approx r_a$.
465
#
466
# Comparison of Eq. {eq_El_MU} with Eq. {eq_Elmol} (after substitution of Eqs. {eq_Cwl} and {eq_Cwa} and insertion into Eq. {eq_El}), assuming isothermal conditions ($T_l = T_a$) and substituting Eq. {eq_epsilon} reveals that
467
# ##### {eq_rv_gbw}
468
# \begin{equation}
469
# r_v = a_s/g_{bw},
470
# \end{equation}
471
# while comparison of Eq. {eq_Hl_MU} with Eq. {eq_Hl} reveals that
472
# ##### {eq_ra_hc}
473
# \begin{equation}
474
# r_a = \frac{\rho_a c_{pa}}{h_c}.
475
# \end{equation}
476
477
# In[44]:
478
479
# According to Eq. 13.20 in Monteith_principles_2013, rho_a*c_pa/r_H = h_c, while he states below Eq. 13.32 that r_H = r_v approximately. This would imply that g_bw = 1/r_w = h_c/(rho_a*c_pa). Is this true?
480
eq_Hl.show()
481
vdict[h_c] = h_c
482
(eq_gbw_hc/(rho_a*c_pa)).subs(eq_rhoa_Pwa_Ta, eq_Le).subs(eq_alphaa, eq_Dva,eq_PN2, eq_PO2).subs(vdict)
483
# However, note that r_v is used in Eq. 13.16 on the vapour pressure gradient, not on the concentration gradient as g_bw! He also uses E_l == lambda_E*rho_a*epsilon/P_a*(P_wl - P_wa)/r_v, when formulating the equation for a wet surface evaporating on one side only.
484
eq_Cwl
485
486
487
# In[45]:
488
489
eq_El_MU = E_l == a_s*lambda_E*rho_a*epsilon/(P_a*(r_v + r_s)) * (P_wl - P_wa)
490
print units_check(eq_El_MU)
491
eq_Hl_MU = H_l == a_sh*rho_a*c_pa/r_a*(T_l - T_a)
492
units_check(eq_Hl_MU)
493
494
495
# In[46]:
496
497
eq_El.subs(eq_Elmol).subs(eq_Cwl, eq_Cwa).show()
498
499
500
# In[47]:
501
502
soln = solve([eq_El_MU(r_s = 0), eq_El.subs(eq_Elmol).subs(eq_Cwl, eq_Cwa)], r_v, E_l)
503
eq_rv_gbw = soln[0][0](T_l = T_a, g_tw = g_bw).subs(eq_epsilon).simplify_full()
504
units_check(eq_rv_gbw)
505
506
507
# <p><span style="color: #ff0000;">Note that according to eq_El_MU, $r_v$ is one-sided resistance, while according to eq_Elmol, $g_{bw}$ is total conductance. Therefore, for hypostomatous leaves, they are both one-sided, whereas for amphistomatous leaves, the one -sided resistance is twice $1/g_{bw}$.</span></p>
508
509
# In[48]:
510
511
eq_El.subs(eq_Elmol).subs(eq_Cwl, eq_Cwa).show()
512
eq_El_MU.subs(eq_epsilon).show()
513
514
515
# In[49]:
516
517
soln = solve([eq_El_MU(r_v = 0), eq_El.subs(eq_Elmol).subs(eq_Cwl, eq_Cwa)], r_s, E_l)
518
eq_rs_gsw = soln[0][0](T_l = T_a, g_tw = g_sw).subs(eq_epsilon).simplify_full()
519
units_check(eq_rs_gsw)
520
521
522
# In[50]:
523
524
soln = solve([eq_Hl_MU, eq_Hl], r_a, H_l)
525
eq_ra_hc = soln[0][0]
526
units_check(eq_ra_hc)
527
528
529
# ## Generalisation of Penman's analytical approach
530
# The key point of Penman's analytical solution is to formulate $E_l$ as a function of ($P_{wl} - P_{wa}$) and $H_l$ as a function of ($T_l - T_a$). We will do this by introducing general transfer coefficients for latent heat ($c_E$, W~m$^{-2}$~Pa$^{1}$) and sensible heat ($c_H$, W~m$^{-2}$~K$^{1}$):
531
# ##### {eq_El_cE}
532
# \begin{equation}
533
# E_l = c_E (P_{wl} - P_{wa})
534
# \end{equation}
535
# ##### {eq_Hl_cH}
536
# \begin{equation}
537
# H_l = c_H (T_l - T_a)
538
# \end{equation}
539
# We now define the psychrometric constant as
540
# ##### {eq_gammav_cE}
541
# \begin{equation}
542
# \gamma_v = c_H/c_E
543
# \end{equation}
544
# and introduce it into Eq. {eq_Hl_cH} to obtain:
545
# ##### {eq_Hl_gammav}
546
# \begin{equation}
547
# H_l = \gamma_v c_E (T_l - T_a)
548
# \end{equation}
549
# Introduction of the Penman assumption (Eq. {eq_Penman_ass}) allows elimination of leaf temperature:
550
# ##### {eq_Hl_Pwl}
551
# \begin{equation}
552
# H_l = \frac{c_E \gamma_v (P_{wl} - P_{was})}{\Delta_{eTa}}
553
# \end{equation}
554
# Eqs. {eq_El_cE}, {eq_Hl_Pwl} and the leaf energy balance equation (Eq. {eq_Rs_enbal}), form a system of three equations that can be solved for $E_l$, $H_l$ and $P_{wl}$ to yield:
555
# ##### {eq_El_Delta}
556
# \begin{equation}
557
# E_{l} = \frac{\Delta_{eTa} c_E
558
# {\left({R_{s}} - R_{ll}\right) + c_E c_{H} \left({P_{was}} - {P_{wa}}\right) }
559
# }
560
# {\Delta_{eTa} c_E + c_H}
561
# \end{equation}
562
# and
563
# ##### {eq_Hl_Delta}
564
# \begin{equation}
565
# H_{l} = \frac{
566
# c_H \left(R_s - R_{ll} \right) + c_E c_H \left(P_{wa} - P_{was}\right)
567
# }
568
# {\Delta_{eTa} c_E + c_H}
569
# \end{equation}
570
# In the above, we already substituted Eq. {eq_gammav_cE} to avoid confusion about the meaning of $\gamma_v$, which is often referred to as the psychrometric constant, but in this case, it would strongly depend on stomatal resistance and hence should not be referred to as a constant.
571
#
572
# Eqs. {eq_Hl_Delta} and {eq_Hl_cH} can now be used to get an analytical solution for leaf temperature ($T_l$):
573
# ##### {eq_Tl_Delta}
574
# \begin{equation}
575
# T_{l} = T_a + \frac{
576
# (R_s - R_{ll}) + c_{E} ({P_{wa}} - P_{was})
577
# }
578
# {\Delta_{eTa} c_E + c_H}
579
# \end{equation}
580
# Instead of using Eqs. {eq_Hl_Delta} and {eq_El_Delta} directly, one might obtain alternative analytic solutions for $H_l$ and $E_l$ by inserting Eq. {eq_Tl_Delta} into Eq. {eq_Hl_cH} or into Eq. {eq_Pwl} and the latter into the aerdynamic formulation given in Eq. {eq_El_cE}.
581
#
582
# In the original formulations by Penman and Monteith, the term $R_s - R_{ll}$ is referred to as net available energy and for a ground surface it is represented by net radiation minus ground heat flux ($R_N - G$). For a leaf, there is no ground heat flux, and $R_N = R_s - R_{ll}$. In most applications of the analytical solutions, $R_{ll}$ is not explicitly calculated, but it is assumed that $R_N$ is known, neglecting the dependence of $R_{ll}$ on the leaf temperature. Use of Eq. {eq_Tl_Delta} to estimate steady-state leaf temperature and subsequent calculation of $H_l$ and $E_l$ as outlined above, has the advantage that missing information on $R_{ll}$ would not directly affect calculation of $H_l$ and $E_l$, but only through its effect on leaf temperature. In fact, using $T_l$ obtained from Eq. {eq_Tl_Delta} by assuming that $R_{ll} = 0$ would then enable approximate estimation of the true $R_{ll}$ by inserting $T_l$ into Eq. {eq_Rll}.
583
584
# In[51]:
585
586
var2('c_E', 'Latent heat transfer coefficient', joule/second/meter^2/pascal)
587
var2('c_H', 'Sensible heat transfer coefficient', joule/second/meter^2/kelvin)
588
589
590
# In[52]:
591
592
eq_El_cE = E_l == c_E*(P_wl - P_wa)
593
print units_check(eq_El_cE)
594
eq_Hl_cH = H_l == c_H*(T_l - T_a)
595
units_check(eq_Hl_cH)
596
597
598
# In[53]:
599
600
# Introducing gamma_v = c_H/c_E into H_l
601
eq_gammav_cE = gamma_v == c_H/c_E
602
eq_Hl_gammav = H_l == c_E*gamma_v*(T_l - T_a)
603
units_check(eq_Hl_gammav)
604
605
606
# In[54]:
607
608
# Introducing the Penman-assumption to eliminate T_l
609
eq_Penman_ass.show()
610
soln = solve([eq_Hl_gammav, eq_Penman_ass], H_l, T_l)
611
#for eq in flatten(soln):
612
# eq.show()
613
eq_Hl_Pwl = soln[0][0]
614
print units_check(eq_Hl_Pwl)
615
616
617
# In[55]:
618
619
# Using energy balance to eliminate P_wl
620
soln = solve([eq_Hl_Pwl,eq_El_cE, eq_Rs_enbal], E_l, H_l, P_wl)
621
[eq_El_Delta, eq_Hl_Delta, eq_Pwl_Delta] = [eq1.subs(eq_gammav_cE).simplify_full() for eq1 in flatten(soln)]
622
for eq1 in [eq_El_Delta, eq_Hl_Delta, eq_Pwl_Delta]:
623
print units_check(eq1)
624
625
626
# In[56]:
627
628
# Solving for T_l
629
eq_Tl_Delta = solve(eq_Hl_Delta.rhs() == eq_Hl_cH.rhs(), T_l)[0].expand().factor()
630
print units_check(eq_Tl_Delta)
631
632
633
# In[57]:
634
635
eq_Tl_Delta.expand().simplify_full().show()
636
637
638
# In[58]:
639
640
# Test if formulation in paper is the same
641
eq_Tl_Delta1 = T_l == T_a + ((R_s - R_ll) + c_E*(P_wa - P_was))/(Delta_eTa*c_E + c_H)
642
eq_Tl_Delta1.show()
643
(eq_Tl_Delta.rhs() - eq_Tl_Delta1.rhs()).full_simplify()
644
645
646
# In[59]:
647
648
# Alternative approach to get T_l
649
eq_Pwl.show()
650
soln = solve(eq_Pwl_Delta.rhs() == eq_Pwl.rhs(), T_l)
651
eq_Tl_Delta2 = soln[0].simplify_full()
652
eq_Tl_Delta2.show()
653
654
655
# In[60]:
656
657
eq_El.subs(eq_Elmol_conv)
658
659
660
# In[61]:
661
662
eq_Hl
663
664
665
# In[62]:
666
667
eqEl = eq_El.subs(eq_Elmol_conv)
668
eqHl = eq_Hl
669
eq_ce_conv = solve([eqEl, eq_El_cE], c_E, E_l)[0][0]
670
print units_check(eq_ce_conv)
671
eq_ch_hc = solve([eqHl, eq_Hl_cH], c_H, H_l)[0][0]
672
units_check(eq_ch_hc)
673
674
675
# In[63]:
676
677
eq_Hl_Delta.subs(eq_ce_conv, eq_ch_hc).simplify_full().show()
678
eq_El_Delta.subs(eq_ce_conv, eq_ch_hc).simplify_full().show()
679
eq_Tl_Delta.subs(eq_ce_conv, eq_ch_hc).simplify_full().show()
680
681
682
# ## Comparison with explicit leaf energy balance model
683
# To test the above equations, we will load fun_SS from leaf_enbalance_eqs, using the 'jupyter line magic', i.e. executing the line starting with %load in the below field.
684
# After execution, the code of the imported fun_SS will be displayed and the original command will be commented out. To update, need to uncomment the top row and re-executed the cell.
685
686
# In[64]:
687
688
# %load -s fun_SS 'temp/leaf_enbalance_eqs.sage'
689
def fun_SS(vdict1):
690
'''
691
Steady-state T_l, R_ll, H_l and E_l under forced conditions.
692
Parameters are given in a dictionary (vdict) with the following entries:
693
a_s, a_sh, L_l, P_a, P_wa, R_s, Re_c, T_a, g_sw, v_w
694
'''
695
vdict = vdict1.copy()
696
697
# Nusselt number
698
vdict[nu_a] = eq_nua.rhs().subs(vdict)
699
vdict[Re] = eq_Re.rhs().subs(vdict)
700
vdict[Nu] = eq_Nu_forced_all.rhs().subs(vdict)
701
702
# h_c
703
vdict[k_a] = eq_ka.rhs().subs(vdict)
704
vdict[h_c] = eq_hc.rhs().subs(vdict)
705
706
# gbw
707
vdict[D_va] = eq_Dva.rhs().subs(vdict)
708
vdict[alpha_a] = eq_alphaa.rhs().subs(vdict)
709
vdict[rho_a] = eq_rhoa.rhs().subs(vdict)
710
vdict[Le] = eq_Le.rhs().subs(vdict)
711
vdict[g_bw] = eq_gbw_hc.rhs().subs(vdict)
712
713
# Hl, Rll
714
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
715
vdict[H_l] = eq_Hl.rhs().subs(vdict)
716
717
# El
718
vdict[g_tw] = eq_gtw.rhs().subs(vdict)
719
vdict[C_wa] = eq_Cwl.rhs()(P_wl = P_wa, T_l = T_a).subs(vdict)
720
vdict[P_wl] = eq_Pwl.rhs().subs(vdict)
721
vdict[C_wl] = eq_Cwl.rhs().subs(vdict)
722
vdict[E_lmol] = eq_Elmol.rhs().subs(vdict)
723
vdict[E_l] = eq_El.rhs().subs(eq_Elmol).subs(vdict)
724
725
# Tl
726
try:
727
vdict[T_l] = find_root((eq_Rs_enbal - R_s).rhs().subs(vdict), 273, 373)
728
except:
729
print 'too many unknowns for finding T_l: ' + str((eq_Rs_enbal - R_s).rhs().subs(vdict).args())
730
731
# Re-inserting T_l
732
Tlss = vdict[T_l]
733
for name1 in [C_wl, P_wl, R_ll, H_l, E_l, E_lmol]:
734
vdict[name1] = vdict[name1].subs(T_l = Tlss)
735
736
# Test for steady state
737
if n((E_l + H_l + R_ll - R_s).subs(vdict))>1.:
738
return 'error in energy balance: El + Hl + Rll - R_s = ' + str(n((E_l + H_l + R_ll - R_s).subs(vdict)))
739
return vdict
740
741
742
# In[27]:
743
744
# Test
745
746
747
# In[65]:
748
749
# Test
750
vdict = cdict.copy()
751
#vdict= {}
752
vdict[a_s] = 1.0 # one sided stomata
753
vdict[g_sw] = 0.01
754
vdict[T_a] = 273 + 25.5
755
vdict[T_w] = vdict[T_a] # Wall temperature equal to air temperature
756
vdict[P_a] = 101325
757
rha = 1
758
vdict[P_wa] = rha*eq_Pwl.rhs()(T_l = T_a).subs(vdict)
759
vdict[L_l] = 0.03
760
vdict[Re_c] = 3000
761
vdict[R_s] = 600
762
vdict[v_w] = 1
763
str1 = ''
764
for key1 in sorted(vdict.keys()):
765
str1 = str1+'$'+ latex(key1)+'$ '
766
print str1
767
#vdict = dict(vdict.items()+cdict.items())
768
str1 = ''
769
for key1 in sorted(vdict.keys()):
770
str1 = str1+'$'+ latex(key1)+'$ '
771
print str1
772
resdict = fun_SS(vdict)
773
for name1 in [T_l, E_l, H_l, R_ll]:
774
print str(name1)+' = ' + str(resdict[name1])
775
vdict[P_was] = eq_Pwl.rhs()(T_l = T_a).subs(vdict)
776
vdict[Delta_eTa] = eq_Deltaeta_T.rhs().subs(vdict)
777
vdict[k_a] = eq_ka.rhs().subs(vdict)
778
vdict[nu_a] = eq_nua.rhs().subs(vdict)
779
vdict[Re] = eq_Re.rhs().subs(vdict)
780
vdict[Nu] = eq_Nu_forced_all.rhs().subs(vdict)
781
vdict[h_c] = eq_hc.rhs().subs(vdict)
782
783
vdict[P_N2] = eq_PN2.rhs().subs(vdict)
784
vdict[P_O2] = eq_PO2.rhs().subs(vdict)
785
vdict[alpha_a] = eq_alphaa.rhs().subs(vdict)
786
vdict[k_a] = eq_ka.rhs().subs(vdict)
787
vdict[D_va] = eq_Dva.rhs().subs(vdict)
788
vdict[Le] = eq_Le.rhs().subs(vdict)
789
vdict[rho_a] = eq_rhoa_Pwa_Ta.rhs().subs(vdict)
790
vdict[g_bw] = eq_gbw_hc.rhs().subs(vdict)
791
vdict[g_tw] = eq_gtw.rhs().subs(vdict)
792
vdict[g_twmol] = eq_gtwmol_gtw_iso.rhs().subs(vdict)
793
794
vdict[R_ll] = 0
795
print 'Direct estimates: '
796
print eq_El_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
797
print eq_Hl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
798
print eq_Tl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
799
print eq_Pwl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
800
801
print 'Using estimated T_l: '
802
vdict[T_l] = eq_Tl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
803
vdict[P_wl] = eq_Pwl.rhs().subs(vdict)
804
print vdict[P_wl]
805
print eq_El.subs(eq_Elmol_conv).subs(vdict)
806
#vdict[C_wa] = eq_Cwa.rhs().subs(vdict)
807
#vdict[C_wl] = eq_Cwl.rhs().subs(vdict)
808
#print eq_El.subs(eq_Elmol).subs(vdict)
809
print eq_Hl.subs(vdict)
810
print eq_Rll.subs(vdict)
811
812
print 'Using estimated T_l only to calculate R_ll: '
813
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
814
print eq_El_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
815
print eq_Hl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
816
print eq_Tl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
817
818
print 'Using 1 iteration to get T_l: '
819
vdict[R_ll] = 0
820
vdict[T_l] = eq_Tl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
821
print 'T_l(R_ll=0): ' + str(vdict[T_l])
822
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
823
print 'R_ll(T_l) = ' + str(vdict[R_ll])
824
vdict[T_l] = eq_Tl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
825
vdict[P_wl] = eq_Pwl.rhs().subs(vdict)
826
print 'T_l = ' + str(vdict[T_l])
827
print eq_El.subs(eq_Elmol_conv).subs(vdict)
828
print eq_Hl.subs(vdict)
829
830
831
# In[66]:
832
833
# Isothermal conversion between gtw and gtwmol leads to quite a bit of error!
834
print eq_El.subs(eq_Elmol_conv).subs(eq_gtwmol_gtw_iso).subs(resdict)
835
print eq_El.subs(eq_Elmol_conv).subs(eq_gtwmol_gtw).subs(resdict)
836
837
838
# <p><span style="color: #ff0000;">The MU-equation can easily be corrected to be consistent with the general solution in eq_El_Delta!<br /></span></p>
839
840
# In[67]:
841
842
eq_gtwmol_gtw.rhs()
843
844
845
# In[68]:
846
847
vdict[P_wl]
848
849
850
# In[69]:
851
852
# Test
853
vdict = cdict.copy()
854
#vdict= {}
855
vdict[a_s] = 1.0 # one sided stomata
856
vdict[g_sw] = 0.01
857
vdict[T_a] = 273 + 25.5
858
vdict[T_w] = vdict[T_a] # Wall temperature equal to air temperature
859
vdict[P_a] = 101325
860
rha = 1
861
vdict[P_wa] = rha*eq_Pwl.rhs()(T_l = T_a).subs(vdict)
862
vdict[L_l] = 0.03
863
vdict[Re_c] = 3000
864
vdict[R_s] = 600
865
vdict[v_w] = 1
866
867
#vdict = dict(vdict.items()+cdict.items())
868
869
resdict = fun_SS(vdict)
870
for name1 in [T_l, E_l, H_l, R_ll]:
871
print str(name1)+' = ' + str(resdict[name1])
872
vdict[P_was] = eq_Pwl.rhs()(T_l = T_a).subs(vdict)
873
vdict[Delta_eTa] = eq_Deltaeta_T.rhs().subs(vdict)
874
vdict[k_a] = eq_ka.rhs().subs(vdict)
875
vdict[nu_a] = eq_nua.rhs().subs(vdict)
876
vdict[Re] = eq_Re.rhs().subs(vdict)
877
vdict[Nu] = eq_Nu_forced_all.rhs().subs(vdict)
878
vdict[h_c] = eq_hc.rhs().subs(vdict)
879
880
vdict[P_N2] = eq_PN2.rhs().subs(vdict)
881
vdict[P_O2] = eq_PO2.rhs().subs(vdict)
882
vdict[alpha_a] = eq_alphaa.rhs().subs(vdict)
883
vdict[k_a] = eq_ka.rhs().subs(vdict)
884
vdict[D_va] = eq_Dva.rhs().subs(vdict)
885
vdict[Le] = eq_Le.rhs().subs(vdict)
886
vdict[rho_a] = eq_rhoa_Pwa_Ta.rhs().subs(vdict)
887
vdict[g_bw] = eq_gbw_hc.rhs().subs(vdict)
888
vdict[g_tw] = eq_gtw.rhs().subs(vdict)
889
vdict[g_twmol] = eq_gtwmol_gtw_iso.rhs().subs(vdict)
890
891
892
vdict[R_ll] = 0
893
print 'Direct estimates: '
894
print eq_El_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
895
print eq_Hl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
896
print eq_Tl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
897
898
print 'Using estimated T_l: '
899
vdict[T_l] = eq_Tl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
900
vdict[P_wl] = eq_Pwl.rhs().subs(vdict)
901
vdict[g_twmol] = eq_gtwmol_gtw.rhs().subs(vdict)
902
print eq_El.subs(eq_Elmol_conv).subs(vdict)
903
print eq_Hl.subs(vdict)
904
print eq_Rll.subs(vdict)
905
906
print 'Using estimated T_l only to calculate R_ll: '
907
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
908
print eq_El_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
909
print eq_Hl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
910
print eq_Tl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
911
912
print 'Using 1 iteration to get T_l: '
913
vdict[R_ll] = 0
914
vdict[T_l] = eq_Tl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
915
print 'T_l(R_ll=0): ' + str(vdict[T_l])
916
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
917
print 'R_ll(T_l) = ' + str(vdict[R_ll])
918
vdict[T_l] = eq_Tl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
919
vdict[P_wl] = eq_Pwl.rhs().subs(vdict)
920
print 'T_l = ' + str(vdict[T_l])
921
vdict[g_twmol] = eq_gtwmol_gtw.rhs().subs(vdict)
922
print eq_El.subs(eq_Elmol_conv).subs(vdict)
923
print eq_Hl.subs(vdict)
924
925
926
# In[70]:
927
928
# Alternative approach, keeping T_l, but eliminateing P_wl
929
eq_El_cE.show()
930
eq_Hl_cH.show()
931
eq_gammav_cE.show()
932
eq_Penman_ass.show()
933
934
# Eliminating c_E
935
eq_El_gammav = solve([eq_El_cE, eq_gammav_cE], E_l, c_E)[0][0]
936
print units_check(eq_El_gammav)
937
938
# Eliminating P_wl
939
eq_El_Tl = solve([eq_El_gammav, eq_Penman_ass], E_l, P_wl)[0][0]
940
print units_check(eq_El_Tl)
941
942
# Solving for E_l, H_l and T_l
943
soln = solve([eq_El_Tl, eq_Hl_cH, eq_Rs_enbal], E_l, H_l, T_l)
944
[eq_El_Delta_a, eq_Hl_Delta_a, eq_Tl_Delta_a] = [eq1.subs(eq_gammav_cE).simplify_full() for eq1 in flatten(soln)]
945
for eq1 in [eq_El_Delta_a, eq_Hl_Delta_a, eq_Tl_Delta_a]:
946
print units_check(eq1)
947
print latex(eq1)
948
949
950
# In[71]:
951
952
# These solutions are identical to the previous ones
953
print (eq_El_Delta - eq_El_Delta_a).simplify_full()
954
print (eq_Hl_Delta - eq_Hl_Delta_a).simplify_full()
955
print (eq_Tl_Delta_a - eq_Tl_Delta1).simplify_full()
956
957
958
# In[72]:
959
960
# More direct approach, not using gamma_v at all
961
soln = solve([eq_Hl_cH, eq_Penman_ass, eq_El_cE, eq_Rs_enbal], E_l, H_l, P_wl, T_l)
962
print soln
963
[eq_El_Delta_b, eq_Hl_Delta_b, eq_Pwl_Delta_b, eq_Tl_Delta_b] = [eq1 for eq1 in flatten(soln)]
964
for eq1 in [eq_El_Delta_b, eq_Hl_Delta_b, eq_Pwl_Delta_b, eq_Tl_Delta_b]:
965
print units_check(eq1)
966
print latex(eq1)
967
print (eq_El_Delta - eq_El_Delta_b).simplify_full()
968
print (eq_Hl_Delta - eq_Hl_Delta_b).simplify_full()
969
print (eq_Tl_Delta_a - eq_Tl_Delta_b).simplify_full()
970
971
972
# In[73]:
973
974
soln = solve([eq_Hl_cH, eq_Penman_ass, eq_El_cE, eq_Rs_enbal], E_l, H_l, P_wl, T_l)
975
print soln
976
for eq1 in soln[0]:
977
eq1.show()
978
979
980
# In[74]:
981
982
eq_El_PM2.show()
983
eq_ra_hc.show()
984
eq_gammav_MU.show()
985
eq_epsilon.show()
986
987
988
# In[75]:
989
990
eq_El_MU.show()
991
eq_El_MU2.show()
992
993
994
# In[76]:
995
996
eq_Hl_P52.args()
997
998
999
# In[77]:
1000
1001
eq_Tl_P52.args()
1002
1003
1004
# In[78]:
1005
1006
# Fig. 8 in Ball et al. 1988
1007
vdict = cdict.copy()
1008
vdict[a_s] = 1
1009
vdict[L_l] = 0.07
1010
vdict[P_a] = 101325
1011
vdict[P_wa] = 20/1000*101325
1012
vdict[R_s] = 400
1013
vdict[Re_c] = 3000
1014
vdict[T_a] = 273+30
1015
vdict[T_w] = vdict[T_a]
1016
vdict[g_sw] = 0.15/40
1017
vdict[v_w] = 1.
1018
print 'numerical solution: '
1019
resdict = fun_SS(vdict)
1020
for name1 in [T_l, E_l, H_l, R_ll, g_bw, g_tw]:
1021
print str(name1)+' = ' + str(resdict[name1])
1022
1023
vdict[P_was] = eq_Pwl.rhs()(T_l = T_a).subs(vdict)
1024
vdict[Delta_eTa] = eq_Deltaeta_T.rhs().subs(vdict)
1025
vdict[k_a] = eq_ka.rhs().subs(vdict)
1026
vdict[nu_a] = eq_nua.rhs().subs(vdict)
1027
vdict[Re] = eq_Re.rhs().subs(vdict)
1028
vdict[Nu] = eq_Nu_forced_all.rhs().subs(vdict)
1029
vdict[h_c] = eq_hc.rhs().subs(vdict)
1030
1031
vdict[P_N2] = eq_PN2.rhs().subs(vdict)
1032
vdict[P_O2] = eq_PO2.rhs().subs(vdict)
1033
vdict[alpha_a] = eq_alphaa.rhs().subs(vdict)
1034
vdict[k_a] = eq_ka.rhs().subs(vdict)
1035
vdict[D_va] = eq_Dva.rhs().subs(vdict)
1036
vdict[Le] = eq_Le.rhs().subs(vdict)
1037
vdict[rho_a] = eq_rhoa_Pwa_Ta.rhs().subs(vdict)
1038
vdict[g_bw] = eq_gbw_hc.rhs().subs(vdict)
1039
vdict[g_tw] = eq_gtw.rhs().subs(vdict)
1040
vdict[g_twmol] = eq_gtwmol_gtw_iso.rhs().subs(vdict)
1041
1042
vdict[R_ll] = 0
1043
print 'Direct estimates: '
1044
namesdict = [E_l, H_l]
1045
vdict[E_l] = eq_El_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1046
vdict[H_l] = eq_Hl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1047
for name1 in namesdict:
1048
print str(name1)+' = ' + str(vdict[name1])
1049
1050
print eq_Tl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1051
print eq_Tl_Delta1.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1052
print eq_Tl_Delta2.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1053
print eq_Rs_enbal.subs(vdict)
1054
1055
1056
print 'Using T_l from eq_Tl_Delta: '
1057
namesdict = [T_l, P_wl, E_l, H_l, R_ll]
1058
vdict[T_l] = eq_Tl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1059
vdict[P_wl] = eq_Pwl.rhs().subs(vdict)
1060
vdict[E_l] = eq_El.rhs().subs(eq_Elmol_conv).subs(vdict)
1061
vdict[H_l] = eq_Hl.rhs().subs(vdict)
1062
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
1063
for name1 in namesdict:
1064
print str(name1)+' = ' + str(vdict[name1])
1065
print eq_Rs_enbal.subs(vdict)
1066
1067
1068
print 'Using T_l from eq_Tl_Delta only to calculate R_ll: '
1069
namesdict = [T_l, R_ll, E_l, H_l]
1070
vdict[R_ll] = 0
1071
vdict[T_l] = eq_Tl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1072
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
1073
vdict[E_l] = eq_El_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1074
vdict[H_l] = eq_Hl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1075
1076
for name1 in namesdict:
1077
print str(name1)+' = ' + str(vdict[name1])
1078
print eq_Rs_enbal.subs(vdict)
1079
1080
1081
1082
print 'Using T_l from eq_Tl_Delta2: '
1083
namesdict = [T_l, P_wl, E_l, H_l, R_ll]
1084
vdict[R_ll] = 0
1085
vdict[T_l] = eq_Tl_Delta2.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1086
vdict[P_wl] = eq_Pwl.rhs().subs(vdict)
1087
vdict[E_l] = eq_El.rhs().subs(eq_Elmol_conv).subs(vdict)
1088
vdict[H_l] = eq_Hl.rhs().subs(vdict)
1089
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
1090
for name1 in namesdict:
1091
print str(name1)+' = ' + str(vdict[name1])
1092
print eq_Rs_enbal.subs(vdict)
1093
1094
print 'Using T_l from eq_Tl_Delta2 only to calculate R_ll: '
1095
namesdict = [T_l, R_ll, E_l, H_l]
1096
vdict[R_ll] = 0
1097
vdict[T_l] = eq_Tl_Delta2.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1098
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
1099
vdict[E_l] = eq_El_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1100
vdict[H_l] = eq_Hl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1101
1102
for name1 in namesdict:
1103
print str(name1)+' = ' + str(vdict[name1])
1104
print eq_Rs_enbal.subs(vdict)
1105
1106
1107
# <p><span style="color: #ff0000;">Why does eq_Tl_Delta2 give a different result than eq_Tl_Delta? eq_Tl_Delta gives the appropriate $T_l$ to reproduce $H_l$ estimated using eq_Hl_Delta, whereas eq_Tl_Delta2 gives the <span style="color: #ff0000;">appropriate $T_l$ to reproduce $E_l$ estimated using eq_El_Delta. Neither allows for energy balance closure, unless only used to compute $R_{ll}$, before using eq_El_Delta and eq_Hl_Delta to compute the other components.</span><br /></span></p>
1108
1109
# In[79]:
1110
1111
vdict[R_ll] = 0
1112
eq_El_P52.subs(eq_S_gbw_gsw, eq_fu_gbw, eq_gammav_as).subs(vdict)
1113
1114
1115
# In[80]:
1116
1117
# Test
1118
vdict = cdict.copy()
1119
#vdict= {}
1120
vdict[a_s] = 1.0 # one sided stomata
1121
vdict[g_sw] = 0.01
1122
vdict[T_a] = 273 + 25.5
1123
vdict[T_w] = vdict[T_a] # Wall temperature equal to air temperature
1124
vdict[P_a] = 101325
1125
rha = 1
1126
vdict[P_wa] = rha*eq_Pwl.rhs()(T_l = T_a).subs(vdict)
1127
vdict[L_l] = 0.03
1128
vdict[Re_c] = 3000
1129
vdict[R_s] = 600
1130
vdict[v_w] = 1
1131
1132
resdict = fun_SS(vdict)
1133
for name1 in [T_l, E_l, H_l, R_ll]:
1134
print str(name1)+' = ' + str(resdict[name1])
1135
vdict[P_was] = eq_Pwl.rhs()(T_l = T_a).subs(vdict)
1136
vdict[Delta_eTa] = eq_Deltaeta_T.rhs().subs(vdict)
1137
vdict[k_a] = eq_ka.rhs().subs(vdict)
1138
vdict[nu_a] = eq_nua.rhs().subs(vdict)
1139
vdict[Re] = eq_Re.rhs().subs(vdict)
1140
vdict[Nu] = eq_Nu_forced_all.rhs().subs(vdict)
1141
vdict[h_c] = eq_hc.rhs().subs(vdict)
1142
1143
vdict[P_N2] = eq_PN2.rhs().subs(vdict)
1144
vdict[P_O2] = eq_PO2.rhs().subs(vdict)
1145
vdict[alpha_a] = eq_alphaa.rhs().subs(vdict)
1146
vdict[k_a] = eq_ka.rhs().subs(vdict)
1147
vdict[D_va] = eq_Dva.rhs().subs(vdict)
1148
vdict[Le] = eq_Le.rhs().subs(vdict)
1149
vdict[rho_a] = eq_rhoa_Pwa_Ta.rhs().subs(vdict)
1150
vdict[g_bw] = eq_gbw_hc.rhs().subs(vdict)
1151
vdict[g_tw] = eq_gtw.rhs().subs(vdict)
1152
vdict[g_twmol] = eq_gtwmol_gtw_iso.rhs().subs(vdict)
1153
1154
vdict[R_ll] = 0
1155
print 'Direct estimates: '
1156
print eq_El_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1157
print eq_Hl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1158
print eq_Tl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1159
1160
print 'Using estimated T_l: '
1161
vdict[T_l] = eq_Tl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1162
vdict[P_wl] = eq_Pwl.rhs().subs(vdict)
1163
print eq_El.subs(eq_Elmol_conv).subs(vdict)
1164
print eq_Hl.subs(vdict)
1165
print eq_Rll.subs(vdict)
1166
1167
print 'Using estimated T_l only to calculate R_ll: '
1168
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
1169
print eq_El_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1170
print eq_Hl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1171
print eq_Tl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1172
1173
print 'Using 1 iteration to get T_l: '
1174
vdict[R_ll] = 0
1175
vdict[T_l] = eq_Tl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1176
print 'T_l(R_ll=0): ' + str(vdict[T_l])
1177
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
1178
print 'R_ll(T_l) = ' + str(vdict[R_ll])
1179
vdict[T_l] = eq_Tl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1180
vdict[P_wl] = eq_Pwl.rhs().subs(vdict)
1181
print 'T_l = ' + str(vdict[T_l])
1182
print eq_El.subs(eq_Elmol_conv).subs(vdict)
1183
print eq_Hl.subs(vdict)
1184
1185
1186
# ## Inconsistencies in the PM equations
1187
# From the general form (Eq. {eq_El_Delta}), we can recover most of the above analytical solutions by appropriate substitutions for $c_E$ and $c_H$, but closer inspection of the necessary substitutions reveals some inconsistencies.
1188
#
1189
# The Penman equation for a wet surface (Eq. {eq_Ew_P}) can be recovered by substituting $c_E = f_u$ and $c_H = \gamma_v f_u$ into (Eq. {eq_El_Delta}), while additional substitution of Eq. {eq_fu_ra_M} leads to recovery of Eq. {eq_Ew_PM1}, the Penman equation, as reformulated by \citet{monteith_evaporation_1965}. The formulation for leaf transpiration derived by \citet{penman_physical_1952} (Eq. {eq_El_P52}) is obtained by substituting $c_E = S f_u$ (deduced from Eq. {eq_El_fu_S}) and $c_E = \gamma_v f_u$ (from Eq. {eq_Hl_Tl_P52}). The substitutions are consistent with the formulations of latent and sensible heat flux given in Eqs. {eq_Hl_Tl_P52} and {eq_Ew_fu} or {eq_El_fu_S}, as long as $f_u$ and $r_a$ refer to the \emph{total resistances} of a leaf to latent and sensible heat flux respectively, as Eq. {eq_fu_ra_M} in conjunction with $c_H = \gamma_v f_u$ implies that:
1190
# ##### {eq_cH_ra}
1191
# \begin{equation}
1192
# c_H = (\rho_a c_{pa})/r_a
1193
# \end{equation}
1194
#
1195
#
1196
# Similarly, the Penman-Monteith equation (Eq. {eq_El_PM2} with $\gamma_v$ defined in Eq. {eq_gammav_MU}) could be recovered by substituting $c_E = \epsilon \lambda_E \rho_a/(P_a(r_s + r_v))$ and $c_H = c_{pa} \rho_a/r_a$, with subsequent substitution of $r_v = r_a$. Note however, that these substitutions are not consistent with Eqs. {eq_El_MU} and {eq_Hl_MU}, as the factors $a_s$ and $a_{sh}$ (referring to the number of leaf faces exchanging latent and sensible heat flux respectively) are missing. This is because the PM equation was derived with a soil surface in mind, which exchanges latent and sensible heat only on one side, and hence is not appropriate for a leaf. To alleviate this constraint, one could define $r_a$ and $r_s$ as total (two-sided) leaf resistances, but in this case, the simplification $r_v \approx r_a$ is not valid for hypostomatous leaves, as $r_a$ would then be only half of $r_v$. This is illustrated in Fig. {fig:leaf_BL-fluxes}, where sensible heat flux is released from both sides of the leaf, while latent heat flux is only released from the abaxial side, implying that $a_{sh}=2$ and $a_s=1$.
1197
1198
# In[81]:
1199
1200
# This allows to recovery of eq_Ew_P
1201
eq1 = eq_El_Delta.subs(c_E = f_u, c_H = gamma_v*f_u)
1202
eq1.simplify_full().show()
1203
eq_Ew_P.show()
1204
(eq_Ew_P.rhs() - eq1.rhs()).simplify_full()
1205
1206
1207
# In[ ]:
1208
1209
1210
1211
1212
# In[82]:
1213
1214
# This allows to recovery of eq_Ew_PM1
1215
eq1 = eq_El_Delta.subs(c_E = f_u, c_H = gamma_v*f_u).subs(eq_fu_ra_M)
1216
eq1.simplify_full().show()
1217
eq_Ew_PM1.show()
1218
(eq_Ew_PM1.rhs() - eq1.rhs()).simplify_full()
1219
1220
1221
# In[83]:
1222
1223
# This allows to recovery of eq_El_P52
1224
eq1 = eq_El_Delta.subs(c_E = f_u*S, c_H = gamma_v*f_u)
1225
eq1.simplify_full().show()
1226
eq_El_P52.show()
1227
(eq_El_P52.rhs() - eq1.rhs()).simplify_full()
1228
1229
1230
# In[84]:
1231
1232
eq_gammav_hc_fu
1233
1234
1235
# In[85]:
1236
1237
eq_El_P52.show()
1238
1239
1240
# In[86]:
1241
1242
eq_El_PM2.show()
1243
eq_El_MU.show()
1244
eq_Hl_MU.show()
1245
eq_gammav_MU.show()
1246
1247
1248
# In[87]:
1249
1250
# This leads to recovery of eq_El_PM2
1251
eq1 = eq_El_Delta(c_E = epsilon*lambda_E*rho_a/(P_a*(r_s + r_v)), c_H = c_pa*rho_a/r_a).subs(r_v = r_a).simplify_full()
1252
eq1.show()
1253
eq2 = eq_El_PM2.subs(eq_gammav_MU).simplify_full()
1254
eq2.show()
1255
(eq1 - eq2).simplify_full()
1256
1257
1258
# In[88]:
1259
1260
# Alternative recovery of eq_El_PM2, using gamma_v at the onset
1261
eq1 = eq_El_Delta(c_E = c_pa*rho_a/(gamma_v*(r_s + r_v)), c_H = c_pa*rho_a/r_a).subs(r_v = r_a).simplify_full()
1262
eq1.show()
1263
eq2 = eq_El_PM2.simplify_full()
1264
eq2.show()
1265
(eq1 - eq2).simplify_full()
1266
1267
1268
# \citet{monteith_principles_2013} acknowledged that a hypostomatous leaf could exchange sensible heat on two sides, but latent heat on one side only and introduced the parameter $n_{MU} = a_{sh}/a_s$ to account for this (Eq. {eq_El_MU2}). Using our general equation, it should be possible to reproduce the MU-Equation (Eq. {eq_El_MU2}) by substituting
1269
# $c_E = a_s \epsilon \lambda_E \rho_a/(P_a(r_s + r_v))$ (deduced from Eq. {eq_El_MU}) and $c_H = a_{sh} c_{pa} \rho_a/r_a$ (deduced from Eq. {eq_Hl_MU}) into Eq. {eq_El_Delta}. However, the result of this substitution, as presented in Eq. {eq_El_Delta_MUcorr}, is not the same as Eq. {eq_El_MU2} after substitution of Eqs. {eq_gammav_MU} and $n_{MU} = a_{sh}/a_s$, which would result in Eq. {eq_El_MU3}:
1270
# ##### {eq_El_Delta_MUcorr}
1271
# \begin{equation}
1272
# E_{l} = \frac{a_{s} \Delta_{eTa} \epsilon \lambda_{E} r_{a} \left(R_s - R_{ll}\right)
1273
# + a_{s} {a_{sh}} {c_{pa}} \epsilon
1274
# \lambda_{E} \rho_{a} \left({P_{was}} - {P_{wa}}\right)}
1275
# {P_{a} {a_{sh}} {c_{pa}} \left( r_{s} + r_a \right) + {\Delta_{eTa}} a_{s}
1276
# \epsilon \lambda_{E}}
1277
# \end{equation}
1278
# ##### {eq_El_MU3}
1279
# \begin{equation}
1280
# E_{l} = \frac{a_{s} \Delta_{eTa} \epsilon \lambda_{E} r_{a} \left(R_s - R_{ll}\right)
1281
# + a_{s} {c_{pa}} \epsilon
1282
# \lambda_{E} \rho_{a} \left({P_{was}} - {P_{wa}}\right)}
1283
# {P_{a} {a_{sh}} {c_{pa}} \left( r_{s} + r_a \right) + {\Delta_{eTa}} a_{s}
1284
# \epsilon \lambda_{E}}
1285
# \end{equation}
1286
# Note the missing $a_{sh}$ in the nominator of Eq. {eq_El_MU3}.
1287
# The reason is that \citet{monteith_principles_2013} introduced $n_{MU} = a_{sh}/a_s$ by modifying the meaning of $\gamma_v$ in Eq. {eq_Ew_PM1} and specifying that $r_a$, $r_v$ and $r_s$ respresent one-sided resitances. However, as explained above, $r_a$ in Eq. {eq_Ew_PM1} represents two-sided resistance to sensible heat flux (see Eq. {eq_cH_ra}). If we replace $r_a$ by $r_a = r_{a}/a_{sh} $ in Eq. {eq_Ew_PM1} before substitution of Eq. {eq_gammavs_MU}, we obtain a corrected MU-equation,
1288
# ##### {eq_El_MU_corr}
1289
# \begin{equation}
1290
# E_l = \frac{\Delta_{eTa}(R_s - R_{ll}) + \rho_a c_{pa} (P_{was} - P_{wa})a_{sh}/r_a}
1291
# {\Delta_{eTa} + \gamma_v a_{sh}/a_s \left(1 + \frac{r_{s}}{r_a}\right)},
1292
# \end{equation}
1293
# which, after substitution of Eq. {eq_gammav_MU}, results in Eq. {eq_El_Delta_MUcorr}.
1294
1295
# In[89]:
1296
1297
# This should lead to recovery of eq_El_MU2, but does not
1298
eq1 = eq_El_Delta(c_E = a_s*epsilon*lambda_E*rho_a/(P_a*(r_s + r_v)), c_H = a_sh*c_pa*rho_a/r_a).subs(r_v = r_a).simplify_full()
1299
print units_check(eq1)
1300
eq2 = eq_El_MU2.subs(eq_gammav_MU)(n_MU = a_sh/a_s).simplify_full()
1301
eq2.show()
1302
(eq1 - eq2).simplify_full()
1303
1304
1305
# In[90]:
1306
1307
eq_El_MU2.subs(eq_gammav_MU)(n_MU = a_sh/a_s).show()
1308
1309
1310
# In[91]:
1311
1312
eq_El_Delta(c_E = a_s*epsilon*lambda_E*rho_a/(P_a*(r_s + r_v)), c_H = a_sh*c_pa*rho_a/r_a).subs(r_v = r_a).show()
1313
1314
1315
# In[92]:
1316
1317
eq_Ew_PM1.show()
1318
1319
1320
# In[93]:
1321
1322
# if C_E and c_H are considered to be one-sided, it would not suffice to incorporate two-sidedness of one of them in gamma_v only, as c_E still features in soln[0][0]
1323
eq_gammav_cE.show()
1324
soln[0][0].show()
1325
soln[0][0].subs(eq_gammav_cE).show()
1326
1327
1328
# In[94]:
1329
1330
# If we replace r_a by r_a/a_sh in eq_Ew_PM1, and only then insert eq_gammavs_MU, we get the right solution
1331
eq_gammav_MU.show()
1332
eq1 = eq_El_Delta(c_E = a_s*epsilon*lambda_E*rho_a/(P_a*(r_s + r_v)), c_H = a_sh*c_pa*rho_a/r_a).subs(r_v = r_a).simplify_full()
1333
print units_check(eq1)
1334
eq_El_MU_corr = eq_Ew_PM1.subs(r_a = r_a/a_sh).subs(eq_gammavs_MU)(E_w = E_l).subs(eq_gammav_MU).subs(n_MU = a_sh/a_s).simplify_full()
1335
print units_check(eq_El_MU_corr)
1336
eq2 = eq_El_MU_corr
1337
1338
eq2.show()
1339
(eq1 - eq2).simplify_full()
1340
1341
1342
# <p><span style="color: #ff0000;">If we replace $r_a$ by $r_a/a_{sh}$ in eq_Ew_PM1, and only then insert eq_gammavs_MU, we get the right solution, equivalent to general equation with $c_E = a_s \epsilon \lambda_E \rho_a/(P_a (r_s + r_v))$ and $c_H = a_{sh} c_{pa} \rho_a/r_a)$, assuming  $r_v = r_a$<br /></span></p>
1343
1344
# In[95]:
1345
1346
eq_El_MU_corr_gammav = eq_Ew_PM1.subs(r_a = r_a/a_sh).subs(eq_gammavs_MU)(E_w = E_l).subs(n_MU = a_sh/a_s).simplify_full()
1347
units_check(eq_El_MU_corr_gammav)
1348
1349
1350
# In[96]:
1351
1352
eq_ra_hc.show()
1353
eq_rv_gbw.show()
1354
(eq_ra_hc/eq_rv_gbw).subs(eq_gbw_hc).show()
1355
plotfun = (eq_ra_hc/eq_rv_gbw).rhs().subs(eq_gbw_hc).subs(eq_Le).subs(eq_alphaa, eq_Dva)
1356
print plotfun(T_a = 300)
1357
P = plot(plotfun, (T_a, 280,310))
1358
P.axes_labels(['Air temperature (K)', '$r_a/r_v$'])
1359
P.show()
1360
1361
1362
# <p><span style="color: #ff0000;">$r_a/r_v$ is indeed  close to 1!</span></p>
1363
1364
# In[97]:
1365
1366
# Fig. 8 in Ball et al. 1988
1367
vdict = cdict.copy()
1368
vdict[a_s] = 1
1369
vdict[L_l] = 0.07
1370
vdict[P_a] = 101325
1371
vdict[P_wa] = 20/1000*101325
1372
vdict[R_s] = 400
1373
vdict[Re_c] = 3000
1374
vdict[T_a] = 273+30
1375
vdict[T_w] = vdict[T_a]
1376
vdict[g_sw] = 0.15/40
1377
#vdict[g_sv] = 1e-6
1378
1379
vdict[v_w] = 1.
1380
resdict = fun_SS(vdict)
1381
for name1 in [T_l, E_l, H_l, R_ll, g_bw, g_tw]:
1382
print str(name1)+' = ' + str(resdict[name1])
1383
1384
vdict[P_was] = eq_Pwl.rhs()(T_l = T_a).subs(vdict)
1385
vdict[Delta_eTa] = eq_Deltaeta_T.rhs().subs(vdict)
1386
vdict[k_a] = eq_ka.rhs().subs(vdict)
1387
vdict[nu_a] = eq_nua.rhs().subs(vdict)
1388
vdict[Re] = eq_Re.rhs().subs(vdict)
1389
vdict[Nu] = eq_Nu_forced_all.rhs().subs(vdict)
1390
vdict[h_c] = eq_hc.rhs().subs(vdict)
1391
1392
vdict[P_N2] = eq_PN2.rhs().subs(vdict)
1393
vdict[P_O2] = eq_PO2.rhs().subs(vdict)
1394
vdict[alpha_a] = eq_alphaa.rhs().subs(vdict)
1395
vdict[k_a] = eq_ka.rhs().subs(vdict)
1396
vdict[D_va] = eq_Dva.rhs().subs(vdict)
1397
vdict[Le] = eq_Le.rhs().subs(vdict)
1398
vdict[rho_a] = eq_rhoa_Pwa_Ta.rhs().subs(vdict)
1399
vdict[g_bw] = eq_gbw_hc.rhs().subs(vdict)
1400
vdict[g_tw] = eq_gtw.rhs().subs(vdict)
1401
vdict[g_twmol] = eq_gtwmol_gtw_iso.rhs().subs(vdict)
1402
1403
vdict[R_ll] = 0
1404
print 'Direct estimates: '
1405
namesdict = [E_l, H_l]
1406
vdict[E_l] = eq_El_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1407
vdict[H_l] = eq_Hl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1408
for name1 in namesdict:
1409
print str(name1)+' = ' + str(vdict[name1])
1410
1411
print eq_Tl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1412
print eq_Tl_Delta1.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1413
print eq_Tl_Delta2.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1414
print eq_Rs_enbal.subs(vdict)
1415
1416
print 'Penman-stomata: '
1417
namesdict = [E_l, H_l, T_l]
1418
vdict[S] = eq_S_gbw_gsw.rhs().subs(vdict)
1419
vdict[f_u] = eq_fu_gbw.rhs().subs(vdict)
1420
vdict[gamma_v] = eq_gammav_as.rhs().subs(vdict)
1421
vdict[E_l] = eq_El_P52.rhs().subs(vdict)
1422
vdict[H_l] = eq_Hl_P52.rhs().subs(vdict)
1423
vdict[T_l] = eq_Tl_P52.rhs().subs(vdict)
1424
for name1 in namesdict:
1425
print str(name1)+' = ' + str(vdict[name1])
1426
1427
print eq_Rs_enbal.subs(vdict)
1428
1429
print 'PM-equation: '
1430
namesdict = [E_l, H_l]
1431
vdict[r_s] = 1/vdict[g_sw]
1432
vdict[r_a] = eq_ra_hc.rhs().subs(vdict)
1433
vdict[gamma_v] = eq_gammav_MU.rhs().subs(vdict)
1434
vdict[epsilon] = eq_epsilon.rhs().subs(vdict)
1435
vdict[E_l] = eq_El_PM2.rhs().subs(vdict)
1436
vdict[H_l] = (R_s - R_ll - E_l).subs(vdict)
1437
1438
for name1 in namesdict:
1439
print str(name1)+' = ' + str(vdict[name1])
1440
1441
print eq_Rs_enbal.subs(vdict)
1442
1443
print 'MU-equation: '
1444
namesdict = [E_l, H_l]
1445
vdict[n_MU] = (a_sh/a_s).subs(vdict)
1446
vdict[E_l] = eq_El_MU2.rhs().subs(vdict)
1447
vdict[H_l] = (R_s - R_ll - E_l).subs(vdict)
1448
1449
for name1 in namesdict:
1450
print str(name1)+' = ' + str(vdict[name1])
1451
1452
print eq_Rs_enbal.subs(vdict)
1453
1454
print 'Corrected MU-equation: '
1455
namesdict = [E_l, H_l]
1456
vdict[E_l] = eq_El_MU_corr.rhs().subs(vdict)
1457
vdict[H_l] = (R_s - R_ll - E_l).subs(vdict)
1458
1459
for name1 in namesdict:
1460
print str(name1)+' = ' + str(vdict[name1])
1461
1462
print eq_Rs_enbal.subs(vdict)
1463
1464
1465
# <p><span style="color: #ff0000;">Penman-stomata gives identical results to the general solutions. </span></p>
1466
# <p><span style="color: #ff0000;">PM-equation greatly over-estimates $E_l$.</span></p>
1467
# <p><span style="color: #ff0000;">MU-equation greatly under-estimates $E_l$. </span></p>
1468
1469
# ## Analytical solution including longwave balance
1470
# The above analytical solutions eliminated the non-linearity problem of the saturation vapour pressure curve, but they did not take into account that the longwave component of the leaf energy balance ($R_{ll}$) also depends on leaf temperature, as expressed in Eq. {eq_Rll}. Therefore, the above analytical equations are commonly used in conjunction with fixed value of $R_{ll}$, either taken from observations or the assumption that $R_{ll}=0$. Here we will replace the non-linear Eq. {eq_Rll} by its tangent at $T_l = T_a$, which is given by:
1471
# ##### {eq_Rll_tang}
1472
# \begin{equation}
1473
# R_{ll} = 4 a_{sh} \epsilon_l \sigma T_a^3 T_l - a_{sh} \epsilon_l \sigma (T_w^4 + 3 T_a^4)
1474
# \end{equation}
1475
# This introduces a bias of less than -20~W~m$^{-2}$ in the calculation of $R_{ll}$ for leaf temperatures $\pm 20$ K of air temperture, compared to Eq. {eq_Rll} (see Fig. {fig:Rll_lin}.
1476
#
1477
#
1478
#
1479
# We can now use a similar procedure as in Section {sec:Penman_general}, but this time aimed at eliminating $P_{wl}$ using the Penman assumption, rather than eliminating $T_l$. We first eliminate $c_E$ from Eq. {eq_El_cE} by introducing Eq. {eq_gammav_cE}, then insert the Penman assumption (Eq. {eq_Penman_ass}) to eliminate $P_{wl}$ and obtain:
1480
# ##### {eq_El_Tl}
1481
# \begin{equation}
1482
# E_l = \frac{c_H \left(\Delta_{eTa} (T_l - T_a) + P_{was} - P_{wa} \right)}{\gamma_v}
1483
# \end{equation}
1484
# We can now insert the linearised Eq. {eq_Rll_tang}, Eq. {eq_El_Tl} and Eq. {eq_Hl_cH} into the energy balance equation (Eq. {eq_Rs_enbal}) and solve for $T_l$ to obtain:
1485
# ##### {eq_Tl_Delta_Rlllin}
1486
# \begin{equation}
1487
# T_l = \frac{R_s + c_H T_a + c_E \left(\Delta_{eTa} T_a + P_{wa} - P_{was} \right) + a_{sh} \epsilon_l \sigma \left(3 T_a^4 + T_w^4 \right)}
1488
# {c_H + c_E \Delta_{eTa} + 4 a_{sh} \epsilon_l \sigma T_a^3}
1489
# \end{equation}
1490
# Eq. {eq_Tl_Delta_Rlin} can be re-inserted into Eqs. {eq_Hl_cH}, {eq_El_Tl} and {eq_Rll_tang} to obtain analytical expressions for $H_l$, $E_l$ and $R_{ll}$ respectively, which satisfy the energy balance (Eq. {eq_Rs_enbal}). Alternatively, the value of $T_l$ obtained from Eq. {eq_Tl_Delta_Rlllin} for specific conditions could be used to calculate any of the energy balance components using the fundamental equations described in Fig. {fig:flow_enbalance}. In this case, bias in $T_l$ due to simplifying assumptions included in the derivation of Eq. {eq_Tl_Delta_Rlllin} would lead to a mismatch in the leaf energy balance.
1491
1492
# In[98]:
1493
1494
# Linearised R_ll
1495
var('T1 Rll1 dRlldT')
1496
dRlldT = diff(eq_Rll.rhs(), T_l)
1497
print dRlldT
1498
soln = solve(dRlldT(T_l = T1)*T1 + Rll1 == eq_Rll.rhs()(T_l = T1), Rll1)
1499
print soln
1500
# Tangent of R_ll at T1
1501
eq_Rll_tang = R_ll == (dRlldT(T_l = T1)*T_l + soln[0].rhs())(T1 = T_a).simplify_full()
1502
eq_Rll_tang.show()
1503
1504
1505
# In[99]:
1506
1507
vdict = cdict.copy()
1508
vdict[T_w] = 300
1509
vdict[T_a] = 300
1510
P = plot((eq_Rll.rhs().subs(vdict)), (T_l, 280,320), axes = False, frame = True, legend_label = 'non-linear' )
1511
P += plot(eq_Rll_tang.rhs().subs(vdict), (T_l, 280,320), linestyle = ':', legend_label = 'linear')
1512
P.axes_labels(['Temperature (K)', '$R_{ll}$ (W m$^{-2}$)'])
1513
1514
P.save(filename='figures/Rll_lin.pdf', figsize=[5,4],legend_font_size=10, fontsize=8)
1515
P.show(figsize=[5,4],legend_font_size=10, fontsize=8)
1516
1517
1518
# In[100]:
1519
1520
# Analtyical solution: keeping T_l, but eliminating P_wl and using eq_Rll_tang
1521
eq_El_cE.show()
1522
eq_Hl_cH.show()
1523
eq_Rll_tang.show()
1524
eq_gammav_cE.show()
1525
eq_Penman_ass.show()
1526
1527
# Eliminating c_E
1528
eq_El_gammav = solve([eq_El_cE, eq_gammav_cE], E_l, c_E)[0][0]
1529
print units_check(eq_El_gammav)
1530
1531
# Eliminating P_wl
1532
eq_El_Tl = solve([eq_El_gammav, eq_Penman_ass], E_l, P_wl)[0][0]
1533
print units_check(eq_El_Tl)
1534
1535
# Solving for E_l, H_l and T_l
1536
soln = solve([eq_El_Tl, eq_Hl_cH, eq_Rs_enbal.subs(eq_Rll_tang(T1 = T_a))], E_l, H_l, T_l)
1537
[eq_El_Delta_Rlllin, eq_Hl_Delta_Rlllin, eq_Tl_Delta_Rlllin] = [eq1.subs(eq_gammav_cE).simplify_full() for eq1 in flatten(soln)]
1538
for eq1 in [eq_El_Delta_Rlllin, eq_Hl_Delta_Rlllin, eq_Tl_Delta_Rlllin]:
1539
print units_check(eq1)
1540
1541
1542
# In[101]:
1543
1544
soln = solve(eq_Rs_enbal.subs(eq_Rll_tang, eq_El_Tl, eq_Hl_cH), T_l)
1545
eq_Tl_Delta_Rlllin = soln[0].subs(eq_gammav_cE).simplify_full()
1546
units_check(eq_Tl_Delta_Rlllin)
1547
1548
1549
# In[102]:
1550
1551
eq_El_Tl.subs(eq_Tl_Delta_Rlllin).subs(eq_gammav_cE).simplify_full().show()
1552
eq_El.subs(eq_Elmol).subs(eq_Cwa, eq_Cwl).subs(eq_Tl_Delta_Rlllin).simplify_full().show()
1553
eq_Hl_cH.subs(eq_Tl_Delta_Rlllin).simplify_full().show()
1554
eq_Rll_tang.subs(eq_Tl_Delta_Rlllin).simplify_full().show()
1555
1556
1557
# In[103]:
1558
1559
# Fig. 8 in Ball et al. 1988
1560
vdict = cdict.copy()
1561
vdict[a_s] = 1
1562
vdict[L_l] = 0.07
1563
vdict[P_a] = 101325
1564
vdict[P_wa] = 20/1000*101325
1565
vdict[R_s] = 400
1566
vdict[Re_c] = 3000
1567
vdict[T_a] = 273+30
1568
vdict[T_w] = vdict[T_a]
1569
vdict[g_sw] = 0.15/40
1570
#vdict[g_sv] = 1e-6
1571
1572
vdict[v_w] = 1.
1573
resdict = fun_SS(vdict)
1574
for name1 in [T_l, E_l, H_l, R_ll, g_bw, g_tw]:
1575
print str(name1)+' = ' + str(resdict[name1])
1576
1577
vdict[P_was] = eq_Pwl.rhs()(T_l = T_a).subs(vdict)
1578
vdict[Delta_eTa] = eq_Deltaeta_T.rhs().subs(vdict)
1579
vdict[k_a] = eq_ka.rhs().subs(vdict)
1580
vdict[nu_a] = eq_nua.rhs().subs(vdict)
1581
vdict[Re] = eq_Re.rhs().subs(vdict)
1582
vdict[Nu] = eq_Nu_forced_all.rhs().subs(vdict)
1583
vdict[h_c] = eq_hc.rhs().subs(vdict)
1584
1585
vdict[P_N2] = eq_PN2.rhs().subs(vdict)
1586
vdict[P_O2] = eq_PO2.rhs().subs(vdict)
1587
vdict[alpha_a] = eq_alphaa.rhs().subs(vdict)
1588
vdict[k_a] = eq_ka.rhs().subs(vdict)
1589
vdict[D_va] = eq_Dva.rhs().subs(vdict)
1590
vdict[Le] = eq_Le.rhs().subs(vdict)
1591
vdict[rho_a] = eq_rhoa_Pwa_Ta.rhs().subs(vdict)
1592
vdict[g_bw] = eq_gbw_hc.rhs().subs(vdict)
1593
vdict[g_tw] = eq_gtw.rhs().subs(vdict)
1594
vdict[g_twmol] = eq_gtwmol_gtw_iso.rhs().subs(vdict)
1595
1596
1597
print 'Direct estimates: '
1598
namesdict = [E_l, H_l, T_l, R_ll]
1599
vdict[E_l] = eq_El_Delta_Rlllin.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1600
vdict[H_l] = eq_Hl_Delta_Rlllin.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1601
vdict[T_l] = eq_Tl_Delta_Rlllin.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1602
vdict[R_ll] = eq_Rll_tang.rhs().subs(vdict)
1603
1604
for name1 in namesdict:
1605
print str(name1)+' = ' + str(vdict[name1])
1606
1607
print eq_Tl_Delta.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1608
print eq_Tl_Delta1.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1609
print eq_Tl_Delta2.subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1610
print eq_Rs_enbal.subs(vdict)
1611
1612
print 'Using T_l from eq_Tl_Delta_Rlllin.rhs() only to calculate R_ll: '
1613
namesdict = [T_l, R_ll, E_l, H_l]
1614
vdict[R_ll] = 0
1615
vdict[T_l] = eq_Tl_Delta_Rlllin.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1616
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
1617
vdict[E_l] = eq_El_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1618
vdict[H_l] = eq_Hl_Delta.rhs().subs(eq_ce_conv, eq_ch_hc).subs(vdict)
1619
1620
for name1 in namesdict:
1621
print str(name1)+' = ' + str(vdict[name1])
1622
print eq_Rs_enbal.subs(vdict)
1623
1624
vdict[R_ll] = 0
1625
print 'Penman-stomata: '
1626
namesdict = [E_l, H_l, T_l]
1627
vdict[S] = eq_S_gbw_gsw.rhs().subs(vdict)
1628
vdict[f_u] = eq_fu_gbw.rhs().subs(vdict)
1629
vdict[gamma_v] = eq_gammav_as.rhs().subs(vdict)
1630
vdict[E_l] = eq_El_P52.rhs().subs(vdict)
1631
vdict[H_l] = eq_Hl_P52.rhs().subs(vdict)
1632
vdict[T_l] = eq_Tl_P52.rhs().subs(vdict)
1633
for name1 in namesdict:
1634
print str(name1)+' = ' + str(vdict[name1])
1635
1636
print eq_Rs_enbal.subs(vdict)
1637
1638
print 'PM-equation: '
1639
namesdict = [E_l, H_l]
1640
vdict[r_s] = 1/vdict[g_sw]
1641
vdict[r_a] = eq_ra_hc.rhs().subs(vdict)
1642
vdict[gamma_v] = eq_gammav_MU.rhs().subs(vdict)
1643
vdict[epsilon] = eq_epsilon.rhs().subs(vdict)
1644
vdict[E_l] = eq_El_PM2.rhs().subs(vdict)
1645
vdict[H_l] = (R_s - R_ll - E_l).subs(vdict)
1646
1647
for name1 in namesdict:
1648
print str(name1)+' = ' + str(vdict[name1])
1649
1650
print eq_Rs_enbal.subs(vdict)
1651
1652
print 'MU-equation: '
1653
namesdict = [E_l, H_l]
1654
vdict[n_MU] = (a_sh/a_s).subs(vdict)
1655
vdict[E_l] = eq_El_MU2.rhs().subs(vdict)
1656
vdict[H_l] = (R_s - R_ll - E_l).subs(vdict)
1657
1658
for name1 in namesdict:
1659
print str(name1)+' = ' + str(vdict[name1])
1660
1661
print eq_Rs_enbal.subs(vdict)
1662
1663
print 'Corrected MU-equation: '
1664
namesdict = [E_l, H_l]
1665
vdict[E_l] = eq_El_MU_corr.rhs().subs(vdict)
1666
vdict[H_l] = (R_s - R_ll - E_l).subs(vdict)
1667
1668
for name1 in namesdict:
1669
print str(name1)+' = ' + str(vdict[name1])
1670
1671
print eq_Rs_enbal.subs(vdict)
1672
1673
1674
# <p><span style="color: #ff0000;">The use of the linearised R_ll improves accurcay significantly compared to eq_Tl_Delta!</span></p>
1675
1676
# In[104]:
1677
1678
save_session('temp/E_PM_eqs')
1679
1680
1681
# # Table of symbols
1682
1683
# In[105]:
1684
1685
# Creating dictionary to substitute names of units with shorter forms
1686
var('m s J Pa K kg mol')
1687
subsdict = {meter: m, second: s, joule: J, pascal: Pa, kelvin: K, kilogram: kg, mole: mol}
1688
var('N_Re_L N_Re_c N_Le N_Nu_L N_Gr_L N_Sh_L')
1689
dict_varnew = {Re: N_Re_L, Re_c: N_Re_c, Le: N_Le, Nu: N_Nu_L, Gr: N_Gr_L, Sh: N_Sh_L}
1690
dict_varold = {v: k for k, v in dict_varnew.iteritems()}
1691
variables = sorted([str(variable.subs(dict_varnew)) for variable in udict.keys()],key=str.lower)
1692
tableheader = [('Variable', 'Description (value)', 'Units')]
1693
tabledata = [('Variable', 'Description (value)', 'Units')]
1694
for variable1 in variables:
1695
variable2 = eval(variable1).subs(dict_varold)
1696
variable = str(variable2)
1697
tabledata.append((eval(variable),docdict[eval(variable)],fun_units_formatted(variable)))
1698
1699
table(tabledata, header_row=True)
1700
1701
1702
# In[ ]:
1703
1704
1705
1706
1707