0.1.39
Loading...
Searching...
No Matches
Stomatal Conductance Model Plugin Documentation

DependenciesNone
Python Importfrom pyhelios import StomatalConductanceModel
Main ClassStomatalConductanceModel

Overview

StomatalConductanceModel provides comprehensive stomatal conductance modeling and gas exchange calculations using validated stomatal response models. This plugin enables accurate simulation of plant-atmosphere interactions and water-carbon coupling in plant physiological studies.

The plugin implements several different stomatal conductance models. A brief description of the theory behind each model is given below, along with coefficients obtained from several example species.

The default model is the Buckley, Mott, Farquhar model (see Buckley, Mott, Farquhar (2003) Model (simplified version given in Buckley, Turnbull, and Adams 2012)).

System Requirements

Dependencies None
Platforms Windows, Linux, macOS
GPU Not required

Quick Start

from pyhelios import Context, StomatalConductanceModel
from pyhelios.types import *
# Create context and add leaf geometry
with Context() as context:
leaf_uuid = context.addPatch(center=vec3(0, 0, 1), size=vec2(0.1, 0.1))
with StomatalConductanceModel(context) as stomatal:
# Use species library for quick setup
stomatal.setBMFCoefficientsFromLibrary("Almond")
# Run steady-state calculation
stomatal.run()

Primitive Data

Input Primitive Data

Primitive Data Label Symbol Units Data Type Description Applicable model(s) Available Plug-ins Default Value
radiation_flux_PAR \(Q\) W/m2 float PAR photon flux density. Note W/m2 is automatically converted to \(\mu\)mol/m2/s using a factor of 4.57. BMF, BB Can be computed by RadiationModel plug-in. 0
temperature \(T_s\) Kelvin float Primitive surface temperature. All Can be computed by EnergyBalanceModel plug-in. 300 K
air_pressure \(p_{atm}\) Pascals float Atmospheric pressure. All N/A 101,000 Pa
air_temperature \(T_a\) Kelvin float Temperature of air outside of primitive boundary-layer. All N/A 300 K
air_humidity \(h\) Unitless float Relative humidity of air outside of primitive boundary-layer. All N/A 0.5
boundarylayer_conductance** \(g_H\) mol air/m2-s float Boundary-layer conductance to heat, summed over both faces of a two-sided primitive. (Assumed that b.l. conductance to moisture is 1.08 that of heat.) All Can be computed by BLConductanceModel plug-in, or by EnergyBalanceModel plug-in if optional output primitive data "boundarylayer_conductance_out" is enabled. 1.0 mol/m2-s
stomatal_sidedness \(\zeta\) unitless float Ratio of stomatal density on the upper leaf surface to the sum of the stomatal density on upper and lower leaf surfaces. Note: if "twosided_flag" is equal to 0, stomatal_sidedness will be automatically set to 0. All N/A 0
beta_soil \(\beta\) unitless float Soil moisture factor, defined as \((\theta-\theta_w)/(\theta_f-\theta_w)\), with \(\theta,\,\theta_f,\,\theta_w\) being the effective soil water content, water content at field capacity, and water content at the wilting point. All N/A 1.0
net_photosynthesis \(A\) \(\mu\)mol/m2-s float Net CO2 (photosynthetic) flux. BWB, BBL, Mopt Can be computed by PhotosynthesisModel plug-in. 0
air_CO2 \(C_a\) \(\mu\)mol/mol float CO2 concentration of air outside primitive boundary-layer. BWB, BBL, Mopt N/A 400 \(\mu\)mol/mol
Gamma_CO2 \(\Gamma\) \(\mu\)mol/mol float CO2 compensation point of photosynthesis including dark respiration. (Note: only used for Ball-Berry models.) BBL Can be computed by PhotosynthesisModel plug-in (need to enable optional primitive data output). 100 \(\mu\)mol/mol
xylem_water_potential \(\Psi_x\) MPa float Water potential of the xylem supplying the leaf. BB N/A

