Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
| Download

šŸ“š The CoCalc Library - books, templates and other resources

Views: 96143
License: OTHER
1
2
# coding: utf-8
3
4
# # Leaf energy balance equations
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
# Note: This worksheet is prepared for the open source software [sage](http://www.sagemath.org). It relies on definitions provided in Worksheet [Worksheet_setup](Worksheet_setup.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\n# Loading modules, settings and custom functions\nload('temp/Worksheet_setup.sage')")
15
16
17
# ## Definition of variables
18
# All variables are also listed in a [Table](#Table-of-symbols) at the end of this document.
19
20
# In[2]:
21
22
var2('alpha_a', 'Thermal diffusivity of dry air',meter^2/second)
23
var2('a_s', 'Fraction of one-sided leaf area covered by stomata (1 if stomata are on one side only, 2 if they are on both sides)', meter^2/meter^2)
24
var2('a_sh', 'Fraction of projected area exchanging sensible heat with the air (2)', meter^2/meter^2, value = 2, latexname = 'a_{sh}')
25
var2('c_pa', 'Specific heat of dry air (1010) ', joule/kilogram/kelvin, latexname = 'c_{pa}', value = 1010)
26
#var2('c_pamol', 'Molar specific heat of dry air (29.19) ', joule/mole/kelvin, latexname = 'c_{pa,mol}', value = 29.19) # https://en.wikipedia.org/wiki/Heat_capacity#Specific_heat_capacity
27
var2('C_wa', 'Concentration of water in the free air ',mole/meter^3, latexname = 'C_{wa}')
28
var2('C_wl', 'Concentration of water in the leaf air space ',mole/meter^3, latexname = 'C_{wl}')
29
var2('D_va', 'Binary diffusion coefficient of water vapour in air',meter^2/second, latexname = 'D_{va}')
30
var2('E_lmol', 'Transpiration rate in molar units',mole/second/meter^2,latexname='E_{l,mol}')
31
var2('E_l', 'Latent heat flux from leaf',joule/second/meter^2)
32
var2('epsilon_l', 'Longwave emmissivity of the leaf surface (1.0)', value = 1, units = 1/1)
33
var2('g', 'Gravitational acceleration (9.81)', meter/second^2, value= 9.81)
34
var2('g_bw', 'Boundary layer conductance to water vapour ',meter/second,latexname='g_{bw}')
35
var2('g_bwmol', 'Boundary layer conductance to water vapour ',mole/meter^2/second,latexname='g_{bw,mol}')
36
var2('Gr', 'Grashof number', latexname = 'N_{Gr_L}')
37
var2('g_sw', 'Stomatal conductance to water vapour',meter/second,latexname='g_{sw}')
38
var2('g_swmol', 'Stomatal conductance to water vapour',mole/meter^2/second,latexname='g_{sw,mol}')
39
var2('g_tw', 'Total leaf conductance to water vapour',meter/second,latexname='g_{tw}')
40
var2('g_twmol', 'Total leaf layer conductance to water vapour',mole/meter^2/second,latexname='g_{tw,mol}')
41
var2('h_c', 'Average 1-sided convective transfer coefficient', joule/meter^2/second/kelvin)
42
var2('H_l', 'Sensible heat flux from leaf',joule/second/meter^2)
43
var2('k_a', 'Thermal conductivity of dry air',joule/second/meter/kelvin)
44
var2('lambda_E', 'Latent heat of evaporation (2.45e6)',joule/kilogram,value = 2.45e6)
45
var2('Le', 'Lewis number', latexname = 'N_{Le}')
46
var2('L_l', 'Characteristic length scale for convection (size of leaf)',meter)
47
var2('M_N2', 'Molar mass of nitrogen (0.028)',kilogram/mole,value = 0.028)
48
var2('M_O2', 'Molar mass of oxygen (0.032)',kilogram/mole,value = 0.032)
49
var2('M_w', 'Molar mass of water (0.018)',kilogram/mole,value = 0.018)
50
var2('nu_a', 'Kinematic viscosity of dry air',meter^2/second)
51
var2('Nu', 'Nusselt number',latexname = 'N_{Nu_L}')
52
var2('P_a', 'Air pressure',pascal)
53
var2('Pr', 'Prandtl number (0.71)',latexname = 'N_{Pr}',value = 0.71)
54
var2('P_N2', 'Partial pressure of nitrogen in the atmosphere', pascal, latexname = 'P_{N2}')
55
var2('P_O2', 'Partial pressure of oxygen in the atmosphere', pascal, latexname = 'P_{O2}')
56
var2('P_wa', 'Vapour pressure in the atmosphere', pascal, latexname = 'P_{wa}')
57
var2('P_was', 'Saturation vapour pressure at air temperature', pascal, latexname = 'P_{was}')
58
var2('P_wl', 'Vapour pressure inside the leaf', pascal, latexname = 'P_{wl}')
59
var2('r_bw', 'Boundary layer resistance to water vapour, inverse of $g_{bw}$', second/meter, latexname = 'r_{bw}')
60
var2('r_sw', 'Stomatal resistance to water vapour, inverse of $g_{sw}$', second/meter, latexname = 'r_{sw}')
61
var2('r_tw', 'Total leaf resistance to water vapour, $r_{bv} + r_{sv}$', second/meter, latexname = 'r_{tw}')
62
var2('Re_c', 'Critical Reynolds number for the onset of turbulence',latexname='N_{Re_c}')
63
var2('Re', 'Reynolds number',latexname='N_{Re_L}')
64
var2('rho_a', 'Density of dry air', kilogram/meter^3)
65
var2('rho_al', 'Density of air at the leaf surface', kilogram/meter^3)
66
var2('R_ll', 'Longwave radiation away from leaf',joule/second/meter^2, latexname = 'R_{ll}')
67
var2('R_mol', 'Molar gas constant (8.314472)',joule/mole/kelvin,latexname='R_{mol}', value = 8.314472)
68
var2('R_s', 'Solar shortwave flux',joule/second/meter^2)
69
var2('Sh', 'Sherwood number',latexname = 'N_{Sh_L}')
70
var2('sigm', 'Stefan-Boltzmann constant (5.67e-8)',joule/second/meter^2/kelvin^4,'real',latexname='\\sigma',value=5.67e-8)
71
var2('T_a', 'Air temperature',kelvin)
72
var2('T_l', 'Leaf temperature',kelvin)
73
var2('T_w', 'Radiative temperature of objects surrounding the leaf', kelvin)
74
var2('v_w', 'Wind velocity',meter/second)
75
76
77
# # Mathematical derivations
78
# ## Leaf energy balance
79
# The material below follows closely derivations published previously \citep{schymanski_stomatal_2013}, with re-organisation of equations for greater consistence with the present paper.
80
#
81
# The leaf energy balance is determined by the dominant energy fluxes between the leaf and its surroundings, including radiative, sensible, and latent energy exchange (linked to mass exchange).
82
#
83
#
84
# In this study we focus on steady-state conditions, in which the energy balance can be written as:
85
# ##### {eq_Rs_enbal}
86
# $$ R_s = R_{ll} + H_l + E_l $$
87
# where $R_s$ absorbed short wave radiation, $R_{ll}$ is the net longwave balance, i.e. the emitted minus the absorbed, $H_l$ is the sensible heat flux away from the leaf and $E_l$ is the latent heat flux away from the leaf. In the above, extensive variables are defined per unit leaf area. Following our previous work \citep{schymanski_stomatal_2013}, this study considers spatially homogeneous planar leaves, i.e. homogenous illumination and a negligible temperature gradient between the two sides of the leaf.
88
# The net longwave emission is represented by the difference between blackbody radiation at leaf temperature ($T_l$) and that at the temperature of the surrounding objects ($T_w$) \citep{Monteith_principles_2007}:
89
# ##### {eq_Rll}
90
# $$R_{ll} = a_{sH} \epsilon_l \sigma (T_{l}^{4} - T_{w}^{4})$$
91
#
92
# where $a_{sH}$ is the fraction of projected leaf area exchanging radiative and sensible heat (2 for a planar leaf, 1 for a soil surface), $\epsilon_l$ is the leaf's longwave emmissivity ($\approx 1$) and $\sigma$ is the Stefan-Boltzmann constant.
93
# Total convective heat transport away from the leaf is represented as:
94
# ##### {eq_Hl}
95
# $$H_l = a_{sH} h_c (T_l - T_a)$$
96
#
97
# where $h_c$ is the average one-sided convective heat transfer coefficient, determined by properties of the leaf boundary layer.
98
#
99
# Latent heat flux ($E_l$, W~m$^{-2}$) is directly related to the transpiration rate ($E_{l,mol}$) by:
100
# ##### {eq_El}
101
# $$E_l = E_{l,mol} M_w \lambda_E$$
102
#
103
# where $M_w$ is the molar mass of water and $\lambda_E$ the latent heat of vaporisation. $E_{l,mol}$ (mol~m$^{-2}$~s$^{-1}$) was computed in molar units as a function of the concentration of water vapour within the leaf ($C_{wl}$, mol m$^{-3}$) and in the free air ($C_{wa}$, mol m$^{-3}$) \citep[Eq. 6.8]{incropera_fundamentals_2006}:
104
# ##### {eq_Elmol}
105
# $$E_{l,mol} = g_{tw}(C_{wl} - C_{wa}) $$
106
#
107
# where $g_{tw}$ (m~s$^{-1}$) is the total leaf conductance for water vapour, dependent on stomatal ($g_{sw}$) and boundary layer conductance ($g_{bw}$) in the following way:
108
# ##### {eq_gtw}
109
# $$g_{tw} = \frac{1}{\frac{1}{g_{sw}} + \frac{1}{g_{bw}}}$$
110
#
111
112
# In[3]:
113
114
eq_Rs_enbal = R_s == R_ll + H_l + E_l
115
units_check(eq_Rs_enbal).simplify_full()
116
117
118
# In[4]:
119
120
eq_Rll = R_ll == a_sh*sigm*epsilon_l*(T_l^4 - T_w^4)
121
units_check(eq_Rll).simplify_full()
122
123
124
# In[5]:
125
126
eq_Hl = H_l == a_sh*h_c*(T_l - T_a)
127
units_check(eq_Hl).simplify_full()
128
129
130
# In[6]:
131
132
eq_El = E_l == E_lmol*M_w*lambda_E
133
units_check(eq_El).simplify_full()
134
135
136
# In[7]:
137
138
ustr = str(units_check(M_w*lambda_E))
139
print str((M_w*lambda_E).subs(cdict)) + ustr
140
141
142
# In[8]:
143
144
eq_Elmol = E_lmol == g_tw*(C_wl - C_wa)
145
units_check(eq_Elmol).simplify_full()
146
147
148
# In[9]:
149
150
eq_gtw = g_tw == 1/(1/g_sw + 1/g_bw)
151
eq_gtw.simplify_full().show()
152
units_check(eq_gtw).simplify_full()
153
154
155
# ## Boundary layer conductance to water vapour
156
# The total leaf conductance to water vapour is determined by the boundary layer and stomatal conductances and equal to 1 over the sum of their respectife resistances ($g_{tw} = 1/(r_{sw} + r_{bw})$.
157
# The boundary layer conductance for water vapour is equivalent to the mass transfer coefficient for a wet surface \cite[Eq. 7.41]{incropera_fundamentals_2006}:
158
# ##### {eq_gbw}
159
# $$g_{bw} = N_{Sh_L} D_{va}/L_l$$
160
#
161
# where $N_{Sh_L}$ is the dimensionless Sherwood number and $D_{va}$ is the diffusivity of water vapour in air.
162
# If the convection coefficient for heat is known, the one for mass ($g_{bw}$) can readily be calculated from the relation \cite[Eq. 6.60]{incropera_fundamentals_2006}:
163
# ##### {eq_gbw_hc}
164
# $$g_{bw} = \frac{a_s h_c}{\rho_a c_{pa} N_{Le}^{1-n}}$$
165
#
166
# where $a_s$ is the fraction of one-sided transpiring surface area in relation to the surface area for sensible heat exchange, $c_{pa}$ is the constant-pressure heat capacity of air, $n$ is an empirical constant ($n=1/3$ for general purposes) and $N_{Le}$ is the dimensionless Lewis number, defined as \cite[Eq. 6.57]{incropera_fundamentals_2006}:
167
# ##### {eq_Le}
168
# $$N_{Le} = \alpha_a/D_{va}$$
169
#
170
# where $\alpha_a$ is the thermal diffusivity of air. The value of $a_s$ was set to 1 for leaves with stomata on one side only, and to 2 for stomata on both sides. Other values could be used for leaves only partly covered by stomata.
171
172
# In[10]:
173
174
eq_gbw = g_bw == D_va*Sh/L_l
175
units_check(eq_gbw).simplify_full()
176
eq_gbw_hc = g_bw == a_s*h_c/(rho_a*c_pa*Le^(2/3))
177
print units_check(eq_gbw_hc).simplify_full()
178
eq_Le = Le == alpha_a/D_va
179
units_check(eq_Le).simplify_full()
180
181
182
# ## Effect of leaf temperature on the leaf-air vapour concentration gradient
183
# \label{sec_Tleaf}
184
# The concentration difference in Eq. [eq_Elmol](#{eq_Elmol}) is a function of the temperature and the vapour pressure differences between the leaf and the free air. Assuming that water vapour behaves like an ideal gas, we can express its concentration as:
185
# ##### {eq_Cwl}
186
# $$C_{wl} = \frac{P_{wl}}{R_{mol} T_l}
187
# $$
188
#
189
# where $P_{wl}$ is the vapour pressure inside the leaf, $R_{mol}$ is the universal gas constant and $T_l$ is leaf temperature. A similar relation holds for the vapour concentration in free air, $C_{wa} = P_{wa}/(R_{mol} T_l)$. In this study the vapour pressure inside the leaf is assumed to be the saturation vapour pressure at leaf temperature, which is computed using the Clausius-Clapeyron relation \citep[Eq. B.3]{hartmann_global_1994}:
190
# ##### {eq_Pwl}
191
# $$P_{wl} = 611 \exp \left( \frac{\lambda_E M_w}{R_{mol}} \left( \frac{1}{273} - \frac{1}{T_l} \right) \right)
192
# $$
193
# where $\lambda_E$ is the latent heat of vaporisation and $M_w$ is the molar mass of water.
194
#
195
# Note that the dependence of the leaf-air water concentration difference ($C_{wl} - C_{wa}$) in Eq. [eq_Cwl](#{eq_Cwl}) is very sensitive to leaf temperature. For example if the leaf temperature increases by 5K relative to air temperature, $C_{wl} - C_{wa}$ would double, while if leaf temperature decreased by 6K, $C_{wl} - C_{wa}$ would go to 0 at 70\% relative humidity.
196
197
# <p>Ā </p>
198
# <p>Ā </p>
199
200
# In[11]:
201
202
eq_Cwl = C_wl == P_wl/(R_mol*T_l)
203
print units_check(eq_Cwl).simplify_full()
204
eq_Pwl = P_wl == 611*exp(lambda_E*M_w/R_mol*(1/273 - 1/T_l))
205
show(eq_Pwl)
206
207
208
# ## Concentration or vapour pressure gradient driving transpiration?
209
#
210
# Note that $E_{l,mol}$ is commonly expressed as a function of the vapour pressure difference between the free air ($P_{wa}$) and the leaf ($P_{wl}$), in which the conductance ($g_{tw,mol}$) is expressed in molar units (mol~m$^{-2}$~s$^{-1}$):
211
# ##### {eq_Elmol_conv}
212
# $$ E_{l,mol} = g_{tw,mol} \frac{P_{wl} - P_{wa}}{P_a}$$
213
#
214
# For $P_{wl} = P_{wa}$, Eq. [eq_Elmol](#{eq_Elmol}) can still give a flux, whereas Eq. [eq_Elmol_conv](#{eq_Elmol_conv}) gives zero flux. This is because the concentrations of vapour in air (mol~m$^{-3}$) can differ due to differences in tempertaure, even if the partial vapour pressures are the same (see Eq. [eq_Cwl](#{eq_Cwl})). Therefore, the relation between $g_{tw}$ and $g_{v,mol}$ has an asymptote at the equivalent temperature. It can be obtained by combining Eqs. [eq_Elmol](#{eq_Elmol}) and [eq_Elmol_conv](#{eq_Elmol_conv}) and solving for $g_{tw,mol}$:
215
# ##### {eq_gtwmol_gtw}
216
# $$g_{tw,mol} = g_{tw}\frac{P_a(P_{wa} T_l - P_{wl} T_a)}{(P_{wa} - P_{wl}) R_{mol} T_a T_l)}$$
217
#
218
# For $T_l = T_a$, the relation simplifies to:
219
# ##### {eq_gtwmol_gtw_iso}
220
# $$g_{tw,mol} = g_{tw}\frac{P_a }{R_{mol} T_a}$$
221
#
222
# which, for typical values of $P_a$ and $T_a$ amounts to $g_{tw,mol}\approx40$~mol~m$^{-3}g_{tw}$. For all practical purposes, we found that Eqs. [eq_Elmol](#{eq_Elmol}) and [eq_Elmol_conv](#{eq_Elmol_conv}) with $g_{tw,mol} = g_{tw}\frac{P_a }{R_{mol} T_a}$ give similar results when plotted as functions of leaf temperature.
223
224
# In[12]:
225
226
eq_Elmol_conv = E_lmol == g_twmol*(P_wl-P_wa)/P_a
227
print units_check(eq_Elmol_conv).simplify_full()
228
soln = solve([eq_Elmol.subs(eq_Cwl, eq_Cwl(C_wl = C_wa, P_wl = P_wa, T_l = T_a)), eq_Elmol_conv], g_twmol, E_lmol)
229
eq_gtwmol_gtw = soln[0][0]
230
print units_check(eq_gtwmol_gtw).simplify_full()
231
eq_gtwmol_gtw_iso = eq_gtwmol_gtw(T_l = T_a).simplify_full()
232
print units_check(eq_gtwmol_gtw_iso).simplify_full()
233
234
235
# ## Model closure
236
#
237
# Given climatic forcing as $P_a$, $T_a$, $R_s$, $P_{wa}$ and $v_w$, and leaf-specific parameters $a_s$, $a_{sH}$, $L_l$ and $g_{sw}$, we need to compute $C_{wa}$, $h_c$, $g_{bw}$ and a series of other derived variables, as described below.
238
#
239
# The vapour concentration in the free air can be computed from vapour pressure analogously to Eq. [eq_Cwl](#{eq_Cwl}):
240
# ##### {eq_Cwa}
241
# $$C_{wa} = \frac{P_{wa}}{R_{mol} T_a}$$
242
#
243
# The heat transfer coefficient ($h_c$) for a flat plate can be determined using the non-dimensional Nusselt number ($N_{Nu_L}$):
244
# ##### {eq_hc}
245
# $$h_{c} = k_a\frac{N_{Nu_L}}{L_l}$$
246
#
247
# where $k_a$ is the thermal conductivity of the air in the boundary layer and $L_l$ is a characteristic length scale of the leaf.
248
#
249
# For sufficiently high wind speeds, inertial forces drive the convective heat transport (forced convection) and the relevant dimensionless number is the Reynolds number ($N_{Re_L}$), which defines the balance between inertial and viscous forces \cite[Eq. 6.41]{incropera_fundamentals_2006}:
250
# ##### {eq_Re}
251
# $$N_{Re_L} = \frac{v_w L_l}{\nu_a}$$
252
#
253
# where $v_w$ is the wind velocity (m s$^{-1}$), $\nu_a$ is the kinematic viscosity of the air and $L_l$ is taken as the length of the leaf in wind direction.
254
#
255
# In the absence of wind, buoyancy forces, driven by the density gradient between the air at the surface of the leaf and the free air dominate convective heat exchange (``free'' or ``natural convection''). The relevant dimensionless number here is the Grashof number ($N_{Gr_L}$), which defines the balance between buoyancy and viscous forces \cite[Eqs. 9.3 and 9.65]{incropera_fundamentals_2006}:
256
# ##### {eq_Gr}
257
# $$N_{Gr_L} =\frac{g(\frac{\rho_a - \rho_{al}}{\rho_{al}}) L_l^3}{\nu_a^2}$$
258
#
259
# where $g$ is gravity, while $\rho_a$ and $\rho_{al}$ are the densities of the gas in the atmosphere and at the leaf surface respectively.
260
#
261
# For $N_{Gr_L} \ll N_{Re_L}^2$, forced convection is dominant and free convection can be neglected, whereas for $N_{Gr_L} \gg N_{Re_L}^2$ free convection is dominant and forced convection can be neglected \cite[P. 565]{incropera_fundamentals_2006}. For simplicity, the analysis is limited to forced conditions, which is satisfied by considering wind speeds greater than 0.5~m~s$^{-1}$ for $5 \times 5$ cm leaves. %See leaf_chamber4.sws or leaf_capacitance_steady_state3.sws.
262
#
263
# The average Nusselt number under forced convection was calculated as a function of the average Reynolds number and a critical Reynolds number ($N_{Re_c}$) that determines the onset of turbulence and depends on the level of turbulence in the free air stream or leaf surface properties \cite[P. 412]{incropera_fundamentals_2006}
264
#
265
# ##### {eq_Nu_forced_all}
266
# $$N_{Nu_L} = (0.037 N_{Re_L}^{4/5} - C_1)N_{Pr}^{1/3}$$
267
#
268
# with
269
# ##### {eq_C1}
270
# $$C_1 = 0.037 C_2^{4/5} - 0.664 C_2^{1/2}$$
271
#
272
# and
273
# ##### {eq_C2}
274
# $$C_2 = \frac{N_{Re_L} + N_{Re_c} - |N_{Re_c} - N_{Re_L}|}{2}$$
275
#
276
# Eq. [eq_C2](#{eq_C2}) was introduced to make Eq. [eq_Nu_forced_all](#{eq_Nu_forced_all}) valid for all Reynolds numbers, and following considerations explained in our previous work \citep{schymanski_stomatal_2013}, we chose $N_{Re_c}=3000$ in the present simulations.
277
278
# In[13]:
279
280
eq_Cwa = C_wa == P_wa/(R_mol*T_a)
281
print units_check(eq_Cwa)
282
eq_hc = h_c == k_a*Nu/L_l
283
print units_check(eq_hc)
284
eq_Re = Re == v_w*L_l/nu_a
285
print units_check(eq_Re)
286
eq_Gr = Gr == g*(rho_a - rho_al)/rho_al * L_l^3/nu_a^2
287
print units_check(eq_Gr)
288
C2 = (Re + Re_c - (abs(Re - Re_c))/2)
289
C1 = 0.037*C2^(4/5) - 0.664*C2^(1/2)
290
eq_Nu_forced_all = Nu == (0.037*Re^(4/5) - C1)*Pr^(1/3)
291
eq_Nu_forced_all.show()
292
293
294
# ### Thermodynamic variables
295
# In order to simulate steady state leaf temperatures and the leaf energy balance terms using the above equations, it is necessary to calculate $\rho_a$, $D_{wa}$, $\alpha_a$, $k_a$, and $\nu_a$, while $L_l$, $Re_c$ and $g_{sv}$ are input parameters, and $P_{wa}$ and $v_w$ (vapour pressure and wind speed) are part of the environmental forcing.
296
# $D_{wa}$, $\alpha_a$, $k_a$ and $\nu_a$ were parameterised as functions of air temperature ($T_a$) only, by fitting linear curves to published data \cite[Table A.3]{Monteith_principles_2007}:
297
# ##### {eq_Dwa}
298
# $$D_{wa} = (1.49\times 10^{-7})T_a - 1.96\times 10^{-5}$$
299
#
300
# ##### {eq_alphaa}
301
# $$\alpha_a = (1.32\times 10^{-7})T_a - 1.73\times 10^{-5}$$
302
#
303
# ##### {eq_ka}
304
# $$k_a = (6.84\times 10^{-5})T_a + 5.62\times 10^{-3}$$
305
#
306
# ##### {eq_nua}
307
# $$\nu_a = (9\times 10^{-8})T_a - 1.13\times 10^{-5}$$
308
#
309
#
310
# Assuming that air and water vapour behave like an ideal gas, and that dry air is composed of 79\% N$_2$ and 21\% O$_2$, we calculated air density as a function of temperature, vapour pressure and the partial pressures of the other two components using the ideal gas law:
311
# ##### {eq_rhoa_Pa_Ta}
312
# $$\rho_a = \frac{n_a M_a}{V_a} = M_a \frac{P_a}{R_{mol} T_a}$$
313
#
314
# where $n_a$ is the amount of matter (mol), $M_a$ is the molar mass (kg~mol$^{-1}$), $P_a$ the pressure, $T_a$ the temperature and $R_{mol}$ the molar universal gas constant.
315
# This equation was used for each component, i.e. water vapour, N$_2$ and O$_2$, where the partial pressures of N$_2$ and O$_2$ are calculated from atmospheric pressure minus vapour pressure, yielding:
316
# ##### {eq_rhoa_Pwa_Ta}
317
# $$\rho_a = \frac{M_w P_{wa} + M_{N_2} P_{N_2} + M_{O_2} P_{O_2}}{R_{mol} T_a}$$
318
#
319
# where $M_{N_2}$ and $M_{O_2}$ are the molar masses of nitrogen and oxygen respectively, while $P_{N_2}$ and $P_{O_2}$ are their partial pressures, calculated as:
320
#
321
# ##### {eq_PN2}
322
# $$P_{N_2} = 0.79(P_a - P_{wa})$$
323
#
324
# and
325
# ##### {eq_PO2}
326
# $$P_{O_2} = 0.21(P_a - P_{wa})$$
327
#
328
329
# In[14]:
330
331
eq_Dva = D_va == 1.49e-07*T_a - 1.96e-05
332
eq_alphaa = alpha_a == (1.32e-07)*T_a - 1.73e-05
333
eq_ka = k_a == 6.84e-05*T_a + 5.63e-03
334
eq_nua = nu_a == 9.e-08*T_a - 1.13e-05
335
eq_rhoa_Pwa_Ta = rho_a == (M_w*P_wa + M_N2*P_N2 + M_O2*P_O2)/(R_mol*T_a)
336
print units_check(eq_rhoa_Pwa_Ta)
337
338
339
# In[15]:
340
341
eq_Pa = P_a == P_N2 + P_O2 + P_wa
342
print units_check(eq_Pa)
343
eq_PN2_PO2 = P_N2 == 0.79/0.21*P_O2
344
soln = solve([eq_Pa, eq_PN2_PO2], P_O2, P_N2)
345
eq_PO2 = soln[0][0]
346
print units_check(eq_PO2)
347
eq_PN2 = soln[0][1]
348
units_check(eq_PN2)
349
350
351
# In[16]:
352
353
eq_rhoa = eq_rhoa_Pwa_Ta.subs(eq_PN2, eq_PO2)
354
units_check(eq_rhoa).simplify_full()
355
356
357
# ## Example calculations
358
359
# In[17]:
360
361
# Energy balance as a function of variables that are independent of leaf temperature
362
eqenbalTl = (eq_Rs_enbal - R_s).rhs().subs(eq_El, eq_Hl, eq_Rll).subs(eq_Elmol).subs(eq_Cwl).subs(eq_Pwl)
363
eqenbalTl.subs(cdict).args()
364
365
366
# Below, we create a copy of cdict, which is a dictionary with general constants, generated during the definition of variables at the top of the worksheet, and some example values for external forcing and leaf properties needed to compute steady-state fluxes and leaf temperature:
367
368
# In[18]:
369
370
# Input values
371
vdict = cdict.copy()
372
vdict[a_s] = 1.0 # one sided stomata
373
vdict[g_sw] = 0.01
374
vdict[T_a] = 273 + 25.5
375
vdict[T_w] = vdict[T_a] # Wall temperature equal to air temperature
376
vdict[P_a] = 101325
377
rha = 1
378
vdict[P_wa] = rha*eq_Pwl.rhs()(T_l = T_a).subs(vdict)
379
vdict[L_l] = 0.03
380
vdict[Re_c] = 3000
381
vdict[R_s] = 600
382
vdict[v_w] = 1
383
384
385
# Now, we compute all derived variables, using the equations described above.
386
387
# In[19]:
388
389
# Nusselt number
390
vdict[nu_a] = eq_nua.rhs().subs(vdict)
391
vdict[Re] = eq_Re.rhs().subs(vdict)
392
vdict[Nu] = eq_Nu_forced_all.rhs().subs(vdict)
393
vdict[Nu]
394
395
396
# In[20]:
397
398
# h_c
399
vdict[k_a] = eq_ka.rhs().subs(vdict)
400
vdict[h_c] = eq_hc.rhs().subs(vdict)
401
vdict[h_c]
402
403
404
# In[21]:
405
406
# gbw
407
vdict[D_va] = eq_Dva.rhs().subs(vdict)
408
vdict[alpha_a] = eq_alphaa.rhs().subs(vdict)
409
vdict[rho_a] = eq_rhoa.rhs().subs(vdict)
410
vdict[Le] = eq_Le.rhs().subs(vdict)
411
vdict[g_bw] = eq_gbw_hc.rhs().subs(vdict)
412
vdict[g_bw]
413
414
415
# In[22]:
416
417
# Hl, Rll
418
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
419
print vdict[R_ll]
420
vdict[H_l] = eq_Hl.rhs().subs(vdict)
421
vdict[H_l]
422
423
424
# In[23]:
425
426
# El
427
vdict[g_tw] = eq_gtw.rhs().subs(vdict)
428
vdict[C_wa] = eq_Cwl.rhs()(P_wl = P_wa, T_l = T_a).subs(vdict)
429
vdict[P_wl] = eq_Pwl.rhs().subs(vdict)
430
vdict[C_wl] = eq_Cwl.rhs().subs(vdict)
431
vdict[E_lmol] = eq_Elmol.rhs().subs(vdict)
432
vdict[E_l] = eq_El.rhs().subs(eq_Elmol).subs(vdict)
433
vdict[E_l]
434
435
436
# Now, we have a dictionary with $E_l$, $H_l$ and $R_{ll}$ as functions of leaf temperature ($T_l$) only. At steady state, [eq_Rs_enbal](#{eq_Rs_enbal}) must be satisfied, so we will substitute the above dictionary into eq_Rs_enbal, subtract $R_s$ and do a numerical search for the root of the equation to obtain steady-state leaf temperature:
437
438
# In[24]:
439
440
# Numerical search for steady-state Tl
441
vdict[T_l] = find_root((eq_Rs_enbal - R_s).rhs().subs(vdict), 273, 373)
442
vdict[T_l]
443
444
445
# Below, we define a function that performs all the above calculations given a dictionary with the instantaneous forcing:
446
447
# In[25]:
448
449
def fun_SS(vdict1):
450
'''
451
Steady-state T_l, R_ll, H_l and E_l under forced conditions.
452
Parameters are given in a dictionary (vdict) with the following entries:
453
a_s, a_sh, L_l, P_a, P_wa, R_s, Re_c, T_a, g_sw, v_w
454
'''
455
vdict = vdict1.copy()
456
457
# Nusselt number
458
vdict[nu_a] = eq_nua.rhs().subs(vdict)
459
vdict[Re] = eq_Re.rhs().subs(vdict)
460
vdict[Nu] = eq_Nu_forced_all.rhs().subs(vdict)
461
462
# h_c
463
vdict[k_a] = eq_ka.rhs().subs(vdict)
464
vdict[h_c] = eq_hc.rhs().subs(vdict)
465
466
# gbw
467
vdict[D_va] = eq_Dva.rhs().subs(vdict)
468
vdict[alpha_a] = eq_alphaa.rhs().subs(vdict)
469
vdict[rho_a] = eq_rhoa.rhs().subs(vdict)
470
vdict[Le] = eq_Le.rhs().subs(vdict)
471
vdict[g_bw] = eq_gbw_hc.rhs().subs(vdict)
472
473
# Hl, Rll
474
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
475
vdict[H_l] = eq_Hl.rhs().subs(vdict)
476
477
# El
478
vdict[g_tw] = eq_gtw.rhs().subs(vdict)
479
vdict[C_wa] = eq_Cwl.rhs()(P_wl = P_wa, T_l = T_a).subs(vdict)
480
vdict[P_wl] = eq_Pwl.rhs().subs(vdict)
481
vdict[C_wl] = eq_Cwl.rhs().subs(vdict)
482
vdict[E_lmol] = eq_Elmol.rhs().subs(vdict)
483
vdict[E_l] = eq_El.rhs().subs(eq_Elmol).subs(vdict)
484
485
# Tl
486
try:
487
vdict[T_l] = find_root((eq_Rs_enbal - R_s).rhs().subs(vdict), 273, 373)
488
except:
489
print 'too many unknowns for finding T_l: ' + str((eq_Rs_enbal - R_s).rhs().subs(vdict).args())
490
491
# Re-inserting T_l
492
Tlss = vdict[T_l]
493
for name1 in [C_wl, P_wl, R_ll, H_l, E_l, E_lmol]:
494
vdict[name1] = vdict[name1].subs(T_l = Tlss)
495
496
# Test for steady state
497
if n((E_l + H_l + R_ll - R_s).subs(vdict))>1.:
498
return 'error in energy balance: El + Hl + Rll - R_s = ' + str(n((E_l + H_l + R_ll - R_s).subs(vdict)))
499
return vdict
500
501
502
# In[26]:
503
504
# Test
505
vdict = cdict.copy()
506
#vdict= {}
507
vdict[a_s] = 1.0 # one sided stomata
508
vdict[g_sw] = 0.01
509
vdict[T_a] = 273 + 25.5
510
vdict[T_w] = vdict[T_a] # Wall temperature equal to air temperature
511
vdict[P_a] = 101325
512
rha = 1
513
vdict[P_wa] = rha*eq_Pwl.rhs()(T_l = T_a).subs(vdict)
514
vdict[L_l] = 0.03
515
vdict[Re_c] = 3000
516
vdict[R_s] = 600
517
vdict[v_w] = 1
518
resdict = fun_SS(vdict)
519
520
fun_dict_print(resdict)
521
522
523
# ### Calculation using known $T_l$
524
# If leaf temperature ($T_l$) is known (e.g. measured), but stomatal conductance $g_{sw}$ is not known, we can still calculate $H_l$ and $R_{ll}$, and then obtain $E_l$ from the energy balance equation:
525
526
# In[27]:
527
528
eq_El_enbal = solve(eq_Rs_enbal, E_l)[0]
529
units_check(eq_El_enbal)
530
531
532
# In[28]:
533
534
# Test with known Tl but no g_sw
535
vdict = cdict.copy()
536
vdict[a_s] = 1.0 # one sided stomata
537
538
vdict[T_a] = 273 + 25.5
539
vdict[T_w] = vdict[T_a] # Wall temperature equal to air temperature
540
vdict[P_a] = 101325
541
rha = 1
542
vdict[P_wa] = rha*eq_Pwl.rhs()(T_l = T_a).subs(vdict)
543
vdict[L_l] = 0.03
544
vdict[Re_c] = 3000
545
vdict[R_s] = 600
546
vdict[v_w] = 1
547
548
vdict[C_wa] = eq_Cwl.rhs()(P_wl = P_wa, T_l = T_a).subs(vdict)
549
vdict[nu_a] = eq_nua.rhs().subs(vdict)
550
vdict[Re] = eq_Re.rhs().subs(vdict)
551
vdict[Nu] = eq_Nu_forced_all.rhs().subs(vdict)
552
vdict[k_a] = eq_ka.rhs().subs(vdict)
553
vdict[h_c] = eq_hc.rhs().subs(vdict)
554
555
556
vdict[T_l] = 305.65
557
vdict[H_l] = eq_Hl.rhs().subs(vdict)
558
vdict[R_ll] = eq_Rll.rhs().subs(vdict)
559
560
eq_El_enbal.subs(vdict)
561
562
563
# # Saving definitions to separate file
564
# In the below, we save the definitions and variables to separate files in the /temp directory, one with the extension .sage, from which we can selectively load functions using
565
# `%load fun_name filenam.sage`
566
# and one with the extension .sobj, to be loaded elsewhere using
567
# `load_session()`
568
569
# In[29]:
570
571
fun_export_ipynb('leaf_enbalance_eqs', 'temp/')
572
save_session('temp/leaf_enbalance_eqs')
573
574
575
# # Table of symbols
576
577
# In[30]:
578
579
# Creating dictionary to substitute names of units with shorter forms
580
var('m s J Pa K kg mol')
581
subsdict = {meter: m, second: s, joule: J, pascal: Pa, kelvin: K, kilogram: kg, mole: mol}
582
var('N_Re_L N_Re_c N_Le N_Nu_L N_Gr_L N_Sh_L')
583
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}
584
dict_varold = {v: k for k, v in dict_varnew.iteritems()}
585
variables = sorted([str(variable.subs(dict_varnew)) for variable in udict.keys()],key=str.lower)
586
tableheader = [('Variable', 'Description (value)', 'Units')]
587
tabledata = [('Variable', 'Description (value)', 'Units')]
588
for variable1 in variables:
589
variable2 = eval(variable1).subs(dict_varold)
590
variable = str(variable2)
591
tabledata.append((eval(variable),docdict[eval(variable)],fun_units_formatted(variable)))
592
593
table(tabledata, header_row=True)
594
595
596
# In[ ]:
597
598
599
600
601