Skip to main content Link Search Menu Expand Document (external link)

Leaf Temperature

Table of contents
  1. Code
    1. Main program
    2. Aux. programs
  2. Output
    1. Text

Code

Main program

sp_10_02.m | View on GitHub
% Supplemental program 10.2

% -------------------------------------------------------------------------
% Calculate leaf temperature for different radiative forcing, wind speed,
% and stomatal conductance
% -------------------------------------------------------------------------

% Pass variables to other routines as global variables

global tfrz sigma g visc0 Dh0 Dv0 Dc0 mmh2o
global tair pref eair wind cpair rhomol
global gsw gbw gbh gbc emleaf dleaf
global tleaf qa rn lwrad sh lh

% Physical constants

tfrz = 273.15;            % Freezing point of water (K)
sigma = 5.67e-08;         % Stefan-Boltzmann constant (W/m2/K4)
g = 9.80616;              % Gravitational acceleration (m/s2)
visc0 = 13.3e-06;         % Kinematic viscosity at 0C and 1013.25 hPa (m2/s)
Dh0 = 18.9e-06;           % Molecular diffusivity (heat) at 0C and 1013.25 hPa (m2/s)
Dv0 = 21.8e-06;           % Molecular diffusivity (H2O) at 0C and 1013.25 hPa (m2/s)
Dc0 = 13.8e-06;           % Molecular diffusivity (CO2) at 0C and 1013.25 hPa (m2/s)
rgas = 8.31447;           % Universal gas constant (J/K/mol)
mmdry = 28.966 / 1000;    % Molecular mass of dry air (kg/mol)
mmh2o = 18.016 / 1000;    % Molecular mass of water vapor (kg/mol)
cpd = 1004.64;            % Specific heat of dry air at constant pressure (J/kg/K)
cpw = 1810;               % Specific heat of water vapor at constant pressure (J/kg/K)

% Waveband indices: 1 = visible. 2 = near-infrared

vis = 1;
nir = 2;

% Number of data points to simulate: 4 wind speeds * 2 stomatal conductance * 2 solar radiation

num = 4 * 2 * 2;

% Input variables

for p = 1:num

   tair(p) = tfrz + 35;                  % Air temperature (K)
   relhum(p) = 50;                       % Relative humidity (%)
   pref(p) = 101325;                     % Air pressure (Pa)
   irsky(p) = 300;                       % Atmospheric longwave radiation (W/m2)
   irgrd(p) = sigma * (tfrz + 39.95)^4;  % Ground longwave radiation (W/m2)

   % Set wind speed (m/s) to specific values

   if (p == 1 | p == 5 | p == 9 | p == 13)
      wind(p) = 0.01;  % Still air
   end
   if (p == 2 | p == 6 | p == 10 | p == 14)
      wind(p) = 0.1;   % Calm - smoke rises vertically
   end
   if (p == 3 | p == 7 | p == 11 | p == 15)
      wind(p) = 1.0;   % Light air - smoke drift indicates wind direction
   end
   if (p == 4 | p == 8 | p == 12 | p == 16)
      wind(p) = 5.0;   % Gentle breeze - leaves constantly moving and light flag extended
   end

   % Solar radiation (W/m2) for visible and near-infrared wavebands

   if (p <= 8)
      swsky(p,vis) = 0.5 * 1100;         % Full sun
      swsky(p,nir) = 0.5 * 1100;
   else
      swsky(p,vis) = 0.5 *  550;         % Cloudy
      swsky(p,nir) = 0.5 *  550;
   end

   % Albedo of ground surface for visible and near-infrared wavebands

   albsoi(p,vis) = 0.1;
   albsoi(p,nir) = 0.2;

   % Leaf input

   rhol(p,vis) = 0.1;   % Leaf reflectance
   rhol(p,nir) = 0.4;
   taul(p,vis) = 0.1;   % Leaf transmittance
   taul(p,nir) = 0.4;

   emleaf(p) = 0.98;     % Leaf emissivity
   dleaf(p) = 0.05;      % Leaf dimension (m)

   % Leaf stomatal conductance (mol H2O/m2/s)

   if ((p >= 1 & p <=4) | (p >= 9 & p <= 12))
      gsw(p) = 0;            % Only longwave and sensible heat. No latent heat
   end
   if ((p >= 5 & p <=8 | p >= 13 & p <= 16))
      gsw(p) = 0.4;          % Longwave, sensible heat, and latent heat
   end

