📚 The CoCalc Library - books, templates and other resources
License: OTHER
1# coding: utf-823# # Equations to derive leaf energy balance components from wind tunnel measurements and compare against leaf model</h1>4#5#67# In[1]:89get_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 from other worksheets\nload('temp/Worksheet_setup.sage')\nload_session('temp/leaf_enbalance_eqs.sobj')\nfun_loadvars(dict_vars) # any variables defined using var2() are saved with their attributes in dict_vars. Here we re-define them based on dict_vars from the other worksheet.")101112# In[2]:1314# %load -s fun_SS 'temp/leaf_enbalance_eqs.sage'15def fun_SS(vdict1):16'''17Steady-state T_l, R_ll, H_l and E_l under forced conditions.18Parameters are given in a dictionary (vdict) with the following entries:19a_s, a_sh, L_l, P_a, P_wa, R_s, Re_c, T_a, g_sw, v_w20'''21vdict = vdict1.copy()2223# Nusselt number24vdict[nu_a] = eq_nua.rhs().subs(vdict)25vdict[Re] = eq_Re.rhs().subs(vdict)26vdict[Nu] = eq_Nu_forced_all.rhs().subs(vdict)2728# h_c29vdict[k_a] = eq_ka.rhs().subs(vdict)30vdict[h_c] = eq_hc.rhs().subs(vdict)3132# gbw33vdict[D_va] = eq_Dva.rhs().subs(vdict)34vdict[alpha_a] = eq_alphaa.rhs().subs(vdict)35vdict[rho_a] = eq_rhoa.rhs().subs(vdict)36vdict[Le] = eq_Le.rhs().subs(vdict)37vdict[g_bw] = eq_gbw_hc.rhs().subs(vdict)3839# Hl, Rll40vdict[R_ll] = eq_Rll.rhs().subs(vdict)41vdict[H_l] = eq_Hl.rhs().subs(vdict)4243# El44vdict[g_tw] = eq_gtw.rhs().subs(vdict)45vdict[C_wa] = eq_Cwl.rhs()(P_wl = P_wa, T_l = T_a).subs(vdict)46vdict[P_wl] = eq_Pwl.rhs().subs(vdict)47vdict[C_wl] = eq_Cwl.rhs().subs(vdict)48vdict[E_lmol] = eq_Elmol.rhs().subs(vdict)49vdict[E_l] = eq_El.rhs().subs(eq_Elmol).subs(vdict)5051# Tl52try:53vdict[T_l] = find_root((eq_Rs_enbal - R_s).rhs().subs(vdict), 273, 373)54except:55print 'too many unknowns for finding T_l: ' + str((eq_Rs_enbal - R_s).rhs().subs(vdict).args())5657# Re-inserting T_l58Tlss = vdict[T_l]59for name1 in [C_wl, P_wl, R_ll, H_l, E_l, E_lmol]:60vdict[name1] = vdict[name1].subs(T_l = Tlss)6162# Test for steady state63if n((E_l + H_l + R_ll - R_s).subs(vdict))>1.:64return 'error in energy balance: El + Hl + Rll - R_s = ' + str(n((E_l + H_l + R_ll - R_s).subs(vdict)))65return vdict666768# In[27]:6970# Test717273# In[3]:7475# Test76vdict = cdict.copy()77vdict[a_s] = 1.0 # one sided stomata78vdict[g_sw] = 0.0179vdict[T_a] = 273 + 25.580vdict[T_w] = vdict[T_a] # Wall temperature equal to air temperature81vdict[P_a] = 10132582rha = 0.583vdict[P_wa] = rha*eq_Pwl.rhs()(T_l = T_a).subs(vdict)84vdict[L_l] = 0.0385#vdict[L_A] = vdict[L_l]^286vdict[Re_c] = 300087vdict[R_s] = 0.88#vdict[Q_in] = 089vdict[v_w] = 19091dict_print(fun_SS(vdict))929394# ## Gas and energy exchange in a leaf chamber95# Calculations based on leaf_capacitance_steady_state1. However, following the LI-6400XT user manual (Eq. 17-3), we replace the air temperature by wall temperature in the calculation of the net longwave balance of the leaf, as wall temperature can be measured in the chamber. Following the same equation, we also add the leaf thermal emissivity of 0.95 (P. 17-3).96# **Note that in order to measure sensible heat flux from the leaf, wall temperature must be equal to air temperature!**9798# In[4]:99100width = 0.05101height = 0.03102volume = 310/(100^3)103print 'Volume = ' + str((volume*1000).n()) + ' l'104105print 'min flow rate for flushing = ' + str((volume*3/100^3/60).n()) + ' m3/s'106print 'min flow rate for flushing = ' + str((volume*3*1000).n()) + ' l/min'107print 'flow rate for 1 m/s direct wind = ' + str(width*height*1) + ' m3/s'108print 'flow rate for 1 m/s direct wind = ' + str(width*height*1*1000*60) + ' l/m'109print 'flow rate for 5 m/s direct wind = ' + str(width*height*5) + ' m3/s'110print 'flow rate for 5 m/s direct wind = ' + str(width*height*5*1000*60) + ' l/m'111112113# In[5]:114115width = 0.05116height = 0.03117volume = 400/(100^3)118print 'Volume = ' + str((volume*1000).n()) + ' l'119120print 'min flow rate for flushing = ' + str((volume*3/100^3/60).n()) + ' m3/s'121print 'min flow rate for flushing = ' + str((volume*3*1000).n()) + ' l/min'122print 'flow rate for 1 m/s direct wind = ' + str(width*height*1) + ' m3/s'123print 'flow rate for 1 m/s direct wind = ' + str(width*height*1*1000*60) + ' l/m'124125126# <h2>Chamber insulation material</h2>127128# In[6]:129130var2('c_pi', 'Heat capacity of insulation material', joule/kilogram/kelvin, latexname='c_{pi}')131var2('lambda_i', 'Heat conductivity of insulation material', joule/second/meter/kelvin)132var2('rho_i', 'Density of insulation material', kilogram/meter^3)133var2('L_i', 'Thickness of insulation material', meter)134var2('A_i', 'Conducting area of insulation material', meter^2)135var2('Q_i', 'Heat conduction through insulation material', joule/second)136var2('dT_i', 'Temperature increment of insulation material', kelvin)137138139# In[7]:140141assumptions(c_pi)142143144# In[8]:145146eq_Qi = Q_i == dT_i*lambda_i*A_i/L_i147units_check(eq_Qi)148149150# In[9]:151152eq_Li = solve(eq_Qi, L_i)[0]153units_check(eq_Li)154155156# In[10]:157158# The amount of heat absorbed by the insulation material per unit area to increase the wall temperature by the same amount as dT_i for given heat flux Q_i159units_check(c_pi*rho_i*dT_i*L_i)160161162# In[11]:163164(c_pi*rho_i*dT_i*L_i).subs(eq_Li)165166167# In[12]:168169# From http://www.sager.ch/default.aspx?navid=25, PIR170vdict = {}171vdict[lambda_i] = 0.022172vdict[c_pi] = 1400173vdict[rho_i] = 30174(c_pi*rho_i*dT_i*L_i).subs(eq_Li).subs(vdict)(A_i = 0.3, dT_i = 0.1, Q_i = 0.01)175176177# In[13]:178179# From http://www.sager.ch/default.aspx?navid=25, Sagex 15180vdict = {}181vdict[lambda_i] = 0.038182vdict[c_pi] = 1400183vdict[rho_i] = 15184(c_pi*rho_i*dT_i*L_i).subs(eq_Li).subs(vdict)(A_i = 0.3, dT_i = 0.1, Q_i = 0.01)185186187# In[14]:188189units_check(lambda_i*A_i*dT_i*L_i)190191192# In[15]:193194# Assuming a 30x10x5 cm chamber, how thick would the insulation have to be in order to lose195# less than 0.01 W heat for 0.1 K dT_i?196eq_Li(A_i = 0.3*0.1*2 + 0.3*0.05*2, dT_i = 0.1, Q_i = 0.01).subs(vdict)197198199# In[16]:200201# From http://www.sager.ch/default.aspx?navid=25, Sagex 30202vdict = {}203vdict[lambda_i] = 0.033204vdict[c_pi] = 1400205vdict[rho_i] = 30206(c_pi*rho_i*dT_i*L_i).subs(eq_Li).subs(vdict)(A_i = 0.3, dT_i = 0.1, Q_i = 0.01)207208209# ## Leaf radiation balance210211# In[17]:212213# Additional variables214var2('alpha_l', 'Leaf albedo, fraction of shortwave radiation reflected by the leaf', watt/watt)215var2('R_d', 'Downwelling global radiation', joule/second/meter^2)216var2('R_la', 'Longwave radiation absorbed by leaf', joule/second/meter^2, latexname='R_{la}')217var2('R_ld', 'Downwards emitted/reflected global radiation from leaf', joule/second/meter^2, latexname='R_{ld}')218var2('R_lu', 'Upwards emitted/reflected global radiation from leaf', joule/second/meter^2, latexname='R_{lu}')219var2('R_u', 'Upwelling global radiation', joule/second/meter^2)220var2('S_a', 'Radiation sensor above leaf reading', joule/second/meter^2)221var2('S_b', 'Radiation sensor below leaf reading', joule/second/meter^2)222var2('S_s', 'Radiation sensor beside leaf reading', joule/second/meter^2)223224225# ### Measuring radiative exchange226#227# <p>The leaf is exposed to downwelling radiation ($R_d$) originating from shortwave irradiance entering through the glass window plus the longwave irradiance transmitted througha and emitted by the glass window, plus the upwelling radiation ($R_u$) emitted by the bottom glass window.</p>228# <p>The leaf itself reflects some of the radiation in both direction and emits its own black body longwave radiation. The sum of refelcted and emitted radiation away from the leaf is denoted as $R_{lu}$ and $R_{ld}$ for upward and downwards respectively. We have three net radiation sensors in place, one above the leaf measuring $S_a$, one below the leaf measureing $S_b$ and one at the same level beside the leaf measureing $S_s$. These sensor measure:</p>229# <p><img style="float: right;" src="figures/Leaf_radbalance.png" alt="" width="400" height="300" /></p>230# <p>$S_a = R_d - R_{lu}$</p>231# <p>$S_b = R_{ld} - R_u$</p>232# <p>$S_s = R_d - R_u$</p>233# <p>This leaves us with 3 equations with 4 unknows, so we either have to assume that $R_{lu} = R_{ld}$, assuming that both sides of the leaf have the same temperature or $R_u = 0$ to solve the algebraic problem. In daylight, $R_d >> R_u$, so this assumption should not lead to a big bias, however this would imply that $S_b = R_{ld}$, which is certainly incorrect.</p>234# <p>Unfortunately, the assumption $R_{lu} = R_{ld}$ does not help solve the problem as it just implies that $S_s = S_a + S_b$:</p>235236# In[18]:237238eq_Rs_Rd = R_s == (1-alpha_l)*R_d239eq_Sa = S_a == R_d - R_lu240eq_Sb = S_b == R_ld - R_u241eq_Ss = S_s == R_d - R_u242243244# In[19]:245246# Assuming R_lu = R_ld247eq_assRldRlu = R_ld == R_lu248solve([eq_Sa, eq_Sb.subs(eq_assRldRlu), eq_Ss], R_d, R_lu, R_u)249250251# In[20]:252253# More specifically,254eq1 = solve(eq_Sa, R_d)[0]255eq2 = solve(eq_Sb, R_ld)[0].subs(eq_assRldRlu)256eq3 = solve(eq_Ss, R_u)[0]257solve(eq1.subs(eq2).subs(eq3), S_s)258259260# In[21]:261262# Assuming that R_u = 0263eq_assRu0 = R_u == 0264soln = solve([eq_Sa, eq_Sb, eq_Ss, eq_assRu0], R_d, R_lu, R_ld, R_u)265print soln266267268# In[22]:269270#eq_Rd = soln[0][0]271#eq_Rlu = soln[0][1]272#eq_Rld = soln[0][2]273#eq_Rlu274275276# <p>However, what we can do in any case is to quantify the net radiative energy absorbed by the leaf as</p>277# <p>$\alpha_l R_s - R_{ll} = S_a - S_b$:</p>278279# In[23]:280281# Leaf radiation balance282eq_Rs_Rll = R_s - R_ll == R_d + R_u - R_lu - R_ld283eq_Rbalance = R_s - R_ll == S_a - S_b284285286# In[24]:287288solve([eq_Sa, eq_Sb, eq_Ss, R_d + R_u - R_lu - R_ld == S_a - S_b], R_d, R_lu, R_ld, R_u)289290291# ## Leaf water vapour exchange and energy balace292# The leaf water vapour exchange and energy balance equations were imported from [leaf_enbalance_eqs](Leaf_enbalance_eqs.ipynb). Here we will use an additional equation to estimate the thickness of the leaf boundary layer and get a feeling for the minimum distance between leaf and sensors to avoid interference with the boundary layer conditions.293294# In[25]:295296# Blasius solution for BL thickness (http://en.wikipedia.org/wiki/Boundary-layer_thickness)297var2('B_l', 'Boundary layer thickness', meter)298vdict = cdict.copy()299Ta = 300300vdict[T_a] = Ta301vdict[T_l] = Ta302vdict[L_l] = 0.15303vdict[v_w] = 0.5304vdict[Re_c] = 3000305vdict[a_s] = 1306vdict[P_a] = 101325307vdict[P_wa] = 0308eq_Bl = B_l == 4.91*sqrt(nu_a*L_l/v_w)309print eq_Bl.subs(eq_nua).subs(vdict)310eq_gbw_hc.subs(eq_hc).subs(eq_Nu_forced_all).subs(eq_Re).subs(eq_rhoa).subs(eq_Le).subs(eq_Dva).subs(eq_alphaa, eq_nua, eq_ka).subs(vdict)311312313# In[26]:314315vdict[L_l] = 0.03316vdict[v_w] = 8317print eq_Bl.subs(eq_nua).subs(vdict)318eq_gbw_hc.subs(eq_hc).subs(eq_Nu_forced_all).subs(eq_Re).subs(eq_rhoa).subs(eq_Le).subs(eq_Dva).subs(eq_alphaa, eq_nua, eq_ka).subs(vdict)319320321# In[27]:322323# How does B_l scale with wind speed?324vdict[v_w] = v_w325P = plot(eq_Bl.rhs().subs(eq_nua).subs(vdict), (v_w, 0.5,5))326P.axes_labels(['Wind speed (m s$^{-1}$)', 'Boundary layer thickness (m)'])327P328329330# In[28]:331332# Maximum sensible heat flux of a 3x3 cm leaf irradiated by 600 W/m2333600*0.03^2334335336# <h1>Chamber mass and energy balance</h1>337# <p>Usually, we know the volumetric inflow into the chamber, so to convert to molar inflow (mol s$^{-1}$), we will use the ideal gas law: $P_a V_c = n R_{mol} T_{in}$, where $n$ is the amount of matter in the chamber (mol). To convert from a volume to a flow rate, we replace $V_c$ by $F_{in,v}$. Note that partial pressures of dry air and vapour are additive, such that</p>338# <p>$P_a = P_w + P_d$</p>339# <p>However, the volumes are not additive, meaning that:</p>340# <p>$P_d V_a = n_d R_{mol} T_{a}$</p>341# <p>$(P_a - P_d) V_a = n_a R_{mol} T_{a}$</p>342# <p>i.e. we use the same volume ($V_a$) for both the vapour and the dry air. This is because both the vapour and the dry air are well mixed and occupy the same total volume. Their different amounts are expressed in their partial pressures. If we wanted to calculate the partial volumes they would take up in isolation from each other, we would need to specify at which pressure this volume is taken up and if we used the same pressure for both (e.g. $P_a$), we would obtain a volume fraction for water vapour equivalent to its partial pressure fraction in the former case.</p>343# <p>Therefore, we will distinguish the molar flow rates of water vapour ($F_{in,mol,v}$) and dry air ($F_{in,mol,a}$) but they share a common volumetric flow rate ($F_{in,v}$).</p>344345# In[29]:346347var2('W_c', 'Chamber width', meter)348var2('L_c', 'Chamber length', meter)349var2('H_c', 'Chamber height', meter)350var2('V_c', 'Chamber volume', meter^3)351var2('n_c', 'molar mass of gas in chamber', mole)352var2('F_in_v', 'Volumetric flow rate into chamber', meter^3/second, latexname='F_{in,v}')353var2('F_in_mola', 'Molar flow rate of dry air into chamber', mole/second, latexname='F_{in,mol,a}')354var2('F_in_molw', 'Molar flow rate of water vapour into chamber', mole/second, latexname='F_{in,mol,w}')355var2('F_out_mola', 'Molar flow rate of dry air out of chamber', mole/second, latexname='F_{out,mol,a}')356var2('F_out_molw', 'Molar flow rate of water vapour out of chamber', mole/second, latexname='F_{out,mol,w}')357var2('F_out_v', 'Volumetric flow rate out of chamber', meter^3/second, latexname='F_{out,v}')358var2('T_d', 'Dew point temperature of incoming air', kelvin)359var2('T_in', 'Temperature of incoming air', kelvin, latexname='T_{in}')360var2('T_out', 'Temperature of outgoing air (= chamber T_a)', kelvin, latexname='T_{out}')361var2('T_room', 'Lab air temperature', kelvin, latexname='T_{room}')362var2('P_w_in', 'Vapour pressure of incoming air', pascal, latexname='P_{w,in}')363var2('P_w_out', 'Vapour pressure of outgoing air', pascal, latexname='P_{w,out}')364var2('R_H_in', 'Relative humidity of incoming air', latexname='R_{H,in}')365var2('L_A', 'Leaf area', meter^2)366367368# In[30]:369370eq_V_c = fun_eq(V_c == W_c*L_c*H_c)371eq_F_in_mola = fun_eq(F_in_mola == (P_a - P_w_in)*F_in_v/(R_mol*T_in))372eq_F_in_molw = fun_eq(F_in_molw == (P_w_in)*F_in_v/(R_mol*T_in))373eq_F_out_mola = fun_eq(F_out_mola == (P_a - P_w_out)*F_out_v/(R_mol*T_out))374eq_F_out_molw = fun_eq(F_out_molw == (P_w_out)*F_out_v/(R_mol*T_out))375eq_F_out_v = fun_eq(F_out_v == (F_out_mola + F_out_molw)*R_mol*T_out/P_a)376377378# <p>At steady state, $F_{out,mola} = F_{in,mola}$ and $F_{out,molw} = F_{in,molw} + E_{l,mol} L_A$. In the presence of evaporation, we can simply add Elmol to get F_out_v as a function of F_in_v</p>379# <p>Assuming that the pressure inside the chamber is constant and equal to the pressure outside, we compute the change in volumetric outflow due to a change in temperature and due to the input of water vapour by transpiration as:</p>380381# In[31]:382383eq_Foutv_Finv_Tout = eq_F_out_v.subs(F_out_mola = F_in_mola, F_out_molw = F_in_molw + E_lmol*L_A).subs(eq_F_in_mola, eq_F_in_molw).simplify_full()384units_check(eq_Foutv_Finv_Tout)385386387# In[32]:388389eq_Foutv_Finv_Tout390391392# In[33]:393394# Other way, using molar in and outflow395eq_Foutmolw_Finmolw_Elmol = F_out_molw == (F_in_molw + E_lmol*L_A)396units_check(eq_Foutmolw_Finmolw_Elmol)397398399# In[ ]:400401402403404# <h2>Change in air temperature</h2>405# <p>See also <a href="http://www.engineeringtoolbox.com/mixing-humid-air-d_694.html">http://www.engineeringtoolbox.com/mixing-humid-air-d_694.html</a> and <a href="http://www.engineeringtoolbox.com/enthalpy-moist-air-d_683.html">http://www.engineeringtoolbox.com/enthalpy-moist-air-d_683.html</a> for reference.</p>406# <p>We will assume that the air entering the chamber mixes with the air inside the chamber at constant pressure, i.e. the volume of the mixed air becomes the chamber volume plus the volume of the air that entered. The temperature of the mixed air is then the sum of their enthalpies plus the heat added by the fan and by sensible heaflux, divided by the sum of their heat capacities. The addition of water vapour through evaporation by itself should not affect the air temperature, but the volume of the air.</p>407# <p> </p>408# <p>Alternatively, we could assume that a given amount of air is added to a constant volume, leading to an increase in pressure. Addition of water vapour would lead to an additional increase in pressure. In addition, addition/removal of heat by sensible heat flux and the chamber fan would affect both temperature and pressure.To calculate both temperature and pressure, we need to track the internal energy in addition to the mole number. According to Eq. 6.1.3 in Kondepudi & Prigogine (2006), the internal energy of an ideal gas is given by (see also Eq. 2.2.15 in Kondepuid & Prigogine):</p>409# <p>$U = N(U_0 + C_v T)$</p>410# <p>where</p>411# <p>$U_0 = M c^2$</p>412# <p>The relation between molar heat capacities at constant pressure and volume is given as :</p>413# <p>$C_v = C_p - R_{mol}$</p>414# <p>Any heat exchanged by sensible heat flux, across the walls and the fan can be added to total $U$, and then knowledge about total $C_v$ will let us calculate air temperature inside the chamber. After that, we can use the ideal gas law to calculate volume or pressure, depending in which of those we fixed:</p>415# <p>$P V = n R T$</p>416# <p> </p>417# <p>The difference in water vapour pressure and temperature between the incoming and outgoing air is a function of the latent and sensible heat flux, as well as the flow rate. The heat fluxes associated with the incoming and outgoing air are $T_{in} (c_{pa} F_{in,mola} M_{air} + c_{pv} F_{in,molw} M_{w})$ and $T_{out} (c_{pa} F_{out,mola} M_{air} + c_{pv} F_{out,molw} M_{w})$ respectively. The difference between the two plus any additional heat sources/sinks ($Q_{in}$) equals the sensible heat flux at constant air temperature (steady state).</p>418419# In[34]:420421units_check(eq_F_out_v)422423424# In[35]:425426var2('M_air', 'Molar mass of air (kg mol-1)', kilogram/mole, value = 0.02897, latexname='M_{air}') # http://www.engineeringtoolbox.com/molecular-mass-air-d_679.html427var2('c_pv', 'Specific heat of water vapour at 300 K', joule/kilogram/kelvin, latexname = 'c_{pv}', value = 1864) # source: http://www.engineeringtoolbox.com/water-vapor-d_979.html428var2('Q_in', 'Internal heat sources, such as fan', joule/second, latexname = 'Q_{in}')429eq_chamber_energy_balance = 0 == H_l*L_A + Q_in + T_in*(c_pa*M_air*F_in_mola + c_pv*M_w*F_in_molw) - (T_out*(c_pa*M_air*F_out_mola + c_pv*M_w*F_out_molw)); show(eq_chamber_energy_balance)430eq_Hl_enbal = solve(eq_chamber_energy_balance.subs(F_out_mola == F_in_mola, F_out_molw == F_in_molw + L_A*E_lmol), H_l)[0].expand()431print units_check(eq_Hl_enbal)432433434# In[36]:435436soln = solve(eq_chamber_energy_balance.subs(eq_Foutmolw_Finmolw_Elmol, F_out_mola == F_in_mola), T_out)437print soln438eq_Tout_Finmol_Tin = soln[0]439units_check(eq_Tout_Finmol_Tin).simplify_full().convert().simplify_full()440441442# In[37]:443444eq_Tout_Finv_Tin = eq_Tout_Finmol_Tin.subs(eq_F_in_mola, eq_F_in_molw).simplify_full()445print eq_Tout_Finv_Tin446show(eq_Tout_Finv_Tin)447units_check(eq_Tout_Finv_Tin).simplify_full().convert()448449450# In[ ]:451452453454455# <p>The molar outflux of dry air equals the molar influx of dry air, while the molar outflux of water vapour equals the molar influx plus the evaporation rate. The sum of both can be used to obtain the volumetric outflow:</p>456457# In[38]:458459# F_out_v as function of F_inv and T_in460eq1 = (eq_F_out_molw + eq_F_out_mola).simplify_full(); show(eq1)461eq2 = eq1.subs(F_out_mola == F_in_mola, eq_Foutmolw_Finmolw_Elmol).subs(eq_F_in_mola, eq_F_in_molw); show(eq2)462soln = solve(eq2,F_out_v); print soln463eq_Foutv_Finv = soln[0]; show(eq_Foutv_Finv)464units_check(eq_Foutv_Finv)465466467# In[39]:468469eq_Foutv_Finv470471472# In[40]:473474eq_Foutv_Finv_Tout475476477# In[41]:478479eq_Tout_Finmol_Tin480481482# In[42]:483484# Finding the T_in that would balance sensible heat release by the plate for given F_inv485assume(F_in_v > 0)486assume(F_out_v > 0)487assume(E_lmol >=0)488show(eq_chamber_energy_balance)489soln = solve(eq_chamber_energy_balance.subs(F_out_mola == F_in_mola).subs(eq_Foutmolw_Finmolw_Elmol).subs(eq_F_in_mola, eq_F_in_molw), T_in)490print soln491eq_T_in_ss = soln[0]492show(eq_T_in_ss)493494495# In[43]:496497# Calculating Q_in from T_in, F_in_v and T_out498soln = solve(eq_T_in_ss,Q_in)499print soln500eq_Qin_Tin_Tout = soln[0]501502503# In[44]:504505# Calculating H_l from T_in, F_in_v and T_out506soln = solve(eq_T_in_ss,H_l)507print soln508eq_Hl_Tin_Tout = soln[0]509eq_Hl_Tin_Tout.show()510511512# In[45]:513514# Calculating H_l from T_in, T_out and Fmol515soln = solve(eq_chamber_energy_balance.subs(F_out_mola == F_in_mola), H_l)516print soln517eq_Hl_Tin_Tout_Fmol = soln[0].simplify_full()518eq_Hl_Tin_Tout_Fmol.show()519520521# <h2>Calculation of volumetric flow rate based on Cellkraft measurements</h2>522# <p>Cellcraft uses Arden-Buck equation to convert between vapour pressure and dew point (<a href="http://en.wikipedia.org/wiki/Arden_Buck_Equation">http://en.wikipedia.org/wiki/Arden_Buck_Equation</a>).<br />The air flow rate is given by the Cellkraft humidifier in l/min, but it refers to dry air at 0 $^o$C and 101300 Pa.</p>523# <p>We will use the reported dew point temperature to obtain the vapour pressure of the air coming out from the Cellkraft humidifier, then the ideal gas law to obtain the molar flow of dry air, leading to three equations with three unknowns:</p>524# <p>$F_{\mathit{in}_{\mathit{mola}}} = \frac{F_{\mathit{in}_{\mathit{va}_{n}}} P_{r}}{{R_{mol}} T_{r}}$</p>525# <p>$F_{\mathit{in}_{v}} = \frac{{\left(F_{\mathit{in}_{\mathit{mola}}} + F_{\mathit{in}_{\mathit{molw}}}\right)} {R_{mol}} T_{\mathit{in}}}{P_{a}}$</p>526# <p>$F_{\mathit{in}_{\mathit{molw}}} = \frac{F_{\mathit{in}_{v}} P_{v_{\mathit{in}}}}{{R_{mol}} T_{\mathit{in}}}$</p>527528# In[46]:529530# Calculating vapour pressure in the incoming air from reported dew point by the Cellkraft humidifier531var2('T0', 'Freezing point in kelvin',kelvin, value = 273.15)532eq_Pwin_Tdew = P_w_in == 611.21*exp((18.678 - (T_d - T0)/234.5)*((T_d - T0)/(257.14-T0+T_d))) # c533list_Tdew = np.array(srange(-40,50,6))+273.25534list_Pwin = [eq_Pwin_Tdew.rhs()(T_d = dummy).subs(cdict) for dummy in list_Tdew]535print list_Pwin536P = plot(eq_Pwin_Tdew.rhs().subs(cdict), (T_d, 253,303), frame = True, axes = False, legend_label = 'Arden Buck')537P += plot(eq_Pwl.rhs().subs(cdict), (T_l, 253,303), color = 'red', linestyle = '--', legend_label = 'Clausius-Clapeyron')538P += list_plot(zip(list_Tdew,list_Pwin), legend_label = 'Cellcraft')539P.axes_labels(['Dew point (K)', 'Saturation vapour pressure (Pa)'])540P541542543# In[47]:544545eq_F_in_molw.show()546547548# In[48]:549550eq_Finv_Finmol = F_in_v == (F_in_mola + F_in_molw)*R_mol*T_in/P_a551units_check(eq_Finv_Finmol)552553554# In[49]:555556var2('F_in_va_n', 'Volumetric inflow of dry air at 0oC and 101325 Pa', meter^3/second, latexname='F_{in,v,a,n}')557var2('P_r', 'Reference pressure',pascal, value = 101325)558var2('T_r', 'Reference temperature', kelvin)559560eq_Finmola_Finva_ref = fun_eq(F_in_mola == F_in_va_n * P_r/(R_mol*T_r))561562563# <p>To get $F_{in,v}$ and $F_{in,mol,w}$, we will consider that:</p>564# <p>$P_d = P_a - P_w$</p>565# <p>$P_w F_{in,v} = F_{in,mol,w} R_{mol} T_{in}$</p>566# <p>$(P_a - P_w) F_{in,v} = F_{in,mol,a} R_{mol} T_{a}$</p>567568# In[50]:569570eq_Finmolw_Finv = F_in_molw == (P_w_in*F_in_v)/(R_mol*T_in)571print units_check(eq_Finmolw_Finv)572eq_Finv_Finmola = F_in_v == F_in_mola*R_mol*T_in/(P_a - P_w_in)573print units_check(eq_Finv_Finmola)574eq_Finmolw_Finmola_Pwa = fun_eq(eq_Finmolw_Finv.subs(eq_Finv_Finmola))575eq_Finv_Finva_ref = fun_eq(eq_Finv_Finmola.subs(eq_Finmola_Finva_ref))576577578# In[51]:579580vdict = cdict.copy()581vdict[F_in_va_n] = 10e-3/60 # 10 l/min reported by Cellkraft582vdict[T_d] = 273.15 + 10 # 10oC dew point583vdict[P_a] = 101325.584vdict[T_r] = 273.15585vdict[P_w_in] = eq_Pwin_Tdew.rhs().subs(vdict)586print vdict[P_w_in]587print vdict[F_in_va_n]588589vdict[T_in] = 273.15+0590inflow0 = eq_Finv_Finva_ref.rhs().subs(vdict)591print 'Volumentric flow at 0 oC: ' + str(inflow0) + ' m3/s'592593vdict[T_in] = 273.15+25594inflow25 = eq_Finv_Finva_ref.rhs().subs(vdict)595print 'Volumentric flow at 25 oC: ' + str(inflow25) + ' m3/s'596597598print '25oC/0oC: ' + str(inflow25/inflow0)599600vdict[T_in] = 273.15+25601vdict[P_w_in] = 0.602inflow25 = eq_Finv_Finva_ref.rhs().subs(vdict)603print 'Volumentric flow at 25 oC without added vapour: ' + str(inflow25) + ' m3/s'604605606# <h2>Vapour pressure</h2>607# <p>The water fluxes associated with the incoming and the outgoing air according to the ideal gas law are $P_{v,in} F_{in,v}/(R_{mol} T_{in})$ and $P_{v,out} F_{out,v}/(R_{mol} T_{out})$ respectively.</p>608609# In[52]:610611eq_Foutv_Finv_Tout.show()612613614# In[53]:615616eq_F_out_v.show()617618619# In[54]:620621eq_F_in_mola.subs(eq_Finv_Finva_ref).show()622623624# In[55]:625626eq_Finv_Finva_ref.show()627628629# In[56]:630631eq_F_in_molw.show()632eq_F_out_molw.show()633eq_Foutmolw_Finmolw_Elmol.show()634635636# In[57]:637638eq1 = eq_F_out_molw.rhs() == eq_Foutmolw_Finmolw_Elmol.rhs().subs(eq_F_in_molw)639eq1.show()640soln = solve(eq1, P_w_out)641eq_Pwout_Elmol = fun_eq(soln[0].subs(eq_Foutv_Finv_Tout.subs(eq_F_in_molw)).simplify_full())642units_check(eq_Pwout_Elmol)643644645# <p><span style="color: #ff0000;">It is a bit surprising that steady-state $P_{w_{out}}$ does not depend on $T_{out}$.</span></p>646647# In[58]:648649soln[0].subs(eq_Foutv_Finv_Tout.subs(eq_F_in_molw)).simplify_full().show()650soln[0].subs(eq_F_out_v).subs(F_out_mola = F_in_mola, F_out_molw = F_in_molw + E_lmol*L_A).simplify_full().show()651652653# <p><span style="color: #ff0000;">The above are equivalent, because $F_{in,v} P_a = (F_{in,mol,a} + F_{in,mol,w}) R_{mol} T_{in}$<br /></span></p>654655# In[59]:656657eq_Pwout_Elmol.subs(eq_Finv_Finva_ref).simplify_full().show()658659660# In[60]:661662show(soln[0])663show(eq_Foutv_Finv_Tout)664show(eq_F_in_molw)665666667# In[61]:668669show(soln[0].subs(eq_Foutv_Finv_Tout.subs(eq_F_in_molw)).simplify())670671672# In[62]:673674# T_out cancels out when the above is expanded675show(soln[0].subs(eq_Foutv_Finv_Tout.subs(eq_F_in_molw)).expand())676677678# <p>To convert from energetic to molar units, we need to divide $E_l$ by $\lambda_E M_w$:</p>679680# In[63]:681682eq_Elmol_El = E_lmol == E_l/(lambda_E*M_w)683print units_check(eq_Elmol_El)684eq_El_Elmol = E_l == E_lmol*lambda_E*M_w685686687# In[64]:688689# In order to keep P_w_out = P_wa = const., we need to adjust P_w_in accordingly.690soln = solve(eq_Pwout_Elmol, P_w_in)691eq_Pwin_Elmol = soln[0].simplify_full()692show(eq_Pwin_Elmol)693694695# In[65]:696697vdict = cdict.copy()698vdict[F_in_va_n] = 10e-3/60 # 10 l/min reported by Cellkraft699vdict[T_d] = 273.15 + 10 # 10oC dew point700vdict[P_a] = 101325.701vdict[T_r] = 273.15702vdict[P_w_in] = eq_Pwin_Tdew.rhs().subs(vdict)703print vdict[P_w_in]704print vdict[F_in_va_n]705706vdict[T_in] = 273.15+0707inflow0 = eq_Finv_Finva_ref.rhs().subs(vdict)708print 'Volumentric flow at 0 oC: ' + str(inflow0) + ' m3/s'709710vdict[T_in] = 273.15+25711inflow25 = eq_Finv_Finva_ref.rhs().subs(vdict)712vdict[F_in_v] = eq_Finv_Finva_ref.rhs().subs(vdict)713print 'Volumentric flow at 25 oC: ' + str(inflow25) + ' m3/s'714715716print '25oC/0oC: ' + str(inflow25/inflow0)717718vdict[T_in] = 273.15+25719vdict[P_w_in] = 0.720inflow25 = eq_Finv_Finva_ref.rhs().subs(vdict)721print 'Volumentric flow at 25 oC without added vapour: ' + str(inflow25) + ' m3/s'722723vdict[E_l] = 100. # assuming 100 W/m2 El724vdict[L_A] = 0.03^2725vdict[E_lmol] = eq_Elmol_El.rhs().subs(vdict)726vdict[T_out] = 273+20. # Assuming 20oC T in chamber727728eq_Pwout_Elmol.subs(vdict)729730731# <h2>Net radiation measurement</h2>732# <p>According to Incropera_fundamentals, Table 13.1, the view factor (absorbed fraction of radiation emitted by another plate) of a small plate of width $w_i$ at a distance $L$ from a parallel larger plate of width $w_j$ is calculated as:</p>733734# In[66]:735736var2('L_s', 'Width of net radiation sensor', meter)737var2('L_ls', 'Distance between leaf and net radiation sensor', meter)738var2('F_s', 'Fraction of radiation emitted by leaf, absorbed by sensor', 1)739Wi = L_s/L_ls740Wj = L_l/L_ls741eq_Fs = F_s == (sqrt((Wi + Wj)^2 + 4) - sqrt((Wj - Wi)^2 + 4))/(2*Wi)742units_check(eq_Fs)743744745# In[67]:746747vdict = cdict.copy()748vdict[L_l] = 0.03749vdict[L_s] = 0.01750print eq_Fs.rhs().subs(vdict)(L_ls = 0.01)751P = plot(eq_Fs.rhs().subs(vdict), (L_ls, 0.001, 0.02))752P.axes_labels(['Distance to leaf (m)', 'Fraction of radiation captured'])753P754755756# # Saving definitions to separate file757# 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 using758# `%load fun_name filenam.sage`759# and one with the extension .sobj, to be loaded elsewhere using760# `load_session()`761762# In[68]:763764fun_export_ipynb('leaf_chamber_eqs', 'temp/')765save_session('temp/leaf_chamber_eqs.sobj')766767768# # Table of symbols769770# In[69]:771772# Creating dictionary to substitute names of units with shorter forms773var('m s J Pa K kg mol')774subsdict = {meter: m, second: s, joule: J, pascal: Pa, kelvin: K, kilogram: kg, mole: mol}775var('N_Re_L N_Re_c N_Le N_Nu_L N_Gr_L N_Sh_L')776dict_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}777dict_varold = {v: k for k, v in dict_varnew.iteritems()}778variables = sorted([str(variable.subs(dict_varnew)) for variable in udict.keys()],key=str.lower)779tableheader = [('Variable', 'Description (value)', 'Units')]780tabledata = [('Variable', 'Description (value)', 'Units')]781for variable1 in variables:782variable2 = eval(variable1).subs(dict_varold)783variable = str(variable2)784tabledata.append((eval(variable),docdict[eval(variable)],fun_units_formatted(variable)))785786table(tabledata, header_row=True)787788789# In[ ]:790791792793794795