-0.1 MPa

**The stomatal conductance model will also check for primitive data "boundarylayer_conductance_out" if "boundarylayer_conductance" does not exist. If you are using the energy balance model to calculate the boundary-layer conductance, you should enable optional output primitive data "boundarylayer_conductance_out" so that other plug-ins can use it.

Output Primitive Data

Primitive Data Label Symbol Units Data Type Description
moisture_conductance \(g_s\) mol air/m2-sec float Conductance of water vapor through stomata.

Optional Output Primitive Data

Optional output primitive data can be written to the context by calling optionalOutputPrimitiveData(), with an argument of one of the primitive data labels given in the table below.

from pyhelios import StomatalConductanceModel
stomatal = StomatalConductanceModel(context)
stomatal.optionalOutputPrimitiveData("vapor_pressure_deficit")
Primitive Data LabelUnitsData TypeDescription
vapor_pressure_deficitmmol/mol floatVapor pressure deficit between the stomatal cavity and leaf surface. Only applicable for BMF model.
model_parametersN/A std::stringModel parameters for each primitive. See table below for the actual primitive data labels that are created.

If you enable the optional output primitive data "model_parameters", different primitive data will be created based on the selected model corresponding to each model parameter.

ModelModel ParameterOutput Primitive Data Label
Ball-Woodrow-Berry\(g_{s,0}\)gs0_BWB
\(a_1\)a1_BWB
Ball-Berry-Leuning\(g_{s,0}\)gs0_BBL
\(a_1\)a1_BBL
\(D_0\)D0_BBL
Medlyn Optimality\(g_{s,0}\)gs0_MOPT
\(g_1\)g1_MOPT
Buckley-Mott-Farquhar\(E_m\)Em_BMF
\(i_0\)i0_BMF
\(k\)k_BMF
\(b\)b_BMF

Introduction

This plugin implements several different stomatal conductance models. A brief description of the theory behind each model is given below, along with coefficients obtained from several example species.

The default model is the Buckley, Mott, Farquhar model (see Buckley, Mott, Farquhar (2003) Model (simplified version given in Buckley, Turnbull, and Adams 2012)).

Ball, Woodrow, Berry (1987) Model Theory

The Ball, Woodrow, and Berry (1987) model is based on the empirical observation that stomatal conductance various roughly linearly with the net photosynthetic flux \(A\) and relative humidity at the leaf surface \(h_s\). They proposed the relationship:

\[g_s = g_{s,0}+a_1A\beta\frac{h_s}{C_s},\]

where \(C_s\) is the air CO2 concentration at the leaf surface, and \(g_{s,0}\) and \(a_1\) are empirical parameters. \(\beta\) is a factor to account for reduction in stomatal conductance with soil drying and is defined as

\[\beta = \frac{\theta-\theta_w}{\theta_f-\theta_w},\]

where \(\theta,\,\theta_f,\,\theta_w\) are the effective soil water content, water content at field capacity, and water content at the wilting point. By default, it is assumed that \(\beta=1\).

This model is at odds with several more recent observation of stomatal function, including: 1) stomata have been shown to respond to the intercellular CO2 concentration \(C_i\) and not the concentration outside of the leaf (Mott 1988); 2) stomata respond to the rate of evaporation, not humidity itself (Mott and Parkhurst 1991); 3) the predicted \(g_s\) value could become negative; 4) the predicted value of \(g_s\) approaches infinity as \(C_s\rightarrow \infty\); 5) the predicted value of \(g_s\) does not respond to soil drying. Another more practical limitation is that photosynthesis must also be modeled in order to calculate stomatal conductance. Nonetheless, this model is one of the most commonly used models of stomatal conductance.

The CO2 concentration at the leaf surface is calculated as

\[C_s = C_a-\frac{A}{g_{bc}},\]

where \(g_{bc}\) is the boundary-layer conductance to CO2 (defined below), and \(C_a\) is the air CO2 concentration outside of the leaf boundary-layer.