end

% Derived quantities

for p = 1:num

   % esat    ! Saturation vapor pressure of air (Pa)
   % eair    ! Vapor pressure of air (Pa)
   % qair    ! Specific humidity (kg/kg)
   % rhomol  ! Molar density (mol/m3)
   % rhoair  ! Air density (kg/m3)
   % mmair   ! Molecular mass of air (kg/mol)
   % cpair   ! Specific heat of air at constant pressure (J/mol/K)

   [esat, desat] = satvap (tair(p)-tfrz);
   eair(p) = (relhum(p) / 100) * esat;
   qair(p) = mmh2o / mmdry * eair(p) / (pref(p) - (1 - mmh2o/mmdry) * eair(p));
   rhomol(p) = pref(p) / (rgas * tair(p));
   rhoair(p) = rhomol(p) * mmdry * (1 - (1 - mmh2o/mmdry) * eair(p) / pref(p));
   mmair(p) = rhoair(p) / rhomol(p);
   cpair(p) = cpd * (1 + (cpw/cpd - 1) * qair(p)) * mmair(p);

end

% Radiative forcing (W/m2): absorbed solar + absorbed longwave radiation

for p = 1:num

   swinc(p,vis) = swsky(p,vis) * (1 + albsoi(p,vis));
   swinc(p,nir) = swsky(p,nir) * (1 + albsoi(p,nir));

   qa(p) = swinc(p,vis) * (1 - rhol(p,vis) - taul(p,vis)) ...
         + swinc(p,nir) * (1 - rhol(p,nir) - taul(p,nir)) + emleaf(p) * (irsky(p) + irgrd(p));

end

% Leaf temperature and fluxes

for p = 1:num

   rn(p) = 0;           % Leaf net radiation (W/m2)
   lwrad(p) = 0;        % Longwave radiation emitted from leaf (W/m2)
   sh(p) = 0;           % Leaf sensible heat flux (W/m2)
   lh(p) = 0;           % Leaf latent heat flux (W/m2)
   gbh(p) = 0;          % Leaf boundary layer conductance, heat (mol/m2/s)
   gbw(p) = 0;          % Leaf boundary layer conductance, H2O (mol H2O/m2/s)
   gbc(p) = 0;          % Leaf boundary layer conductance, CO2 (mol CO2/m2/s)
   tleaf(p) = tair(p);  % Initial estimate leaf temperature (K)

   % Solve for leaf temperature and fluxes. Need to iterate because boundary
   % layer conductances depend on tleaf (for free convection)

   niter = 0;
   delta = 1e36;

   while (niter <= 100 & abs(delta) > 1e-06)

      % Increment iteration counter

      niter = niter + 1;

      % Save temperature from previous iteration

      tleaf_old = tleaf(p);

      % Leaf boundary layer conductances

      [x] = leaf_boundary_layer (p);

      % Leaf temperature and energy fluxes

      [x] = leaf_temperature (p);

      % Change in leaf temperature

      delta = tleaf(p) - tleaf_old;

   end
end

tleaf = tleaf - tfrz;
fprintf('qa = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',qa(1),qa(2),qa(3),qa(4),qa(5),qa(6),qa(7),qa(8))
fprintf('gsw = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',gsw(1),gsw(2),gsw(3),gsw(4),gsw(5),gsw(6),gsw(7),gsw(8))
fprintf('wind = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',wind(1),wind(2),wind(3),wind(4),wind(5),wind(6),wind(7),wind(8))
fprintf('tleaf = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',tleaf(1),tleaf(2),tleaf(3),tleaf(4),tleaf(5),tleaf(6),tleaf(7),tleaf(8))
fprintf('lwrad = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',lwrad(1),lwrad(2),lwrad(3),lwrad(4),lwrad(5),lwrad(6),lwrad(7),lwrad(8))
fprintf('sh = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',sh(1),sh(2),sh(3),sh(4),sh(5),sh(6),sh(7),sh(8))
fprintf('lh = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',lh(1),lh(2),lh(3),lh(4),lh(5),lh(6),lh(7),lh(8))

