Plant Hydraulics
Table of contents
Code
Main program
sp_13_01.m
| View on GitHub
% Supplemental program 13.1
% -------------------------------------------------------------------------
% Calculate leaf gas exchange coupled with the leaf energy budget for C3
% and C4 plants. Leaf temperature is calculated from the energy balance.
% Stomatal conductance is calculated from water-use efficiency optimization
% within the constraints imposed by plant hydraulics.
% -------------------------------------------------------------------------
% --- Waveband indices for visible and near-infrared
params.vis = 1; params.nir = 2;
% --- Physical constants
physcon.grav = 9.80665; % Gravitational acceleration (m/s2)
physcon.tfrz = 273.15; % Freezing point of water (K)
physcon.sigma = 5.67e-08; % Stefan-Boltzmann constant (W/m2/K4)
physcon.mmdry = 28.97 / 1000; % Molecular mass of dry air (kg/mol)
physcon.mmh2o = 18.02 / 1000; % Molecular mass of water (kg/mol)
physcon.cpd = 1005; % Specific heat of dry air at constant pressure (J/kg/K)
physcon.cpw = 1846; % Specific heat of water vapor at constant pressure (J/kg/K)
physcon.rgas = 8.31446; % Universal gas constant (J/K/mol)
physcon.visc0 = 13.3e-06; % Kinematic viscosity at 0C and 1013.25 hPa (m2/s)
physcon.Dh0 = 18.9e-06; % Molecular diffusivity (heat) at 0C and 1013.25 hPa (m2/s)
physcon.Dv0 = 21.8e-06; % Molecular diffusivity (H2O) at 0C and 1013.25 hPa (m2/s)
physcon.Dc0 = 13.8e-06; % Molecular diffusivity (CO2) at 0C and 1013.25 hPa (m2/s)
physcon.denh2o = 1000; % Density of liquid water (kg/m3)
% --- Set leaf physiology variables
% Photosynthetic pathway: 1 = C3. 0 = C4
leaf.c3psn = 1;
% Photosynthesis co-limitation: 0 = no. 1 = yes
leaf.colim = 1;
% Leaf physiological parameters
[leaf] = LeafPhysiologyParams (params, physcon, leaf);
% --- Set root parameters
[rootvar] = RootParams();
% --- Set site variables
% Leaf height (m)
flux.height = 15;
% Fine root biomass (g biomass / m2)
rootvar.biomass = 500;
% Canopy leaf area index (m2/m2)
flux.lai = 5;
% Soil texture classes
% 1: sand
% 2: loamy sand
% 3: sandy loam
% 4: silt loam
% 5: loam
% 6: sandy clay loam
% 7 silty clay loam
% 8: clay loam
% 9: sandy clay
% 10: silty clay
% 11: clay
soil.texture = 5;
% --- Set soil hydraulic parameters, soil depth, and rooting fraction
[soil] = SoilParams (soil);
% --- Set soil moisture
for j = 1:soil.nlevsoi
soil.h2osoi_vol(j) = 0.5 * soil.watsat(j);
soil.psi(j) = soil.psisat(j) * (soil.h2osoi_vol(j) / soil.watsat(j))^-soil.bsw(j);
end
% --- Hydraulic conductances
% Aboveground plant stem resistance for xylem-to-leaf (MPa.s.m2/mmol H2O)
flux.rplant = 1 / leaf.gplant;
% Calculate soil hydraulic resistance, weighted soil water potential and
% water uptake from each soil layer
[flux] = SoilResistance (physcon, leaf, rootvar, soil, flux);
% Leaf-specific conductance for soil-to-leaf (mmol H2O/m2 laef/s/MPa)
flux.lsc = 1 / (flux.rsoil + flux.rplant);
fprintf('rplant = %15.5f\n',flux.rplant)
fprintf('rsoil = %15.5f\n',flux.rsoil)
fprintf('lsc = %15.5f\n',flux.lsc)
% --- Atmospheric forcing
% Process sunlit or shaded leaf
leaftype = 'sun';
% leaftype = 'shade';
% Atmospheric CO2 (umol/mol) and O2 (mmol/mol)
atmos.co2air = 380;
atmos.o2air = 0.209 * 1000;
% Air temperature (K) and relative humidity (%)
atmos.tair = physcon.tfrz + 30;
atmos.relhum = 60;
% Wind (m/s)
% u = 0.01_r8 ! Still air
% u = 0.1_r8 ! Calm - smoke rises vertically
% u = 1.0_r8 ! Light air - smoke drift indicates wind direction
% u = 2.5_r8 ! Light breeze - wind felt on skin, leaves rustle
% u = 5.0_r8 ! Gentle breeze - leaves constantly moving and light flag extended
% u = 10.0_r8 ! Moderate breeze
atmos.wind = 1;
% Atmospheric pressure (Pa)
atmos.patm = 101325;
% Vapor pressure (Pa) and specific humidity (kg/kg)
[esat, desat] = satvap ((atmos.tair-physcon.tfrz));
atmos.eair = esat * (atmos.relhum / 100);
atmos.qair = physcon.mmh2o / physcon.mmdry * atmos.eair / (atmos.patm - (1 - physcon.mmh2o/physcon.mmdry) * atmos.eair);
% Molar density (mol/m3)
atmos.rhomol = atmos.patm / (physcon.rgas * atmos.tair);
% Air density (kg/m3)
atmos.rhoair = atmos.rhomol * physcon.mmdry * (1 - (1 - physcon.mmh2o/physcon.mmdry) * atmos.eair / atmos.patm);
% Molecular mass of air (kg/mol)
atmos.mmair = atmos.rhoair / atmos.rhomol;
% Specific heat of air at constant pressure (J/mol/K)
atmos.cpair = physcon.cpd * (1 + (physcon.cpw/physcon.cpd - 1) * atmos.qair) * atmos.mmair;
% Atmospheric longwave radiation (W/m2)
atmos.irsky = 400;
% Solar radiation (W/m2)
switch leaftype
case 'sun'
fsds = 800; % Sun leaf
case 'shade'
fsds = 300; % Shade leaf
end
atmos.swsky(params.vis) = 0.5 * fsds;
atmos.swsky(params.nir) = 0.5 * fsds;
% --- Ground variables
ground.albsoi(params.vis) = 0.1; % Soil albedo (visible waveband)
ground.albsoi(params.nir) = 0.2; % Soil albedo (near-infrared waveband)
tg = atmos.tair;
ground.irgrd = physcon.sigma * tg^4;
% --- Radiation absorbed by leaf
% Solar radiation incident on leaf
flux.swinc(params.vis) = atmos.swsky(params.vis) * (1 + ground.albsoi(params.vis));
flux.swinc(params.nir) = atmos.swsky(params.nir) * (1 + ground.albsoi(params.nir));
% Solar radiation absorbed by leaf
flux.swflx(params.vis) = flux.swinc(params.vis) * (1 - leaf.rho(params.vis) - leaf.tau(params.vis));
flux.swflx(params.nir) = flux.swinc(params.nir) * (1 - leaf.rho(params.nir) - leaf.tau(params.nir));
flux.apar = flux.swflx(params.vis) * 4.6;
% Radiative forcing for leaf temperature calculation
flux.qa = flux.swflx(params.vis) + flux.swflx(params.nir) + leaf.emiss * (atmos.irsky + ground.irgrd);
% --- Leaf temperature, energy fluxes, photosynthesis, and stomatal conductance
% Initial estimate for leaf temperature
flux.tleaf = atmos.tair;
% Leaf water potential at beginning of time step (MPa)
flux.psi_leaf = -0.1;
% Time step (s) for change in leaf water potential
flux.dt = 30 * 60;
% Flux calculations
[flux] = LeafFluxes (physcon, atmos, leaf, flux);
% Print flux output
fprintf('dleaf = %15.5f\n',leaf.dleaf*100) % m -> cm
fprintf('apar = %15.5f\n',flux.apar)
fprintf('tleaf = %15.5f\n',flux.tleaf-physcon.tfrz) % K -> oC
fprintf('qa = %15.5f\n',flux.qa)
fprintf('lhflx = %15.5f\n',flux.lhflx)
fprintf('etflx = %15.5f\n',flux.etflx*1000) % mol H2O/m2/s -> mmol H2O/m2/s
fprintf('an = %15.5f\n',flux.an)
fprintf('gbh = %15.5f\n',flux.gbh)
fprintf('gs = %15.5f\n',flux.gs)
fprintf('psi_leaf = %15.5f\n',flux.psi_leaf)
Aux. programs
brent_root.m
| View on GitHub
function [flux, root] = brent_root (func, physcon, atmos, leaf, flux, xa, xb, tol)
% Use Brent's method to find the root of a function, which is known to exist between
% xa and xb. The root is updated until its accuracy is tol. func is the name of the
% function to solve. The variable root is returned as the root of the function. The
% function being evaluated has the definition statement:
%
% function [flux, fx] = func (physcon, atmos, leaf, flux, x)
%
% The function func is exaluated at x and the returned value is fx. It uses variables
% in the physcon, atmos, leaf, and flux structures. These are passed in as
% input arguments. It also calculates values for variables in the flux structure
% so this must be returned in the function call as an output argument. The matlab
% function feval evaluates func.
% --- Evaluate func at xa and xb and make sure the root is bracketed
a = xa;
b = xb;
[flux, fa] = feval(func, physcon, atmos, leaf, flux, a);
[flux, fb] = feval(func, physcon, atmos, leaf, flux, b);
if ((fa > 0 & fb > 0) | (fa < 0 & fb < 0))
error('brent_root error: root must be bracketed')
end
% --- Initialize iteration
itmax = 50; % Maximum number of iterations
eps1 = 1e-08; % Relative error tolerance
c = b;
fc = fb;
% --- Iterative root calculation
for iter = 1:itmax
if ((fb > 0 & fc > 0) | (fb < 0 & fc < 0))
c = a;
fc = fa;
d = b - a;
e = d;
end
if (abs(fc) < abs(fb))
a = b;
b = c;
c = a;
fa = fb;
fb = fc;
fc = fa;
end
tol1 = 2 * eps1 * abs(b) + 0.5 * tol;
xm = 0.5 * (c - b);
% Check to end iteration
if (abs(xm) <= tol1 | fb == 0)
break
end
if (abs(e) >= tol1 & abs(fa) > abs(fb))
s = fb / fa;
if (a == c)
p = 2 * xm * s;
q = 1 - s;
else
q = fa / fc;
r = fb / fc;
p = s * (2 * xm * q * (q - r) - (b - a) * (r - 1));
q = (q - 1) * (r - 1) * (s - 1);
end
if (p > 0)
q = -q;
end
p = abs(p);
if (2*p < min(3*xm*q-abs(tol1*q), abs(e*q)))
e = d;
d = p / q;
else
d = xm;
e = d;
end
else
d = xm;
e = d;
end
a = b;
fa = fb;
if (abs(d) > tol1)
b = b + d;
else
if (xm >= 0)
b = b + abs(tol1);
else
b = b - abs(tol1);
end
end
[flux, fb] = feval(func, physcon, atmos, leaf, flux, b);
% Check to end iteration
if (fb == 0)
break
end
% Check to see if failed to converge
if (iter == itmax)
error('brent_root error: Maximum number of interations exceeded')
end
end
root = b;
CiFuncOptimization.m
| View on GitHub
function [flux] = CiFuncOptimization (atmos, leaf, flux)
% Calculate leaf photosynthesis for a specified stomatal conductance.
% Then calculate Ci from the diffusion equation.
%
% This routine uses a quadratic equation to solve for net photosynthesis (An).
% A general equation for C3 photosynthesis is:
%
% a*(Ci - Cp)
% An = ----------- - Rd
% e*Ci + d
%
% where:
%
% An = Net leaf photosynthesis (umol CO2/m2/s)
% Rd = Leaf respiration (umol CO2/m2/s)
% Ci = Intercellular CO2 concentration (umol/mol)
% Cp = CO2 compensation point (umol/mol)
%
% Rubisco-limited photosynthesis (Ac)
% a = Vcmax
% e = 1
% d = Kc*(1 + Oi/Ko)
%
% RuBP regeneration-limited photosynthesis (Aj)
% a = J
% e = 4
% d = 8*Cp
%
% where:
%
% Vcmax = Maximum carboxylation rate (umol/m2/s)
% Kc = Michaelis-Menten constant for CO2 (umol/mol)
% Ko = Michaelis-Menten constant for O2 (mmol/mol)
% Oi = Intercellular O2 concentration (mmol/mol)
% J = Electron transport rate (umol/m2/s)
%
% Ci is calculated from the diffusion equation:
%
% 1.4 1.6
% An = (Ca - Ci) / (--- + ---)
% gb gs
%
% 1.4 1.6
% Ci = Ca - (--- + ---)*An
% gb gs
%
% where:
%
% Ca = Atmospheric CO2 concentration (umol/mol)
% gb = Leaf boundary layer conductance (mol H2O/m2/s)
% gs = Leaf stomatal conductance (mol H2O/m2/s)
% 1.4 = Corrects gb for the diffusivity of CO2 compared with H2O
% 1.6 = Corrects gs for the diffusivity of CO2 compared with H2O
%
% The resulting quadratic equation is: a*An^2 + b*An + c = 0, which
% is solved for An. Correct solution is the smaller of the two roots.
%
% A similar approach is used for C4 photosynthesis.
% ------------------------------------------------------
% Input
% atmos.o2air ! Atmospheric O2 (mmol/mol)
% atmos.co2air ! Atmospheric CO2 (umol/mol)
% leaf.c3psn ! Photosynthetic pathway: 1 = C3. 0 = C4 plant
% leaf.colim ! Photosynthesis co-limitation: 0 = no. 1 = yes
% leaf.colim_c3 ! Empirical curvature parameter for C3 co-limitation
% leaf.colim_c4a ! Empirical curvature parameter for C4 co-limitation
% leaf.colim_c4b ! Empirical curvature parameter for C4 co-limitation
% leaf.qe_c4 ! C4: Quantum yield (mol CO2 / mol photons)
% flux.vcmax ! Maximum carboxylation rate (umol/m2/s)
% flux.cp ! CO2 compensation point (umol/mol)
% flux.kc ! Michaelis-Menten constant for CO2 (umol/mol)
% flux.ko ! Michaelis-Menten constant for O2 (mmol/mol)
% flux.je ! Electron transport rate (umol/m2/s)
% flux.kp_c4 ! C4: Initial slope of CO2 response curve (mol/m2/s)
% flux.gs ! Leaf stomatal conductance (mol H2O/m2 leaf/s)
% flux.gbc ! Leaf boundary layer conductance, CO2 (mol CO2/m2 leaf/s)
% flux.apar ! Leaf absorbed PAR (umol photon/m2 leaf/s)
% flux.rd ! Leaf respiration rate (umol CO2/m2 leaf/s)
%
% Output
% flux.ac ! Leaf Rubisco-limited gross photosynthesis (umol CO2/m2 leaf/s)
% flux.aj ! Leaf RuBP regeneration-limited gross photosynthesis (umol CO2/m2 leaf/s)
% flux.ap ! Leaf product-limited (C3) or CO2-limited (C4) gross photosynthesis (umol CO2/m2 leaf/s)
% flux.ag ! Leaf gross photosynthesis (umol CO2/m2 leaf/s)
% flux.an ! Leaf net photosynthesis (umol CO2/m2 leaf/s)
% flux.cs ! Leaf surface CO2 (umol/mol)
% flux.ci ! Leaf intercellular CO2 (umol/mol)
% ------------------------------------------------------
% --- Leaf conductance
% gbc has units mol CO2/m2/s
% gs has units mol H2O/m2/s
% gleaf has units mol CO2/m2/s
gleaf = 1 / (1 / flux.gbc + 1.6 / flux.gs);
% --- Gross assimilation rates
if (leaf.c3psn == 1)
% C3: Rubisco-limited photosynthesis
a0 = flux.vcmax;
e0 = 1;
d0 = flux.kc * (1 + atmos.o2air / flux.ko);
aquad = e0 / gleaf;
bquad = -(e0 * atmos.co2air + d0) - (a0 - e0 * flux.rd) / gleaf;
cquad = a0 * (atmos.co2air - flux.cp) - flux.rd * (e0 * atmos.co2air + d0);
pcoeff = [aquad bquad cquad];
proots = roots(pcoeff);
flux.ac = min(proots(1), proots(2)) + flux.rd;
% C3: RuBP regeneration-limited photosynthesis
a0 = flux.je;
e0 = 4;
d0 = 8 * flux.cp;
aquad = e0 / gleaf;
bquad = -(e0 * atmos.co2air + d0) - (a0 - e0 * flux.rd) / gleaf;
cquad = a0 * (atmos.co2air - flux.cp) - flux.rd * (e0 * atmos.co2air + d0);
pcoeff = [aquad bquad cquad];
proots = roots(pcoeff);
flux.aj = min(proots(1), proots(2)) + flux.rd;
% C3: Product-limited photosynthesis
flux.ap = 0;
else
% C4: Rubisco-limited photosynthesis
flux.ac = flux.vcmax;
% C4: RuBP-limited photosynthesis
flux.aj = leaf.qe_c4 * flux.apar;
% C4: PEP carboxylase-limited (CO2-limited)
flux.ap = flux.kp_c4 * (atmos.co2air * gleaf + flux.rd) / (gleaf + flux.kp_c4);
end
% --- Net assimilation as the minimum or co-limited rate
if (leaf.colim == 1) % Use co-limitation
% First co-limit Ac and Aj. Ai is the intermediate co-limited photosynthesis
% rate found by solving the polynomial: aquad*Ai^2 + bquad*Ai + cquad = 0 for Ai.
% Correct solution is the smallest of the two roots.
if (leaf.c3psn == 1)
aquad = leaf.colim_c3;
else
aquad = leaf.colim_c4a;
end
bquad = -(flux.ac + flux.aj);
cquad = flux.ac * flux.aj;
pcoeff = [aquad bquad cquad];
proots = roots(pcoeff);
ai = min(proots(1), proots(2));
% Now co-limit again using Ap, but only for C4 plants. Solve the polynomial:
% aquad*Ag^2 + bquad*Ag + cquad = 0 for Ag. Correct solution is the smallest
% of the two roots. Ignore the product-limited rate For C3 plants.
if (leaf.c3psn == 0)
aquad = leaf.colim_c4b;
bquad = -(ai + flux.ap);
cquad = ai * flux.ap;
pcoeff = [aquad bquad cquad];
proots = roots(pcoeff);
flux.ag = min(proots(1), proots(2));
else
flux.ag = ai;
end
elseif (leaf.colim == 0) % No co-limitation
if (leaf.c3psn == 1)
flux.ag = min(flux.ac, flux.aj); % C3
else
flux.ag = min(flux.ac, flux.aj, flux.ap); % C4
end
end
% Prevent photosynthesis from ever being negative
flux.ac = max(flux.ac, 0);
flux.aj = max(flux.aj, 0);
flux.ap = max(flux.ap, 0);
flux.ag = max(flux.ag, 0);
% Net CO2 uptake
flux.an = flux.ag - flux.rd;
% --- CO2 at leaf surface
flux.cs = atmos.co2air - flux.an / flux.gbc;
flux.cs = max(flux.cs, 1);
% --- Intercelluar CO2
flux.ci = atmos.co2air - flux.an / gleaf;
latvap.m
| View on GitHub
function [val] = latvap (tc, mmh2o)
% Latent heat of vaporization (J/mol) at temperature tc (degC)
val = 2501.6 - 2.3773 * tc; % Latent heat of vaporization (J/g)
val = val * 1000; % Convert from J/g to J/kg
val = val * mmh2o; % Convert from J/kg to J/mol
LeafBoundaryLayer.m
| View on GitHub
function [flux] = LeafBoundaryLayer (physcon, atmos, leaf, flux)
% Leaf boundary layer conductances
% -------------------------------------------------------------------------
% Input
% physcon.grav ! Gravitational acceleration (m/s2)
% physcon.tfrz ! Freezing point of water (K)
% physcon.visc0 ! Kinematic viscosity at 0C and 1013.25 hPa (m2/s)
% physcon.Dh0 ! Molecular diffusivity (heat) at 0C and 1013.25 hPa (m2/s)
% physcon.Dv0 ! Molecular diffusivity (H2O) at 0C and 1013.25 hPa (m2/s)
% physcon.Dc0 ! Molecular diffusivity (CO2) at 0C and 1013.25 hPa (m2/s)
% atmos.patm ! Atmospheric pressure (Pa)
% atmos.rhomol ! Molar density mol/m3)
% atmos.wind ! Wind speed (m/s)
% atmos.tair ! Air temperature (K)
% leaf.dleaf ! Leaf dimension (m)
% flux.tleaf ! Leaf temperature (K)
%
% Output
% flux.gbh ! Leaf boundary layer conductance, heat (mol/m2 leaf/s)
% flux.gbv ! Leaf boundary layer conductance, H2O (mol H2O/m2 leaf/s)
% flux.gbc ! Leaf boundary layer conductance, CO2 (mol CO2/m2 leaf/s)
% -------------------------------------------------------------------------
% --- Adjust diffusivity for temperature and pressure
fac = 101325 / atmos.patm * (atmos.tair / physcon.tfrz)^1.81;
visc = physcon.visc0 * fac; % Kinematic viscosity (m2/s)
Dh = physcon.Dh0 * fac; % Molecular diffusivity, heat (m2/s)
Dv = physcon.Dv0 * fac; % Molecular diffusivity, H2O (m2/s)
Dc = physcon.Dc0 * fac; % Molecular diffusivity, CO2 (m2/s)
% --- Dimensionless numbers
Re = atmos.wind * leaf.dleaf / visc; % Reynolds number
Pr = visc / Dh; % Prandtl number
Scv = visc / Dv; % Schmidt number for H2O
Scc = visc / Dc; % Schmidt number for CO2
% Grashof number
Gr = physcon.grav * leaf.dleaf^3 * max(flux.tleaf-atmos.tair, 0) / (atmos.tair * visc * visc);
% --- Empirical correction factor for Nu and Sh
b1 = 1.5;
% --- Nusselt number (Nu) and Sherwood numbers (H2O: Shv, CO2: Shc)
% 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 forced and free convection regimes occur together
Nu = Nu_forced + Nu_free;
Shv = Shv_forced + Shv_free;
Shc = Shc_forced + Shc_free;
% --- Boundary layer conductances (m/s)
flux.gbh = Dh * Nu / leaf.dleaf;
flux.gbv = Dv * Shv / leaf.dleaf;
flux.gbc = Dc * Shc / leaf.dleaf;
% --- Convert conductance (m/s) to (mol/m2/s)
flux.gbh = flux.gbh * atmos.rhomol;
flux.gbv = flux.gbv * atmos.rhomol;
flux.gbc = flux.gbc * atmos.rhomol;
LeafFluxes.m
| View on GitHub
function [flux] = LeafFluxes (physcon, atmos, leaf, flux)
% --- Leaf temperature, energy fluxes, photosynthesis, and stomatal conductance
% using stomatal optimization
[flux] = StomataOptimization (physcon, atmos, leaf, flux);
LeafPhotosynthesis.m
| View on GitHub
function [flux] = LeafPhotosynthesis (physcon, atmos, leaf, flux)
% Calculate leaf photosynthesis for a specified stomatal
% conductance. Then calculate Ci from the diffusion equation.
% This is used with the WUE stomatal optimization.
% ------------------------------------------------------
% Input
% physcon.tfrz ! Freezing point of water (K)
% physcon.rgas ! Universal gas constant (J/K/mol)
% atmos.co2air ! Atmospheric CO2 (umol/mol)
% atmos.eair ! Vapor pressure of air (Pa)
% leaf.c3psn ! Photosynthetic pathway: 1 = C3. 0 = C4 plant
% leaf.vcmax25 ! Maximum carboxylation rate at 25C (umol/m2/s)
% leaf.jmax25 ! Maximum electron transport rate at 25C (umol/m2/s)
% leaf.rd25 ! Leaf respiration rate at 25C (umol CO2/m2/s)
% leaf.kc25 ! Michaelis-Menten constant for CO2 at 25C (umol/mol)
% leaf.ko25 ! Michaelis-Menten constant for O2 at 25C (mmol/mol)
% leaf.cp25 ! CO2 compensation point at 25C (umol/mol)
% leaf.kcha ! Activation energy for Kc (J/mol)
% leaf.koha ! Activation energy for Ko (J/mol)
% leaf.cpha ! Activation energy for Cp (J/mol)
% leaf.vcmaxha ! Activation energy for Vcmax (J/mol)
% leaf.jmaxha ! Activation energy for Jmax (J/mol)
% leaf.rdha ! Activation energy for Rd (J/mol)
% leaf.vcmaxhd ! Deactivation energy for Vcmax (J/mol)
% leaf.jmaxhd ! Deactivation energy for Jmax (J/mol)
% leaf.rdhd ! Deactivation energy for Rd (J/mol)
% leaf.vcmaxse ! Entropy term for Vcmax (J/mol/K)
% leaf.jmaxse ! Entropy term for Jmax (J/mol/K)
% leaf.rdse ! Entropy term for Rd (J/mol/K)
% leaf.vcmaxc ! Vcmax scaling factor for high temperature inhibition (25 C = 1.0)
% leaf.jmaxc ! Jmax scaling factor for high temperature inhibition (25 C = 1.0)
% leaf.rdc ! Rd scaling factor for high temperature inhibition (25 C = 1.0)
% leaf.phi_psii ! Quantum yield of PS II
% leaf.theta_j ! Empirical curvature parameter for electron transport rate
% leaf.kp25_c4 ! C4: Initial slope of CO2 response curve at 25C (mol/m2/s)
% flux.gbv ! Leaf boundary layer conductance, H2O (mol H2O/m2 leaf/s)
% flux.gbc ! Leaf boundary layer conductance, CO2 (mol CO2/m2 leaf/s)
% flux.apar ! Leaf absorbed PAR (umol photon/m2 leaf/s)
% flux.tleaf ! Leaf temperature (K)
% flux.gs ! Leaf stomatal conductance (mol H2O/m2 leaf/s)
%
% Output
% flux.vcmax ! Maximum carboxylation rate (umol/m2/s)
% flux.jmax ! Maximum electron transport rate (umol/m2/s)
% flux.cp ! CO2 compensation point (umol/mol)
% flux.kc ! Michaelis-Menten constant for CO2 (umol/mol)
% flux.ko ! Michaelis-Menten constant for O2 (mmol/mol)
% flux.je ! Electron transport rate (umol/m2/s)
% flux.kp_c4 ! C4: Initial slope of CO2 response curve (mol/m2/s)
% flux.ac ! Leaf Rubisco-limited gross photosynthesis (umol CO2/m2 leaf/s)
% flux.aj ! Leaf RuBP regeneration-limited gross photosynthesis (umol CO2/m2 leaf/s)
% flux.ap ! Leaf product-limited (C3) or CO2-limited (C4) gross photosynthesis (umol CO2/m2 leaf/s)
% flux.ag ! Leaf gross photosynthesis (umol CO2/m2 leaf/s)
% flux.an ! Leaf net photosynthesis (umol CO2/m2 leaf/s)
% flux.rd ! Leaf respiration rate (umol CO2/m2 leaf/s)
% flux.cs ! Leaf surface CO2 (umol/mol)
% flux.ci ! Leaf intercellular CO2 (umol/mol)
% flux.hs ! Leaf fractional humidity at surface (dimensionless)
% flux.vpd ! Leaf vapor pressure deficit at surface (Pa)
% ------------------------------------------------------
% --- Adjust photosynthetic parameters for temperature
if (leaf.c3psn == 1)
% C3 temperature response
ft = @(tl, ha) exp(ha/(physcon.rgas*(physcon.tfrz+25)) * (1-(physcon.tfrz+25)/tl));
fth = @(tl, hd, se, fc) fc / (1 + exp((-hd+se*tl)/(physcon.rgas*tl)));
flux.kc = leaf.kc25 * ft(flux.tleaf, leaf.kcha);
flux.ko = leaf.ko25 * ft(flux.tleaf, leaf.koha);
flux.cp = leaf.cp25 * ft(flux.tleaf, leaf.cpha);
t1 = ft(flux.tleaf, leaf.vcmaxha);
t2 = fth(flux.tleaf, leaf.vcmaxhd, leaf.vcmaxse, leaf.vcmaxc);
flux.vcmax = leaf.vcmax25 * t1 * t2;
t1 = ft(flux.tleaf, leaf.jmaxha);
t2 = fth(flux.tleaf, leaf.jmaxhd, leaf.jmaxse, leaf.jmaxc);
flux.jmax = leaf.jmax25 * t1 * t2;
t1 = ft(flux.tleaf, leaf.rdha);
t2 = fth(flux.tleaf, leaf.rdhd, leaf.rdse, leaf.rdc);
flux.rd = leaf.rd25 * t1 * t2;
flux.kp_c4 = 0;
elseif (leaf.c3psn == 0)
% C4 temperature response
t1 = 2^((flux.tleaf-(physcon.tfrz+25)) / 10);
t2 = 1 + exp(0.2*((physcon.tfrz+15)-flux.tleaf));
t3 = 1 + exp(0.3*(flux.tleaf-(physcon.tfrz+40)));
flux.vcmax = leaf.vcmax25 * t1 / (t2 * t3);
t3 = 1 + exp(1.3*(flux.tleaf-(physcon.tfrz+55)));
flux.rd = leaf.rd25 * t1 / t3;
flux.kp_c4 = leaf.kp25_c4 * t1;
flux.kc = 0;
flux.ko = 0;
flux.cp = 0;
flux.jmax = 0;
flux.je = 0;
end
% --- Electron transport rate for C3 plants
% Solve the polynomial: aquad*Je^2 + bquad*Je + cquad = 0
% for Je. Correct solution is the smallest of the two roots.
if (leaf.c3psn == 1)
qabs = 0.5 * leaf.phi_psii * flux.apar;
aquad = leaf.theta_j;
bquad = -(qabs + flux.jmax);
cquad = qabs * flux.jmax;
pcoeff = [aquad bquad cquad];
proots = roots(pcoeff);
flux.je = min(proots(1), proots(2));
end
% --- Ci calculation. Calculate photosynthesis for a specified stomatal conductance
[flux] = CiFuncOptimization (atmos, leaf, flux);
% --- Relative humidity and vapor pressure at leaf surface
[esat, desat] = satvap ((flux.tleaf-physcon.tfrz));
flux.hs = (flux.gbv * atmos.eair + flux.gs * esat) / ((flux.gbv + flux.gs) * esat);
flux.vpd = max(esat - flux.hs*esat, 0.1);
% Compare with diffusion equation: An = (ca - ci) * gleaf
an_err = (atmos.co2air - flux.ci) / (1 / flux.gbc + 1.6 / flux.gs);
if (flux.an > 0 & abs(flux.an-an_err) > 0.01)
fprintf('An = %15.4f\n', flux.an)
fprintf('An_err = %15.4f\n', an_err)
error ('LeafPhotosynthesis: failed diffusion error check')
end
LeafPhysiologyParams.m
| View on GitHub
function [leaf] = LeafPhysiologyParams (params, physcon, leaf)
% ------------------------------------------------------
% Input
% params.vis ! Waveband index for visible radiation
% params.nir ! Waveband index for near-infrared radiation
% physcon.tfrz ! Freezing point of water (K)
% physcon.rgas ! Universal gas constant (J/K/mol)
% leaf.c3psn ! Photosynthetic pathway: 1 = C3. 0 = C4 plant
%
% Output
% leaf.vcmax25 ! Maximum carboxylation rate at 25C (umol/m2/s)
% leaf.jmax25 ! Maximum electron transport rate at 25C (umol/m2/s)
% leaf.rd25 ! Leaf respiration rate at 25C (umol CO2/m2/s)
% leaf.kc25 ! Michaelis-Menten constant for CO2 at 25C (umol/mol)
% leaf.ko25 ! Michaelis-Menten constant for O2 at 25C (mmol/mol)
% leaf.cp25 ! CO2 compensation point at 25C (umol/mol)
% leaf.kcha ! Activation energy for Kc (J/mol)
% leaf.koha ! Activation energy for Ko (J/mol)
% leaf.cpha ! Activation energy for Cp (J/mol)
% leaf.vcmaxha ! Activation energy for Vcmax (J/mol)
% leaf.jmaxha ! Activation energy for Jmax (J/mol)
% leaf.rdha ! Activation energy for Rd (J/mol)
% leaf.vcmaxhd ! Deactivation energy for Vcmax (J/mol)
% leaf.jmaxhd ! Deactivation energy for Jmax (J/mol)
% leaf.rdhd ! Deactivation energy for Rd (J/mol)
% leaf.vcmaxse ! Entropy term for Vcmax (J/mol/K)
% leaf.jmaxse ! Entropy term for Jmax (J/mol/K)
% leaf.rdse ! Entropy term for Rd (J/mol/K)
% leaf.vcmaxc ! Vcmax scaling factor for high temperature inhibition (25 C = 1.0)
% leaf.jmaxc ! Jmax scaling factor for high temperature inhibition (25 C = 1.0)
% leaf.rdc ! Rd scaling factor for high temperature inhibition (25 C = 1.0)
% leaf.phi_psii ! Quantum yield of PS II
% leaf.theta_j ! Empirical curvature parameter for electron transport rate
% leaf.colim_c3 ! Empirical curvature parameter for C3 co-limitation
% leaf.colim_c4a ! Empirical curvature parameter for C4 co-limitation
% leaf.colim_c4b ! Empirical curvature parameter for C4 co-limitation
% leaf.qe_c4 ! C4: Quantum yield (mol CO2 / mol photons)
% leaf.kp25_c4 ! C4: Initial slope of CO2 response curve at 25C (mol/m2/s)
% leaf.dleaf ! Leaf dimension (m)
% leaf.emiss ! Leaf emissivity
% leaf.rho ! Leaf reflectance for visible (vis) and near-infrared (nir) wavebands
% leaf.tau ! Leaf transmittance for visible (vis) and near-infrared (nir) wavebands
% leaf.iota ! Stomatal efficiency (umol CO2/ mol H2O)
% leaf.capac ! Plant capacitance (mmol H2O/m2 leaf area/MPa)
% leaf.minlwp ! Minimum leaf water potential (MPa)
% leaf.gplant ! Stem (xylem-to-leaf) hydraulic conductance (mmol H2O/m2 leaf area/s/Mpa)
% ------------------------------------------------------
% --- Vcmax and other parameters (at 25C)
if (leaf.c3psn == 1)
leaf.vcmax25 = 60;
leaf.jmax25 = 1.67 * leaf.vcmax25;
leaf.kp25_c4 = 0;
leaf.rd25 = 0.015 * leaf.vcmax25;
else
leaf.vcmax25 = 40;
leaf.jmax25 = 0;
leaf.kp25_c4 = 0.02 * leaf.vcmax25;
leaf.rd25 = 0.025 * leaf.vcmax25;
end
% --- Kc, Ko, Cp at 25C
leaf.kc25 = 404.9;
leaf.ko25 = 278.4;
leaf.cp25 = 42.75;
% --- Activation energy
leaf.kcha = 79430;
leaf.koha = 36380;
leaf.cpha = 37830;
leaf.rdha = 46390;
leaf.vcmaxha = 65330;
leaf.jmaxha = 43540;
% --- High temperature deactivation
% Deactivation energy (J/mol)
leaf.rdhd = 150000;
leaf.vcmaxhd = 150000;
leaf.jmaxhd = 150000;
% Entropy term (J/mol/K)
leaf.rdse = 490;
leaf.vcmaxse = 490;
leaf.jmaxse = 490;
% Scaling factors for high temperature inhibition (25 C = 1.0).
% The factor "c" scales the deactivation to a value of 1.0 at 25C.
fth25 = @(hd, se) 1 + exp((-hd + se*(physcon.tfrz+25)) / (physcon.rgas*(physcon.tfrz+25)));
leaf.vcmaxc = fth25 (leaf.vcmaxhd, leaf.vcmaxse);
leaf.jmaxc = fth25 (leaf.jmaxhd, leaf.jmaxse);
leaf.rdc = fth25 (leaf.rdhd, leaf.rdse);
% --- C3 parameters
% Quantum yield of PS II
leaf.phi_psii = 0.85;
% Empirical curvature parameter for electron transport rate
leaf.theta_j = 0.90;
% Empirical curvature parameter for C3 co-limitation
leaf.colim_c3 = 0.98;
% Empirical curvature parameters for C4 co-limitation
leaf.colim_c4a = 0.80;
leaf.colim_c4b = 0.95;
% --- C4: Quantum yield (mol CO2 / mol photons)
leaf.qe_c4 = 0.05;
% --- Stomatal efficiency for optimization (An/E; umol CO2/ mol H2O)
leaf.iota = 750;
% --- Leaf dimension (m)
leaf.dleaf = 0.05;
% --- Leaf emissivity
leaf.emiss = 0.98;
% --- Leaf reflectance and transmittance: visible and near-infrared wavebands
leaf.rho(params.vis) = 0.10;
leaf.tau(params.vis) = 0.10;
leaf.rho(params.nir) = 0.40;
leaf.tau(params.nir) = 0.40;
% --- Plant hydraulic parameters
% Plant capacitance (mmol H2O/m2 leaf area/MPa)
leaf.capac = 2500;
% Minimum leaf water potential (MPa)
leaf.minlwp = -2;
% Stem (xylem-to-leaf) hydraulic conductance (mmol H2O/m2 leaf area/s/Mpa)
leaf.gplant = 4;
LeafTemperature.m
| View on GitHub
function [flux] = LeafTemperature (physcon, atmos, leaf, flux)
% Leaf temperature and energy fluxes
% ------------------------------------------------------
% Input
% physcon.tfrz ! Freezing point of water (K)
% physcon.mmh2o ! Molecular mass of water (kg/mol)
% physcon.sigma ! Stefan-Boltzmann constant (W/m2/K4)
% atmos.patm ! Atmospheric pressure (Pa)
% atmos.cpair ! Specific heat of air at constant pressure (J/mol/K)
% atmos.tair ! Air temperature (K)
% atmos.eair ! Vapor pressure of air (Pa)
% leaf.emiss ! Leaf emissivity
% flux.gbh ! Leaf boundary layer conductance, heat (mol/m2 leaf/s)
% flux.gbv ! Leaf boundary layer conductance, H2O (mol H2O/m2 leaf/s)
% flux.gs ! Leaf stomatal conductance (mol H2O/m2 leaf/s)
% flux.qa ! Leaf radiative forcing (W/m2 leaf)
%
% Input/ouput
% flux.tleaf ! Leaf temperature (K)
%
% Output
% flux.rnet ! Leaf net radiation (W/m2 leaf)
% flux.lwrad ! Longwave radiation emitted from leaf (W/m2 leaf)
% flux.shflx ! Leaf sensible heat flux (W/m2 leaf)
% flux.lhflx ! Leaf latent heat flux (W/m2 leaf)
% flux.etflx ! Leaf transpiration flux (mol H2O/m2 leaf/s)
% ------------------------------------------------------
% --- Latent heat of vaporization (J/mol)
[lambda_val] = latvap ((atmos.tair-physcon.tfrz), physcon.mmh2o);
% --- Newton-Raphson iteration until leaf energy balance is less than
% f0_max or to niter_max iterations
niter = 0; % Number of iterations
f0 = 1e36; % Leaf energy balance (W/m2)
niter_max = 100; % Maximum number of iterations
f0_max = 1e-06; % Maximum energy imbalance (W/m2)
while (niter <= niter_max & abs(f0) > f0_max)
% Increment iteration counter
niter = niter + 1;
% Saturation vapor pressure (Pa) and temperature derivative (Pa/K)
[esat, desat] = satvap ((flux.tleaf-physcon.tfrz));
% Leaf conductance for water vapor (mol H2O/m2/s)
gleaf = flux.gs * flux.gbv / (flux.gs + flux.gbv);
% Emitted longwave radiation (W/m2) and temperature derivative (W/m2/K)
flux.lwrad = 2 * leaf.emiss * physcon.sigma * flux.tleaf^4;
dlwrad = 8 * leaf.emiss * physcon.sigma * flux.tleaf^3;
% Sensible heat flux (W/m2) and temperature derivative (W/m2/K)
flux.shflx = 2 * atmos.cpair * (flux.tleaf - atmos.tair) * flux.gbh;
dshflx = 2 * atmos.cpair * flux.gbh;
% Latent heat flux (W/m2) and temperature derivative (W/m2/K)
flux.lhflx = lambda_val / atmos.patm * (esat - atmos.eair) * gleaf;
dlhflx = lambda_val / atmos.patm * desat * gleaf;
% Energy balance (W/m2) and temperature derivative (W/m2/K)
f0 = flux.qa - flux.lwrad - flux.shflx - flux.lhflx;
df0 = -dlwrad - dshflx - dlhflx;
% Change in leaf temperature
dtleaf = -f0 / df0;
% Update leaf temperature
flux.tleaf = flux.tleaf + dtleaf;
end
% --- Net radiation
flux.rnet = flux.qa - flux.lwrad;
% --- Error check
err = flux.rnet - flux.shflx - flux.lhflx;
if (abs(err) > f0_max)
fprintf('err = %15.3f\n',err)
fprintf('qa = %15.3f\n',flux.qa)
fprintf('lwrad = %15.3f\n',flux.lwrad)
fprintf('sh = %15.3f\n',flux.shflx)
fprintf('lh = %15.3f\n',flux.lhflx)
error ('LeafTemperature error')
end
% Water vapor flux: W/m2 -> mol H2O/m2/s
flux.etflx = flux.lhflx / lambda_val;
LeafWaterPotential.m
| View on GitHub
function [leafwp] = LeafWaterPotential (physcon, leaf, flux)
% Calculate leaf water potential for the current transpiration rate
% -------------------------------------------------------------------------
% Input
% physcon.grav ! Gravitational acceleration (m/s2)
% physcon.denh2o ! Density of liquid water (kg/m3)
% leaf.capac ! Plant capacitance (mmol H2O/m2 leaf area/MPa)
% flux.height ! Leaf height (m)
% flux.lsc ! Leaf-specific conductance (mmol H2O/m2 leaf/s/MPa)
% flux.psi_leaf ! Leaf water potential at beginning of time step (MPa)
% flux.psi_soil ! Weighted soil water potential (MPa)
% flux.etflx ! Leaf transpiration flux (mol H2O/m2 leaf/s)
% flux.dt ! Model time step (s)
% Output
% leafwp ! Leaf water potential at end of time step (MPa)
% -------------------------------------------------------------------------
% --- Head of pressure (MPa/m)
head = physcon.denh2o * physcon.grav * 1e-06;
% --- Change in leaf water potential is: dy / dt = (a - y) / b. The integrated change
% over a full model timestep is: dy = (a - y0) * (1 - exp(-dt/b))
y0 = flux.psi_leaf;
a = flux.psi_soil - head * flux.height - 1000 * flux.etflx / flux.lsc;
b = leaf.capac / flux.lsc;
dy = (a - y0) * (1 - exp(-flux.dt/b));
leafwp = y0 + dy;
RootParams.m
| View on GitHub
function [rootvar] = RootParams
% Fine root radius (m)
rootvar.radius = 0.29e-03;
% Fine root density (g biomass / m3 root)
rootvar.density = 0.31e06;
% Hydraulic resistivity of root tissue (MPa.s.g/mmol H2O)
rootvar.resist = 25;
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;
SoilParams.m
| View on GitHub
function [soil] = SoilParams (soil)
% Set soil hydraulic parameters, soil depth, and rooting fraction
% -------------------------------------------------------------------------
% Input
% soil.texture ! Soil texture class
% Output
% soil.nlevsoi ! Number of soil layers
% soil.dz ! Soil layer thickness (m)
% soil.rootfr ! Fraction of roots in each soil layer (-)
% soil.watsat ! Soil layer volumetric water content at saturation (porosity)
% soil.psisat ! Soil layer matric potential at saturation (mm)
% soil.hksat ! Soil layer hydraulic conductivity at saturation (mm H2O/s)
% soil.bsw ! Soil layer Clapp and Hornberger "b" parameter
% -------------------------------------------------------------------------
% --- Soil texture classes
% 1: sand
% 2: loamy sand
% 3: sandy loam
% 4: silt loam
% 5: loam
% 6: sandy clay loam
% 7 silty clay loam
% 8: clay loam
% 9: sandy clay
% 10: silty clay
% 11: clay
% Volumetric water content at saturation (porosity)
theta_sat = [0.395, 0.410, 0.435, 0.485, 0.451, 0.420, 0.477, 0.476, 0.426, 0.492, 0.482];
% Matric potential at saturation (mm)
psi_sat = [-121, -90, -218, -786, -478, -299, -356, -630, -153, -490, -405];
% Clapp and Hornberger "b" parameter
b = [4.05, 4.38, 4.90, 5.30, 5.39, 7.12, 7.75, 8.52, 10.40, 10.40, 11.40];
% Hydraulic conductivity at saturation (cm/min -> mm/s)
k_sat = [1.056, 0.938, 0.208, 0.0432, 0.0417, 0.0378, 0.0102, 0.0147, 0.0130, 0.0062, 0.0077];
k_sat = k_sat * 10 / 60;
% --- Soil layer thickness (total depth is 2.5 m)
soil.nlevsoi = 11;
soil.dz = [0.05, 0.05, 0.10, 0.10, 0.20, 0.20, 0.20, 0.30, 0.40, 0.40, 0.50];
% --- Root profile
beta_param = 0.90; % root profile parameter: shallow profile
% beta_param = 0.97; % root profile parameter: deep profile
for j = 1:soil.nlevsoi
if (j == 1)
z2 = soil.dz(j) * 100;
soil.rootfr(j) = 1 - beta_param^z2;
else
z1 = z2;
z2 = z1 + soil.dz(j) * 100;
soil.rootfr(j) = beta_param^z1 - beta_param^z2;
end
end
% --- Soil texture to process
k = soil.texture;
% --- Soil layer values
for j = 1:soil.nlevsoi
soil.watsat(j) = theta_sat(k);
soil.psisat(j) = psi_sat(k);
soil.hksat(j) = k_sat(k);
soil.bsw(j) = b(k);
end
SoilResistance.m
| View on GitHub
function [flux] = SoilResistance (physcon, leaf, rootvar, soil, flux)
% Calculate soil hydraulic resistance, weighted soil water potential and
% water uptake from each soil layer
% ----------------------------------------------------------------------------------
% Input
% physcon.grav ! Gravitational acceleration (m/s2)
% physcon.denh2o ! Density of liquid water (kg/m3)
% physcon.mmh2o ! Molecular mass of water (kg/mol)
% leaf.minlwp ! Minimum leaf water potential (MPa)
% rootvar.biomass ! Fine root biomass (g biomass / m2)
% rootvar.radius ! Fine root radius (m)
% rootvar.density ! Fine root density (g biomass / m3 root)
% rootvar.resist ! Hydraulic resistivity of root tissue (MPa.s.g/mmol H2O)
% soil.nlevsoi ! Number of soil layers
% soil.h2osoi_vol ! Soil layer volumetric water content (m3/m3)
% soil.psi ! Soil layer matric potential (mm)
% soil.watsat ! Soil layer volumetric water content at saturation (porosity)
% soil.hksat ! Soil layer hydraulic conductivity at saturation (mm H2O/s)
% soil.bsw ! Soil layer Clapp and Hornberger "b" parameter
% soil.rootfr ! Fraction of roots in each soil layer (-)
% soil.dz ! Soil layer thickness (m)
% flux.lai ! Canopy leaf area index (m2/m2)
% Output
% flux.rsoil ! Soil hydraulic resistance (MPa.s.m2/mmol H2O)
% flux.psi_soil ! Weighted soil water potential (MPa)
% flux.et_loss ! Fraction of total transpiration from each soil layer (-)
% ----------------------------------------------------------------------------------
% --- Head of pressure (MPa/m)
head = physcon.denh2o * physcon.grav * 1e-06;
% --- Root cross-sectional area (m2 root)
root_cross_sec_area = pi * rootvar.radius^2;
% --- Soil and root resistances for each layer
flux.rsoil = 0;
for j = 1:soil.nlevsoi
% Hydraulic conductivity for each layer (mmol/m/s/MPa)
s = max(min(soil.h2osoi_vol(j)/soil.watsat(j), 1), 0.01);
hk = soil.hksat(j) * s^(2 * soil.bsw(j) + 3); % mm/s
hk = hk * 1e-03 / head; % mm/s -> m/s -> m2/s/MPa
hk = hk * physcon.denh2o / physcon.mmh2o * 1000; % m2/s/MPa -> mmol/m/s/MPa
% Matric potential for each layer (MPa)
psi_mpa(j) = soil.psi(j) * 1e-03 * head; % mm -> m -> MPa
% Root biomass density (g biomass / m3 soil)
root_biomass_density = rootvar.biomass * soil.rootfr(j) / soil.dz(j);
root_biomass_density = max(root_biomass_density, 1e-10);
% Root length density (m root per m3 soil)
root_length_density = root_biomass_density / (rootvar.density * root_cross_sec_area);
% Distance between roots (m)
root_dist = sqrt(1 / (root_length_density * pi));
% Soil-to-root resistance (MPa.s.m2/mmol H2O)
soilr1 = log(root_dist/rootvar.radius) / (2 * pi * root_length_density * soil.dz(j) * hk);
% Root-to-stem resistance (MPa.s.m2/mmol H2O)
soilr2 = rootvar.resist / (root_biomass_density * soil.dz(j));
% Belowground resistance (MPa.s.m2/mmol H2O)
soilr = soilr1 + soilr2;
% Total belowground resistance. First sum the conductances (1/soilr)
% for each soil layer and then convert back to a resistance after the
% summation
flux.rsoil = flux.rsoil + 1 / soilr;
% Maximum transpiration for each layer (mmol H2O/m2/s)
evap(j) = (psi_mpa(j) - leaf.minlwp) / soilr;
evap(j) = max (evap(j), 0);
end
% Belowground resistance: resistance = 1 / conductance
flux.rsoil = flux.lai / flux.rsoil;
% Weighted soil water potential (MPa)
flux.psi_soil = 0;
for j = 1:soil.nlevsoi
flux.psi_soil = flux.psi_soil + psi_mpa(j) * evap(j);
end
totevap = sum(evap); % Total maximum transpiration
if (totevap > 0)
flux.psi_soil = flux.psi_soil / totevap;
else
flux.psi_soil = leaf.minlwp;
end
% Fractional transpiration uptake from soil layers
for j = 1:soil.nlevsoi
if (totevap > 0)
flux.et_loss(j) = evap(j) / totevap;
else
flux.et_loss(j) = 1 / soil.nlevsoi;
end
end
StomataEfficiency.m
| View on GitHub
function [flux, val] = StomataEfficiency (physcon, atmos, leaf, flux, gs_val)
% Stomata water-use efficiency check and cavitation check to determine maximum gs.
% For the stomatal conductance gs_val, calculate photosynthesis and leaf
% water potential for an increase in stomatal conductance equal to "delta".
% The returned value is positive if this increase produces a change in
% photosynthesis > iota*vpd*delta or if the leaf water potential is > minlwp.
% The returned value is negative if the increase produces a change in
% photosynthesis < iota*vpd*delta or if the leaf water potential is < minlwp.
% --- Leaf boundary layer conductances
[flux] = LeafBoundaryLayer (physcon, atmos, leaf, flux);
% --- Specify "delta" as a small difference in gs (mol H2O/m2/s)
delta = 0.001;
% --- Calculate photosynthesis at lower gs (gs_val - delta), but first need leaf temperature for this gs
% gs2 - lower value for gs (mol H2O/m2/s)
% an2 - leaf photosynthesis at gs2 (umol CO2/m2/s)
gs2 = gs_val - delta;
flux.gs = gs2;
[flux] = LeafTemperature (physcon, atmos, leaf, flux);
[flux] = LeafPhotosynthesis (physcon, atmos, leaf, flux);
an2 = flux.an;
% --- Calculate photosynthesis at higher gs (gs_val), but first need leaf temperature for this gs
% gs1 - higher value for gs (mol H2O/m2/s)
% an1 - leaf photosynthesis at gs1 (umol CO2/m2/s)
gs1 = gs_val;
flux.gs = gs1;
[flux] = LeafTemperature (physcon, atmos, leaf, flux);
[flux] = LeafPhotosynthesis (physcon, atmos, leaf, flux);
an1 = flux.an;
% --- Efficiency check: wue < 0 when d(An) / d(gs) < iota * vpd
wue = (an1 - an2) - leaf.iota * delta * (flux.vpd / atmos.patm);
% --- Cavitation check: minpsi < 0 when leafwp < minlwp
[leafwp] = LeafWaterPotential (physcon, leaf, flux);
minpsi = leafwp - leaf.minlwp;
% --- Return the minimum of the two checks
val = min(wue, minpsi);
StomataOptimization.m
| View on GitHub
function [flux] = StomataOptimization (physcon, atmos, leaf, flux)
% Leaf temperature, energy fluxes, photosynthesis, and stomatal conductance
% with water-use efficiency stomatal optimization
% --- Low and high initial estimates for gs (mol H2O/m2/s)
gs1 = 0.002;
gs2 = 2.0;
% --- Check for minimum stomatal conductance linked to low light or drought stress based
% on the water-use efficiency and cavitation checks for gs1 and gs2 (check1, check2)
[flux, check1] = StomataEfficiency (physcon, atmos, leaf, flux, gs1);
[flux, check2] = StomataEfficiency (physcon, atmos, leaf, flux, gs2);
if (check1 * check2 < 0)
% Calculate gs using the function StomataEfficiency to iterate gs
% to an accuracy of tol (mol H2O/m2/s)
tol = 0.004;
func_name = 'StomataEfficiency';
[flux, root] = brent_root (func_name, physcon, atmos, leaf, flux, gs1, gs2, tol);
flux.gs = root;
else
% Low light or drought stress. Set gs to minimum conductance
flux.gs = 0.002;
end
% --- Leaf fluxes for this gs
[flux] = LeafBoundaryLayer (physcon, atmos, leaf, flux);
[flux] = LeafTemperature (physcon, atmos, leaf, flux);
[flux] = LeafPhotosynthesis (physcon, atmos, leaf, flux);
[flux.psi_leaf] = LeafWaterPotential (physcon, leaf, flux);
Output
Text
sp_13_01_out.txt
(standard output) | View on GitHub | View raw
rplant = 0.25000
rsoil = 0.25012
lsc = 1.99952
dleaf = 5.00000
apar = 1619.20000
tleaf = 32.79223
qa = 1309.28797
lhflx = 166.93008
etflx = 3.81174
an = 8.36513
gbh = 1.03400
gs = 0.18485
psi_leaf = -1.74042