![]() |
0.1.39
|
| Dependencies | None |
|---|---|
| Python Import | from pyhelios import PlantHydraulicsModel |
| Main Class | PlantHydraulicsModel |
PlantHydraulicsModel computes the water potential of the root and stem of each plant, and the water potential, relative water content, turgor pressure and osmotic potential of each of its leaf primitives. The plugin operates on a group of leaf primitives and treats the stem and the root each as a single compartment associated with those leaves, with soil water potential as an environmental input set by the user. The leaf quantities are computed for each leaf primitive from its transpiration, temperature and hydraulic model parameters.
Leaves are grouped into plants by a "plantID". It is read from the object data of a primitive's parent object, or from the primitive's own data, and can be assigned by this plugin or generated by other plugins such as Plant Architecture.
| Dependencies | None |
|---|---|
| Platforms | Windows, Linux, macOS |
| GPU | Not required |
timespan > 0) is under construction in the native plugin.getModelCoefficients(UUID) reads only coefficients that were set for specific primitives. The model-wide coefficients cannot be read back, so it raises for a primitive that has none of its own.| Primitive Data Label | Symbol | Units | Data Type | Description | Available Plugins | Default Value |
|---|---|---|---|---|---|---|
| temperature | \(T_s\) | Kelvin | float | Primitive surface temperature | Can be computed by Energy Balance Model | 300 K |
| latent_flux | \(E\) | W/m² | float | Latent heat flux (transpiration) | Can be computed by Energy Balance Model | 0 |
| water_potential | \(\psi\) | MPa | float | Leaf water potential at which a water-potential dependent leaf conductance is evaluated | Output of a previous run of this plugin | -0.001 MPa |
| relative_water_content | \(w\) | unitless | float | Initial leaf relative water content. Read by non-steady-state runs only. | Output of a previous run of this plugin | 1.0 |
| air_temperature | \(T_a\) | Kelvin | float | Temperature of the stem; the root is taken to be 5 K cooler. Used only when stem or root conductance is temperature dependent, and read from a single primitive, the one with the lowest UUID in the plant. | N/A | 298.15 K |
"temperature" is used only for a temperature-dependent leaf conductance.
| Object Data Label | Symbol | Units | Data Type | Description | Available Plugins | Default Value |
|---|---|---|---|---|---|---|
| plantID | N/A | N/A | int | Unique plant identification number | Can be generated by Plant Architecture | N/A |
The default of 0 for "latent_flux" applies to an individual leaf's own water potential. A plant's transpiration, which sets its root and stem water potentials, is the area-weighted mean of "latent_flux" over only those primitives of the plant that have it. If none of them do, the plant transpires nothing and its root and stem water potentials equal the soil water potential. "latent_flux" must be set as a float.
Water-potential dependent conductances are evaluated once per run, at the water potentials from before the run: the "water_potential" primitive data for leaves, and the root and stem water potentials stored in the model from its previous run for that plant (-0.001 MPa before the first run). A steady-state run is therefore not iterated to a self-consistent solution, and repeated runs with identical inputs give different results when a conductance depends on water potential.
| Primitive Data Label | Symbol | Units | Data Type | Description |
|---|---|---|---|---|
| water_potential | \(\psi\) | MPa | float | Water potential |
| relative_water_content | \(w\) | unitless | float | Relative water content |
| turgor_pressure | \(p\) | MPa | float | Cellular turgor pressure |
| osmotic_potential | \(\pi\) | MPa | float | Cellular osmotic potential |
These are enabled with outputConductancePrimitiveData(True) and outputCapacitancePrimitiveData(True), and are written by non-steady-state runs only.
| Primitive Data Label | Symbol | Units | Data Type | Description |
|---|---|---|---|---|
| hydraulic_conductance | \(K\) | mol m \(^{-2}\) s \(^{-1}\) MPa \(^{-1}\) | float | Hydraulic conductance |
| hydraulic_capacitance | \(C\) | mol m \(^{-2}\) MPa \(^{-1}\) | float | Hydraulic capacitance |
Primitives that share a plantID are treated as the leaves of one plant, with one shared stem, root and soil water potential. getPlantID() takes the plantID of a primitive from the object data "plantID" of its parent object if present, otherwise from the primitive data "plantID". The primitives of a plant are all those in the Context whose parent object data or primitive data "plantID" equals the plant's ID, so a primitive carrying different values in the two places belongs to both plants; avoid setting both.
The model runs for every plant that the primitives passed to run() belong to, and writes its output data to all primitives of those plants, not only to the primitives passed. Where non-leaf primitives carry the plantID (for example the internodes of a Plant Architecture plant), they are treated as leaves and receive output data too.
Primitives passed to run() that have no plantID are grouped into one new plant:
run() raises PlantHydraulicsModelError. This is the case for the primitives of a tile or other compound object, or of Plant Architecture organs, that have no plantID. Set "plantID" on them yourself before running.Calling run() with no UUIDs applies this to every primitive in the Context, so a ground surface or other non-plant geometry without a plantID becomes part of a plant. Pass the leaf UUIDs instead when the Context holds other geometry.
To control the grouping yourself, set "plantID" as object data or primitive data before running, or call groupPrimitivesIntoPlantObject(), which performs the grouping described above and returns the new plantID. It raises ValueError if any of the primitives already has a plantID.
When the geometry comes from the Plant Architecture plugin, call optionalOutputObjectData("plantID") before building plants so that the leaves carry the ID of their plant (see the examples below), and pass the leaf UUIDs to run(). Not every organ of the plant receives a plantID, so calling run() with no UUIDs on such a Context can fail as described above.
Plant transpiration, \(E_{plant}\) (mol m \(^{-2}\) s \(^{-1}\)), is first obtained by aggregating the latent heat fluxes \(E_i\) (W m \(^{-2}\)) of the \(n\) primitives of the plant that have "latent_flux" data, weighted by their area \(a_i\) (m \(^2\)), and converting to a molar flux with the latent heat of vaporization of water, \(\lambda\) = 44000 J mol \(^{-1}\):
\[E_{plant} = \frac{1}{\lambda}\frac{\sum_{i=1}^n E_i a_i}{\sum_{i=1}^n a_i}. \]
Stem and root water potentials, \(\psi_{stem}\) and \(\psi_{root}\) (MPa), are then solved for given \(E_{plant}\) and soil water potential, \(\psi_{soil}\), using
\[C(\psi_{root})\frac{d\psi_{root}}{dt} = K_{root}(\psi_{soil}-\psi_{root}) - K_{stem}(\psi_{root}-\psi_{stem}) \]
\[C(\psi_{stem})\frac{d\psi_{stem}}{dt} = K_{stem}(\psi_{root}-\psi_{stem}) - E_{plant}, \]
where \(C(\psi)\) and \(K(\psi)\) are the hydraulic capacitance and conductance, which depend on the current water status. When a timespan is specified, a backward Euler scheme solves the equations implicitly. When no timespan is specified, the steady-state water potentials are solved with \(\frac{d\psi}{dt}=0\):
\[\psi_{root} = \psi_{soil} - \frac{E_{plant}}{K_{root}} \]
\[\psi_{stem} = \psi_{root} - \frac{E_{plant}}{K_{stem}}. \]
The steady-state water potential of each leaf follows from the stem water potential and the leaf's own latent heat flux,
\[\psi_{leaf,i} = \psi_{stem} - \frac{E_i}{\lambda K_{leaf}}. \]
Each compartment (leaf, stem and root) has a parameterized hydraulic conductance \(K(\psi)\) and capacitance \(C(\psi)\). Conductance is modeled as a symmetric sigmoid of the form
\[K(\psi) = K_{max}\left(1+\left|\frac{\psi}{\psi_{50}}\right|^s\right)^{-1}, \]
where \(K_{max}\) is the maximal conductance, \(\psi_{50}\) is the water potential giving half of \(K_{max}\), and \(s\) controls the steepness. An optional temperature dependence adjusts conductance as \(K(\psi,T) = K(\psi) \cdot \left(\frac{T}{298.15}\right)^7\), where \(T\) is the primitive data "temperature" for a leaf, "air_temperature" for the stem, and "air_temperature" minus 5 K for the root.
The slope of the leaf pressure-volume relation defines the hydraulic capacitance, \(C(\psi) = \frac{\partial w}{\partial \psi} W_{sat}\). Water potential ( \(\psi\), MPa) as a function of relative water content ( \(w\), unitless) is the sum of turgor pressure ( \(p\), MPa) and osmotic potential ( \(\pi\), MPa),
\[\psi(w)=p(w)+\pi(w) = -\pi_o \max\left(0,\frac{w-w_{tlp}}{1-w_{tlp}}\right)^\epsilon + \frac{\pi_o}{w}, \]
where turgor pressure is parameterized by a saturated turgor pressure equal to the saturated osmotic pressure \(-\pi_o\) at \(w=1\), the relative water content at the turgor loss point, \(w_{tlp}\) (Sack et al. 2018), and an empirical compartmental wall elasticity, \(\epsilon\). Osmotic potential is the saturated osmotic pressure divided by relative water content, \(\frac{\pi_o}{w}\) ( \(\pi_o\) is itself negative).
Osmotic potential at full turgor is given to the model as a single parameter. The model does not compute it, but it can be estimated from the moles of osmotica per area, \(n_o\), and the saturated specific water content, \(W_{sat}\), which together with \(w\) give the osmotic concentration \(c = \frac{n_o \rho_w}{wW_{sat}\mu_w}\) in the van 't Hoff relationship \(\pi = -icRT\) with \(i=1\), the molar mass \(\mu_w\) and density \(\rho_w\) of water, and a conversion from Pa to MPa, \(\Upsilon\):
\[\pi_o = -\frac{n_o RT}{W_{sat}}\frac{\rho_w \Upsilon}{\mu_w}. \]
| Parameter | Description | Units | Default Value |
|---|---|---|---|
| \(K_{max}\) | maximum hydraulic conductance of leaf, stem or root | mol m \(^{-2}\) s \(^{-1}\) MPa \(^{-1}\) | 0.5 |
| \(\psi_{50}\) | water potential at which conductance is half of its maximum | MPa | N/A |
| \(s\) | steepness of conductance change with water potential around \(\psi_{50}\) | unitless | N/A |
(The \(K_{max}\) values in the figure legends are in mmol m \(^{-2}\) s \(^{-1}\) MPa \(^{-1}\); the axes are in mol m \(^{-2}\) s \(^{-1}\) MPa \(^{-1}\), the unit the model takes. Data from Hernandez-Santana et al. 2016).
| Parameter | Description | Units | Default Value |
|---|---|---|---|
| \(\pi_o\) | osmotic potential at full turgor | MPa | -2.0 |
| \(w_{tlp}\) | relative water content at turgor loss point | unitless | 0.8 |
| \(\epsilon\) | empirical cell wall elasticity coefficient | unitless | 1.0 |
| \(W_{sat}\) | specific water content at \(w=1\) | mol m \(^{-2}\) | 1.0 |
The figure legends show the fitted parameters rounded. The values used by the species library are listed under Species Library below, and differ slightly from the legends (for western redbud, \(\epsilon\) is 1.5 in the library and 1.51 in the figure).
The model itself uses one physical constant:
| Parameter | Description | Units | Value |
|---|---|---|---|
| \(\lambda\) | latent heat of vaporization of water | J mol \(^{-1}\) | 44000 |
The following constants appear only in the estimate of \(\pi_o\) given under Governing Equations, which the model does not evaluate:
| Parameter | Description | Units | Value |
|---|---|---|---|
| \(R\) | gas constant | J mol \(^{-1}\) K \(^{-1}\) | 8.314 |
| \(\mu_w\) | molar mass of water | g mol \(^{-1}\) | 18.015 |
| \(\rho_w\) | density of water | g m \(^{-3}\) | 10 \(^{6}\) |
| \(\Upsilon\) | Pa to MPa | MPa Pa \(^{-1}\) | 10 \(^{-6}\) |
Leaf pressure-volume curve parameters are available for the following species. Each can be given by any of the listed names; any other name raises ValueError.
| Species | Accepted Names | \(\pi_o\) (MPa) | \(w_{tlp}\) | \(\epsilon\) |
|---|---|---|---|---|
| Walnut | Walnut, walnut | -1.6386 | 0.7683 | 2.0 |
| Pistachio (female) | PistachioFemale, pistachiofemale, pistachio_female, Pistachio_Female, Pistachio_female, pistachio, Pistachio | -3.096 | 0.7652 | 2.0 |
| Elderberry | Elderberry, elderberry, blue_elderberry | -2.011 | 0.8135 | 2.0 |
| Western Redbud | Western_Redbud, western_redbud, Redbud, redbud | -2.1963 | 0.8872 | 1.5 |
The library can be applied to the whole model, leaving all other coefficients at their defaults, or to the leaf capacitance of a coefficients object:
Coefficients are collected in a PlantHydraulicsModelCoefficients object. Each compartment's conductance can be constant or a function of water potential. Capacitance is used as follows:
Leaf conductance and capacitance can also be set for a subset of leaves, which then use them in place of the model-wide values. Stem and root water potentials are always computed from the model-wide coefficients, so the stem and root settings of coefficients given for specific primitives are not used:
Setting model-wide coefficients clears any coefficients previously set for specific primitives.
getModelCoefficientsFromLibrary() returns a species' library coefficients as a new PlantHydraulicsModelCoefficients, which can be inspected, modified and passed to setModelCoefficients(). getModelCoefficients(UUID) returns the coefficients set for one primitive:
Leaf capacitance taken from the species library comes back as its pressure-volume curve parameters, with leaf_capacitance_species set to None. getModelCoefficients() raises PlantHydraulicsModelError for a primitive that has no coefficients of its own, since it uses the model-wide ones.
The examples below use the Plant Architecture plugin to create the leaves. optionalOutputObjectData("plantID") makes the leaves carry the plantID of their plant, which the hydraulics model uses to group them. It must be called before the plant is built.
The curve functions used by the model are available directly, for example to plot a pressure-volume curve or to check a parameterization:
docs/examples/planthydraulics_wilting_movie.py couples the model to radiation, stomatal conductance and the energy balance over one day for a tomato plant, and sets the leaf angle distribution and petiole droop of the plant from the computed turgor pressure at each timestep. It renders a movie of the plant wilting in the afternoon and recovering in the evening, which is a quick visual check of the model's output.
Invalid arguments (an unknown species, a non-positive conductance, an empty UUID list) raise ValueError before the model is called. Failures in the model itself, such as querying the stem water potential of a plant the model has not been run for, raise PlantHydraulicsModelError.
If creating a PlantHydraulicsModel reports that the plugin is not available, check whether it is in the native library, and rebuild if it is not:
getPlantID() and getUniquePlantIDs() raise PlantHydraulicsModelError if a primitive has neither parent object data nor primitive data "plantID". Set "plantID" yourself, as object data on the parent object or as primitive data. For primitives that do not belong to any object, you can instead call groupPrimitivesIntoPlantObject() or run the model on them, which groups them into a plant.
run() and groupPrimitivesIntoPlantObject() raise this when all of the primitives without a plantID already belong to an object (see Grouping Leaves into Plants). Set "plantID" on those primitives or their parent objects yourself.
The list forms of getPlantID() and the water potential getters expect the leaves of a single plant. Use getUniquePlantIDs() and the ...OfPlant(plantID) getters when working with several plants.
Runs with timespan > 0 raise PlantHydraulicsModelError unless the stem and root capacitances are constants (setStemHydraulicCapacitance(C), setRootHydraulicCapacitance(C)).