fprintf(' \n')

fprintf('qa = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',qa(9),qa(10),qa(11),qa(12),qa(13),qa(14),qa(15),qa(16))
fprintf('gsw = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',gsw(9),gsw(10),gsw(11),gsw(12),gsw(13),gsw(14),gsw(15),gsw(16))
fprintf('wind = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',wind(9),wind(10),wind(11),wind(12),wind(13),wind(14),wind(15),wind(16))
fprintf('tleaf = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',tleaf(9),tleaf(10),tleaf(11),tleaf(12),tleaf(13),tleaf(14),tleaf(15),tleaf(16))
fprintf('lwrad = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',lwrad(9),lwrad(10),lwrad(11),lwrad(12),lwrad(13),lwrad(14),lwrad(15),lwrad(16))
fprintf('sh = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',sh(9),sh(10),sh(11),sh(12),sh(13),sh(14),sh(15),sh(16))
fprintf('lh = %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n',lh(9),lh(10),lh(11),lh(12),lh(13),lh(14),lh(15),lh(16))

Aux. programs

leaf_boundary_layer.m | View on GitHub
function [x] = leaf_boundary_layer (p)

% ----------------------------------------------------------------------------
% Calculate leaf boundary layer conductances
% ----------------------------------------------------------------------------

% Global variables

global tfrz g visc0 Dh0 Dv0 Dc0
global gbh gbw gbc dleaf
global pref tair wind rhomol 
global tleaf

% Adjust diffusivity for temperature and pressure

fac = 101325 / pref(p) * (tair(p) / tfrz)^1.81;

visc = visc0 * fac;    % Kinematic viscosity (m2/s)
Dh = Dh0 * fac;        % Molecular diffusivity, heat (m2/s)
Dv = Dv0 * fac;        % Molecular diffusivity, H2O (m2/s)
Dc = Dc0 * fac;        % Molecular diffusivity, CO2 (m2/s)

% Dimensionless numbers

Re = wind(p) * dleaf(p) / visc;   % Reynolds number
Pr  = visc / Dh;                  % Prandtl number
Scv = visc / Dv;                  % Schmidt number for H2O
Scc = visc / Dc;                  % Schmidt number for CO2
Gr = g * dleaf(p)^3 * max(tleaf(p) - tair(p), 0) / (tair(p) * visc * visc); % Grashof number

% Empirical correction factor for Nu and Sh

b1 = 1.5;

% Forced convection - laminar flow

Nu_lam  = b1 * 0.66 *  Pr^0.33 * Re^0.5;     % Nusselt number
Shv_lam = b1 * 0.66 * Scv^0.33 * Re^0.5;     % Sherwood number, H2O
Shc_lam = b1 * 0.66 * Scc^0.33 * Re^0.5;     % Sherwood number, CO2

% Forced convection - turbulent flow

Nu_turb  = b1 * 0.036 *  Pr^0.33 * Re^0.8;   % Nusselt number
Shv_turb = b1 * 0.036 * Scv^0.33 * Re^0.8;   % Sherwood number, H2O
Shc_turb = b1 * 0.036 * Scc^0.33 * Re^0.8;   % Sherwood number, CO2

% Choose correct flow regime for forced convection

Nu_forced = max(Nu_lam, Nu_turb);
Shv_forced = max(Shv_lam, Shv_turb);
Shc_forced = max(Shc_lam, Shc_turb);

% Free convection