The relative humidity at the leaf surface is calculated by setting up a water vapor flux balance at the leaf surface and iteratively solving for the humidity at the leaf surface:

\[g_s*e_{sat}(T_L)*(1-h_s) = g_{bw}*(e_{sat}(T_L)h_s-e_{sat}(T_a)h_a),\]

where \(e_{sat}(T_L)\) and \(e_{sat}(T_a)\) are the saturated vapor pressure evaluated respectively at the leaf surface and air temperature (calculated according to the Tetens equation), and \(h_a\) is the air relative humidity outside the leaf boundary-layer.

The boundary-layer conductance \(g_H\) is summed over both faces of a two-sided primitive ( \(n_s=2\)), but the stomata on a face exchange gas only through the boundary layer of that face, whose conductance to water vapor is \(g_f=1.08g_H/n_s\). With a fraction \(z_1=\zeta\) of the stomata on the upper face and \(z_2=1-\zeta\) on the lower face, \(g_{bw}\) is the effective boundary-layer conductance that, in series with \(g_s\), carries the same flux as the stomata of each face in series with the boundary layer of that face:

\[g_{bw} = g_f\frac{\sum_k z_k/(g_f+z_kg_s)}{\sum_k z_k^2/(g_f+z_kg_s)}.\]

The leaf-surface humidity \(h_s\) and CO2 concentration \(C_s\) are then the stomata-weighted means over the two faces. For a hypostomatous leaf ( \(\zeta=0\)) or a one-sided primitive \(g_{bw}=g_f\), and for an amphistomatous leaf ( \(\zeta=0.5\)) \(g_{bw}=2g_f\). The boundary-layer conductance to CO2 \(g_{bc}\) is given by the same expression with \(g_f\) replaced by \(g_f/1.37\) and \(g_s\) by \(g_s/1.6\), where 1.37 and 1.6 are the ratios of the conductances to water vapor and CO2 through the boundary layer and the stomata, respectively, as conventionally used in leaf gas-exchange analysis (e.g., Cernusak et al. 2018). For other values of \(\zeta\) these conductances depend on \(g_s\), and the self-consistent \(g_s\) is found by bisection. A leaf-surface CO2 concentration \(C_s\le 0\) is an error only if it occurs even at the largest possible boundary-layer conductance, \(2g_f\). The total moisture conductance implied by \(g_s\) and \(g_{bw}\) is the same one used by the EnergyBalanceModel plug-in to calculate the latent heat flux.

Below are example parameter values for several different tree crop species (a description of how calibration data was collected is given in the section below). Note that, as mentioned above, in order to apply the model photosynthesis must also be modeled - coefficients for these species are also given in the photosynthesis model documentation.

Species \(g_{s,0}\) (mol air/m2-s) \(a_1\) (unitless) \(R^2\) of fit
Almond (default) 0.0733 9.422 0.976
Apple 0.0444 7.681 0.809
Cherry 0.0939 5.226 0.839
Prune 0.0425 7.120 0.917
Pear 0.0775 8.298 0.928
Pistachio (female) 0.0647 10.732 0.956
Pistachio (male) 0.0419 7.580 0.953
Walnut 0.1253 5.527 0.962

Ball-Berry-Leuning Model Theory

Leuning et al. (1990,1995) revised the original Ball, Woodrow, Berry model to overcome some of it's original limitations, namely the fact that \(g_s\) approaches infinity as \(C_s\rightarrow \infty\) by calculating stomatal conductance as

\[g_s = g_{s,0}+\frac{a_1A\beta}{\left(C_s-\Gamma\right)\left(1+\frac{D_s}{D_0}\right)},\]

where \(D_s\) is the vapor pressure deficit between the sub-stomatal cavity and the leaf surface, \(\Gamma\) is the CO2 compensation point of photosynthesis (including dark respiration), and \(D_0\) (mmol/mol) is an additional empirical parameter.