Nu_free  = 0.54 *  Pr^0.25 * Gr^0.25;        % Nusselt number
Shv_free = 0.54 * Scv^0.25 * Gr^0.25;        % Sherwood number, H2O
Shc_free = 0.54 * Scc^0.25 * Gr^0.25;        % Sherwood number, CO2

% Both convection regimes occur together

Nu = Nu_forced + Nu_free;
Shv = Shv_forced + Shv_free;
Shc = Shc_forced + Shc_free;

% Boundary layer conductances (mol/m2/s)

gbh(p) = Dh * Nu / dleaf(p) * rhomol(p);      % Heat
gbw(p) = Dv * Shv / dleaf(p) * rhomol(p);     % H2O
gbc(p) = Dc * Shc / dleaf(p) * rhomol(p);     % CO2

% Dummy output

x = 0;
leaf_temperature.m | View on GitHub
function [dtleaf] = leaf_temperature (p)

% ----------------------------------------------------------------------------
% Use Newton-Raphson iteration to solve the leaf energy budget for leaf temperature
% ----------------------------------------------------------------------------

% Global variables

global tfrz mmh2o sigma
global tair cpair pref eair
global gsw gbw gbh emleaf
global tleaf qa rn lwrad sh lh

niter = 0;           % Number of iterations
err = 1e36;          % Energy inbalance (W/m2)

% Iteration is until energy imbalance < 1e-06 W/m2 or to 100 iterations

while (niter <= 100 & abs(err) > 1e-06)

   % Increment iteration counter

   niter = niter + 1;

   % Saturation vapor pressure ESAT (Pa) and temperature derivative DESAT (Pa/K)

   [esat, desat] = satvap (tleaf(p)-tfrz);

   % Latent heat of vaporization (J/mol)

   lambda = 2501.6 - 2.3773 * (tair(p) - tfrz);  % J/g
   lambda = lambda * 1000 * mmh2o;               % J/g -> J/kg -> J/mol

   % Leaf conductance for water vapor (mol H2O/m2/s)

   gleaf = gsw(p) * gbw(p) / (gsw(p) + gbw(p));

   % Emitted longwave radiation LWRAD (W/m2) and temperature derivative DLWRAD (W/m2/K)

   lwrad(p) = 2 * emleaf(p) * sigma * tleaf(p)^4;
   dlwrad = -8 * emleaf(p) * sigma * tleaf(p)^3;

   % Sensible heat flux SH (W/m2) and temperature derivative DSH (W/m2/K)

   sh(p) = 2 * cpair(p) * (tleaf(p) - tair(p)) * gbh(p);
   dsh = -2 * cpair(p) * gbh(p);

   % Latent heat flux LH (W/m2) and temperature derivative DLH (W/m2/K)

   lh(p) = lambda * (esat - eair(p)) / pref(p) * gleaf;
   dlh = -lambda * desat / pref(p) * gleaf;

   % Energy imbalance (W/m2)

   err = qa(p) - lwrad(p) - sh(p) - lh(p);

   % Change in leaf temperature (K)

   dtleaf = -err / (dlwrad + dsh + dlh);

   % Update leaf temperature (K)

   tleaf(p) = tleaf(p) + dtleaf;

end

% Net radiation (W/m2)

rn(p) = qa(p) - lwrad(p);

% Error check

err = rn(p) - sh(p) - lh(p);
if (abs(err) > 1e-06)
   fprintf('err = %15.3f\n',err)
   fprintf('qa = %15.3f\n',qa(p))
   fprintf('lwrad = %15.3f\n',lwrad(p))
   fprintf('sh = %15.3f\n',sh(p))
   fprintf('lh = %15.3f\n',lh(p))
   error ('leaf temperature error')
end
satvap.m | View on GitHub
function [esat, desat] = satvap (tc)

% Compute saturation vapor pressure and change in saturation vapor pressure
% with respect to temperature. Polynomial approximations are from:
% Flatau et al. (1992) Polynomial fits to saturation vapor pressure.
% Journal of Applied Meteorology 31:1507-1513. Input temperature is Celsius.

% --- For water vapor (temperature range is 0C to 100C)
 
a0 =  6.11213476;        b0 =  0.444017302;
a1 =  0.444007856;       b1 =  0.286064092e-01;
a2 =  0.143064234e-01;   b2 =  0.794683137e-03;
a3 =  0.264461437e-03;   b3 =  0.121211669e-04;
a4 =  0.305903558e-05;   b4 =  0.103354611e-06;
a5 =  0.196237241e-07;   b5 =  0.404125005e-09;
a6 =  0.892344772e-10;   b6 = -0.788037859e-12;
a7 = -0.373208410e-12;   b7 = -0.114596802e-13;
a8 =  0.209339997e-15;   b8 =  0.381294516e-16;
 
% --- For ice (temperature range is -75C to 0C)
 
c0 =  6.11123516;        d0 =  0.503277922;
c1 =  0.503109514;       d1 =  0.377289173e-01;
c2 =  0.188369801e-01;   d2 =  0.126801703e-02;
c3 =  0.420547422e-03;   d3 =  0.249468427e-04;
c4 =  0.614396778e-05;   d4 =  0.313703411e-06;
c5 =  0.602780717e-07;   d5 =  0.257180651e-08;
c6 =  0.387940929e-09;   d6 =  0.133268878e-10;
c7 =  0.149436277e-11;   d7 =  0.394116744e-13;
c8 =  0.262655803e-14;   d8 =  0.498070196e-16;

% --- Limit temperature to -75C to 100C
 
tc = min(tc, 100);
tc = max(tc, -75);

% --- Saturation vapor pressure (esat, mb) and derivative (desat, mb)

if (tc >= 0)
   esat  = a0 + tc*(a1 + tc*(a2 + tc*(a3 + tc*(a4 ...
         + tc*(a5 + tc*(a6 + tc*(a7 + tc*a8)))))));
   desat = b0 + tc*(b1 + tc*(b2 + tc*(b3 + tc*(b4 ...
         + tc*(b5 + tc*(b6 + tc*(b7 + tc*b8)))))));
else
   esat  = c0 + tc*(c1 + tc*(c2 + tc*(c3 + tc*(c4 ...
         + tc*(c5 + tc*(c6 + tc*(c7 + tc*c8)))))));
   desat = d0 + tc*(d1 + tc*(d2 + tc*(d3 + tc*(d4 ...
         + tc*(d5 + tc*(d6 + tc*(d7 + tc*d8)))))));
end

% --- Convert from mb to Pa

esat  = esat  * 100;
desat = desat * 100;

Output

Text

sp_10_02_out.txt (standard output) | View on GitHub | View raw
qa =    1444.00    1444.00    1444.00    1444.00    1444.00    1444.00    1444.00    1444.00
gsw =       0.00       0.00       0.00       0.00       0.40       0.40       0.40       0.40
wind =       0.01       0.10       1.00       5.00       0.01       0.10       1.00       5.00
tleaf =      49.40      45.77      40.88      38.18      39.84      37.71      35.78      35.17
lwrad =    1202.86    1149.67    1080.71    1044.12    1066.54    1037.71    1012.29    1004.21
sh =     241.14     294.33     363.29     399.88      67.85      65.50      45.64      20.18
lh =       0.00       0.00       0.00       0.00     309.61     340.79     386.07     419.61
 
qa =    1136.00    1136.00    1136.00    1136.00    1136.00    1136.00    1136.00    1136.00
gsw =       0.00       0.00       0.00       0.00       0.40       0.40       0.40       0.40
wind =       0.01       0.10       1.00       5.00       0.01       0.10       1.00       5.00
tleaf =      39.90      38.53      36.84      35.98      36.29      33.49      32.93      33.42
lwrad =    1067.28    1048.75    1026.25    1014.86    1018.92     982.59     975.37     981.60
sh =      68.72      87.26     109.75     121.14       6.78     -25.08    -109.03    -186.44
lh =       0.00       0.00       0.00       0.00     110.30     178.49     269.66     340.84