\(D_s\) is calculated by first determining the surface relative humidity as described above for the Ball, Woodrow, Berry model, then calculating the surface vapor pressure deficit as \(D_s=\frac{e_{sat}(T_L)(1-h_s)}{p_{atm}}\) ( \(p_{atm}\) is atmospheric pressure).

Below are example parameter values for several different tree crop species (a description of how calibration data was collected is given in the section below). Note that, as mentioned above, in order to apply the model photosynthesis must also be modeled - coefficients for these species are also given in the photosynthesis model documentation.

Species \(g_{s,0}\) (mol air/m2-s) \(a_1\) (unitless) \(D_0\) (mmol/mol) \(R^2\) of fit
Almond (default) 0.0743 4.265 14570.0 0.984
Apple 0.0405 3.511 32950.2 0.869
Cherry 0.0881 2.485 1578689.7 0.947
Prune 0.0425 3.185 30488.1 0.846
Pear 0.0814 3.718 61725.6 0.894
Pistachio (female) 0.0675 4.743 1566202.4 0.971
Pistachio (male) 0.0465 3.370 26990.8 0.934
Walnut 0.1248 4.548 21.4 0.977

Medlyn et al. (2011) Optimality-Based Model

The stomatal conductance mode of Medlyn et al. (2011) combines the empirical modeling approach with the hypothesis that stomata should act should act to optimally minimize the amount of water used per unit carbon gained.

\[g_s = g_{s,0}+1.6\left(1+\frac{g_1\sqrt{\beta}}{\sqrt{D_s P_{atm}}}\right)\frac{A}{C_s},\]

where \(D_s\) is in units of mol/mol, and \(P_{atm}\) is atmospheric pressure in kPa. Note that there are a couple of deviations of this equation from that presented in Medlyn et al. (2011): 1) The factor of 1.6 is needed for the resulting conductance to be that of water vapor, 2) We express \(D_s\) in units of mol/mol, and thus multiplication by the atmospheric pressure is needed to get units of kPa, 3) We use surface values for VPD and CO2 concentration, which allows for incorporation of boundary-layer effects.

One issue with this model is that stomatal conductance blows up to infinity as \(D_s\rightarrow 0\). Our implementation imposes an arbitrary minimum \(D_s\) value of 0.00001 mol/mol.

Below are example parameter values for several different tree crop species (a description of how calibration data was collected is given in the section below). Note that, as mentioned above, in order to apply the model photosynthesis must also be modeled - coefficients for these species are also given in the photosynthesis model documentation.

Species \(g_{s,0}\) (mol air/m2-s) \(g_1\) ( \(\sqrt{kPa}\)) \(R^2\) of fit
Almond (default) 0.0825 2.637 0.941
Apple 0.0426 2.160 0.864
Cherry 0.0936 1.043 0.893
Prune 0.0412 1.863 0.949
Pear 0.0775 2.418 0.966
Pistachio (female) 0.0756 3.252 0.902
Pistachio (male) 0.0434 2.039 0.941
Walnut 0.1246 1.167 0.973

Buckley, Mott, Farquhar (2003) Model (simplified version given in Buckley, Turnbull, and Adams 2012)

The stomatal conductance model of Buckley, Turnbull, and Adams (2012) is a simplification of the hydromechanical/biochemical model orignially proposed by Buckley, Mott, and Farquhar (2003). The original model is highly complex with many parameters, but with the simplifications described by Buckley, Turnbull, and Adams (2003), an explicit expression for stomatal conductance can be written as

\[g_s = \frac{E_m\beta(Q+i_0)}{k+bQ+(Q+i_0)D_s},\]

where \(Q\) is the photosynthetic photon flux density, \(D_s\) is defined and calculated as described for other models above, \(E_m,\,i_0,\,k,\) and \(b\) are semi-empirical parameters. Note that the photosynthetic flux that is input to the plug-in is in units of energy flux (W/m2), but \(Q\) in this equation is photon flux density ( \(\mu\)mol/m2-s). This is because the primitive data value output from the radiation model is in energy flux. The stomatal conductance plug-in automatically converts energy flux to photon flux density using a factor of 4.57 \(\mu\)mol/W.

Below are example parameter values for several different tree crop species (a description of how calibration data was collected is given in the section below).

Species \(E_m\) (mmol/m2-s) \(i_0\) ( \(\mu\)mol/m2-s) \(k\) ( \(\mu\)mol/m-2s-1 mmol mol-1) \(b\) (mmol/mol) \(R^2\) of fit
Almond (default) 865.52 38.65 780320.1 2086.07 0.991
Apple 24.82 182.86 109688.7 21.30 0.986
Cherry 138.03 154.24 262462.7 545.59 0.963
Prune 5.47 115.73 12280.2 6.10 0.993
Pear 13.06 167.89 25926.4 9.81 0.960
Pistachio (female) 24865.61 171.52 63444078.5 22428.01 0.968
Pistachio (male) 236.89 272.74 1224393.7 257.26 0.964
Walnut 29.12 68.03 19778.8 75.26 0.972

These coefficients can be applied by species name using setBMFCoefficientsFromLibrary() (all primitives, a subset of UUIDs, or a material label) or retrieved using getBMFCoefficientsFromLibrary(). Besides the species in the table above, the library also contains: Grape (cv. Cabernet Sauvignon), Elderberry, Toyon, Big_Leaf_Maple (or Maple), Western_Redbud (or Redbud), Baylaurel (or Bay_Laurel), Olive, and EasternRedbud. Pistachio female and male coefficients are requested as "PistachioFemale" (or "Pistachio") and "PistachioMale". Names may be given capitalized as listed or in all lower case. An unrecognized species name is an error, and the error message lists the valid names.

Bailey Model Theory

The Bailey model is a simplified hydromechanical model in which stomatal conductance is proportional to the guard cell turgor pressure \(P_g\):

\[g_s = \beta\chi P_g,\qquad P_g = \mathrm{max}\left(0,\,\pi_g+\Psi_e\right),\]

where \(\chi\) (mol/m2-s-MPa) is a proportionality constant. The guard cell osmotic pressure \(\pi_g\) increases with the photosynthetic photon flux density \(Q\) toward a saturating value, and both \(\pi_g\) and the epidermal water potential \(\Psi_e\) decrease as transpiration draws water through the xylem-to-epidermis hydraulic resistance:

\[\pi_g = \pi_0+\left(\pi_m-\pi_0\right)\frac{Q}{Q+\theta}+\sigma\left(\Psi_x-R_{xe}f_e g_s D_s\right),\]

\[\Psi_e = \Psi_x-R_{xe}f_e g_s D_s,\]

where \(\Psi_x\) is the xylem water potential (MPa), \(D_s\) is the vapor pressure deficit between the sub-stomatal cavity and the leaf surface (calculated as described for the other models above), \(f_e=0.5\) is the fraction of the epidermal water potential transmitted to the guard cells, and \(R_{xe}=200\) MPa m2 s/mol is the xylem-to-epidermis hydraulic resistance. \(f_e\) and \(R_{xe}\) are treated as fixed constants in this simplified form of the model. The parameters \(\pi_0,\,\pi_m,\,\theta,\,\sigma,\) and \(\chi\) are given by BBcoefficients.

Because \(g_s\) appears on both sides of these expressions but enters only linearly, the implicit relation is solved in closed form rather than iterated:

\[g_s = \beta\,\mathrm{max}\left(0,\,\frac{\chi\left[\pi_0+\left(\pi_m-\pi_0\right)\frac{Q}{Q+\theta}+\left(1+\sigma\right)\Psi_x\right]}{1+\chi\left(1+\sigma\right)R_{xe}f_eD_s}\right).\]

As with the other models, \(D_s\) is obtained by iteratively solving the water vapor flux balance at the leaf surface, so the Bailey model responds to the boundary-layer conductance. This model requires the xylem water potential (primitive data xylem_water_potential) rather than the net photosynthetic flux.

Note
Changed in helios-core 1.3.80: the Bailey model was rewritten. It is now coupled to the boundary layer in the same way as the other models — previously it used the air-to-cavity vapor pressure deficit directly and was the only model that ignored the boundary-layer conductance entirely. It also now applies the soil moisture factor \(\beta\), which it previously ignored (the beta_soil primitive data had no effect on Bailey model results). Bailey model results will therefore differ from earlier Helios versions.

Error Conditions

The plug-in follows a fail-fast philosophy: physically meaningless inputs produce an error rather than a silently substituted value. As of helios-core 1.3.80, run() raises an error if any of the following conditions is encountered.

Note that a boundary-layer conductance of exactly zero is not an error. It is physically attainable (a zero-size primitive, or zero wind speed) and is produced by the boundary-layer conductance plug-in in those cases. In that limit no water vapor can be exchanged with the air outside the boundary layer, so stomatal conductance no longer influences the transpiration rate and the steady-state value is taken to be \(g_s = 0\). A warning is issued rather than an error. A negative or non-finite boundary-layer conductance, by contrast, is an error.

ConditionReason
Boundary-layer conductance is negative or non-finite It appears in the denominator of both the surface CO2 balance and the vapor flux balance, and a negative value has no physical interpretation.
Ambient CO2 concentration (air_CO2) is zero, negative, or non-finite Not physically meaningful. (BWB, BBL, and Medlyn optimality models only.)
Surface CO2 concentration \(C_s\) evaluates to a non-positive value Occurs when the assimilation rate is too large to be supplied through the given boundary-layer conductance. All three \(A\)-based models divide by \(C_s\), so this would flip the sign of \(g_s\). Note that a negative \(A\) (dark respiration) legitimately gives \(C_s>C_a\) and is not an error.
\(C_s\le\Gamma\) in the Ball-Berry-Leuning model The model has a pole at \(C_s=\Gamma\), so approaching it produces an unbounded conductance.
A dynamic response time constant is zero, negative, or non-finite \(\tau\) appears in the denominator of the forward Euler update, and a negative value would invert the direction of the relaxation. Checked by setDynamicTimeConstants() for both the opening and closing time constants.

Using the Stomatal Conductance Model

Setting the Model Coefficients

Each model has a data structure containing member variables for each of the model parameters. These are listed in the table below.

Model Parameter Structure
Ball, Woodrow, Berry BWBcoefficients
Ball, Berry, Leuning BBLcoefficients
Medlyn et al. Optimality MOPTcoefficients
Buckley, Mott, Farquhar BMFcoefficients

In order to modify model coefficients from the default values, one should 1) declare and instance of the coefficient structure, 2) modify the appropriate data elements of the data structure, and 3) pass the data structure to the model-specific coefficient setting function (e.g., setBMFCoefficients()). Model coefficients can be set to the same value for all primitives, or differently for a subset of primitives based on a vector of UUIDs. Example code is given below


from pyhelios import BMFCoefficients
# BMFCoefficients is an immutable NamedTuple - all four values are supplied
# at construction. Use ._replace(...) to derive a modified copy.
modelcoeffs = BMFCoefficients(Em=9.3, i0=5.3, k=672, b=6.7)
# Apply to all primitives
stomatal.setBMFCoefficients(modelcoeffs)
# Or apply to specific primitives only
stomatal.setBMFCoefficients(modelcoeffs, uuids=[uuid1, uuid2, uuid3])

UUID-Based Coefficient Setting

PyHelios uses a UUID-based approach for setting coefficients to specific primitives. Coefficients can be applied to all primitives or to a subset specified by their UUIDs.

Setting coefficients for different species:

from pyhelios import Context, StomatalConductanceModel, WeberPennTree, WPTType
from pyhelios.types import vec3, vec2
with Context() as context:
# Create different tree species
with WeberPennTree(context) as wpt:
almond_tree_id = wpt.buildTree(WPTType.ALMOND, origin=vec3(0, 0, 0))
# Get UUIDs for almond tree leaves
almond_leaf_uuids = context.getAllUUIDs()
# Create grape leaves separately
grape_leaf_uuids = []
for i in range(10):
uuid = context.addPatch(center=vec3(5, i, 0), size=vec2(0.1, 0.1))
grape_leaf_uuids.append(uuid)
with StomatalConductanceModel(context) as stomatal:
# Set coefficients from species library for each group
stomatal.setBMFCoefficientsFromLibrary("Almond", uuids=almond_leaf_uuids)
stomatal.setBMFCoefficientsFromLibrary("Grape", uuids=grape_leaf_uuids)
# Run model - coefficients automatically applied based on UUIDs
stomatal.run()

You can also set custom coefficients for specific primitives:

from pyhelios import BMFCoefficients
custom_coeffs = BMFCoefficients(Em=500.0, i0=100.0, k=5000.0, b=1000.0)
# Apply to specific primitives only
stomatal.setBMFCoefficients(custom_coeffs, uuids=[uuid1, uuid2, uuid3])
# Or apply to all primitives
stomatal.setBMFCoefficients(custom_coeffs)

Per-Primitive Coefficient Lists (BMF)

For the BMF model, a list of coefficient sets can be passed together with an equal-length list of UUIDs; coeffs[i] is applied to uuids[i]. This is convenient for leaf-to-leaf variability. Each primitive in the call is also given the primitive data twoway_stomatal_conductance_flag = 1, and a warning is printed if a primitive already carried that flag (its coefficients are being overwritten).

base = stomatal.getBMFCoefficientsFromLibrary("Almond")
coeff_sets = [base._replace(Em=base.Em * f) for f in (0.8, 1.0, 1.2)]
stomatal.setBMFCoefficients(coeff_sets, uuids=[leaf1, leaf2, leaf3])

getBMFCoefficientsFromLibrary() returns a species' library values as a BMFCoefficients without applying them. An unrecognized species name raises StomatalConductanceModelError, and the error message lists the valid names.

Material-Based Coefficient Setting

All coefficient setters (setBWBCoefficients, setBBLCoefficients, setMOPTCoefficients, setBMFCoefficients, setBBCoefficients) and setBMFCoefficientsFromLibrary accept an optional material_label= keyword, mirroring the material support in the photosynthesis plugin. The coefficients are stored as material data on that Context material and apply to every primitive that references the material. material_label and uuids are mutually exclusive (passing both raises ValueError), and the material must already exist (context.addMaterial(...)), otherwise a StomatalConductanceModelError is raised.

context.addMaterial("sun_leaf")
context.addMaterial("shade_leaf")
context.assignMaterialToPrimitive(sun_leaf_uuids, "sun_leaf")
context.assignMaterialToPrimitive(shade_leaf_uuids, "shade_leaf")
with StomatalConductanceModel(context) as stomatal:
stomatal.setBMFCoefficientsFromLibrary("Almond", material_label="sun_leaf")
shade = stomatal.getBMFCoefficientsFromLibrary("Almond")._replace(Em=300.0)
stomatal.setBMFCoefficients(shade, material_label="shade_leaf")
stomatal.run()

Coefficient precedence. Coefficients are resolved for each primitive when run() is called, using the primitive's material at that moment, in this order:

  1. Coefficients set on the primitive's material via material_label= (all coefficients of the active model must be present on the material).
  2. Coefficients set for the primitive's UUID via uuids= (including the per-UUID list form).
  3. Coefficients set for all primitives (no uuids / material_label), or the built-in defaults.

Material coefficients therefore override per-UUID coefficients, regardless of the order of the calls. Because primitives created without an explicit material may share a common default material, assign a dedicated material (as above) before setting coefficients by label, so that only the intended primitives are affected.

Active model. Every coefficient setter, including the material-label form, also selects which of the five models run() evaluates for all primitives (the model of the most recent call wins). Different materials cannot run different models in the same run(); use material labels to vary the coefficients of a single model.

Running the Model (steady-state mode)

There are two possible functions to run the model: one to run the model for all primitives in the Context (see run()), and another to run the model only for a subset of primitives given their UUIDs (see run()).

from pyhelios import Context, StomatalConductanceModel, BMFCoefficients
from pyhelios.types import vec3, vec2
# Initialize the Context and add some geometry
with Context() as context:
context.addPatch(center=vec3(0, 0, 0), size=vec2(1, 1))
# Initialize the stomatal conductance model
with StomatalConductanceModel(context) as stomatal:
# Initialize model coefficients and modify their values
# BMFCoefficients is immutable; these are the model default values.
modelcoeffs = BMFCoefficients(Em=258.25, i0=38.65, k=232916.82, b=609.67)
# _replace() returns a copy with one or more parameters changed
modelcoeffs = modelcoeffs._replace(Em=9.3, i0=5.3, k=672, b=6.7)
stomatal.setBMFCoefficients(modelcoeffs)
# -- Normally you would initialize and run some other models (e.g., radiation, energybalance) here --
# Run the stomatal conductance model (for all primitives)
stomatal.run()

Running the Model in Dynamic Mode

Any of the above steady-state models can be run in dynamic mode by specifying a timestep and response time constants, which will delay stomatal response to environmental stimuli. When environmental conditions are changed, the stomatal conductance will exponentially relax toward the steady-state value, which is calculated according to any of the above models.

Let the steady-state stomatal conductance value calculated according to any of the above models be denoted by \(g_{s,ss}\). Then the dynamic stomatal conductance is calculated according to the following equation

\[\dfrac{d g_s}{dt} = \dfrac{g_{s,ss} - g_s}{\tau},\]

where

\(\tau\) is the time constant for stomatal response to a change in environmental conditions, and \(\tau = \tau_{open}\) if stomata are opening, and \(\tau = \tau_{close}\) if stomata are closing.

The above equation can be discretized using a forward Euler scheme to update the stomatal conductance after each timestep \(\Delta t\) as

\[g_s^{new} = g_s^{old} + \dfrac{g_{s,ss} - g_s^{old}}{\tau}\Delta t.\]

The response time constants \(\tau_{open}\) and \(\tau_{close}\) are specified using the setDynamicTimeConstants() method. If time constants are not defined, a warning will be issued and the model will run in steady-state mode.

The model also requires an initial stomatal conductance value, which is specified by setting primitive data "moisture_conductance". If this primitive data is not defined, the model will run in steady-state mode for the first timestep, and this steady-state value will become the initial value for running in dynamic mode.

Below is and example of running the model in dynamic mode.

from pyhelios import Context, StomatalConductanceModel, BMFCoefficients
# Initialize the Context and add some geometry
with Context() as context:
UUID = context.addPatch()
# Initialize the stomatal conductance model
with StomatalConductanceModel(context) as stomatal:
# Initialize model coefficients with default values
# BMFCoefficients is immutable; these are the model default values.
modelcoeffs = BMFCoefficients(Em=258.25, i0=38.65, k=232916.82, b=609.67)
stomatal.setBMFCoefficients(modelcoeffs)
# Set the response time constants (seconds)
tau_open = 10
tau_close = 10
stomatal.setDynamicTimeConstants(tau_open, tau_close)
# Set the initial stomatal conductance value
gs_initial = 0.2
context.setPrimitiveDataFloat(UUID, "moisture_conductance", gs_initial)
dt = 1 # timestep (seconds)
Nsteps = 50 # number of timesteps to run
for t in range(Nsteps):
# Run the model for each timestep
stomatal.run(dt)
# Get and print the stomatal conductance value
gs_dyn = context.getPrimitiveData(UUID, "moisture_conductance")
print(f"Timestep {t}: {gs_dyn}")