The BioCro C++ Library
c4photo.cpp
Go to the documentation of this file.
1#include <cmath> // for pow, exp
2#include <limits> // for std::numeric_limits
3#include "../framework/constants.h" // for dr_stomata, dr_boundary
4#include "../framework/quadratic_root.h" // for quadratic_root_min
5#include "ball_berry_gs.h" // for ball_berry_gs
6#include "conductance_helpers.h" // for sequential_conductance
7#include "conductance_limited_assim.h" // for conductance_limited_assim
8#include "../math/roots/onedim/dekker.h" // for dekker
9#include "c4photo.h"
10
11using physical_constants::dr_boundary;
12using physical_constants::dr_stomata;
13
14/*
15 The secant method is used to solve for assimilation, Ci, and stomatal conductance,
16 because of known convergence issues when using fixed-point iteration, based on
17 Sun et al. (2012) "A numerical issue in calculating the coupled carbon and
18 water fluxes in a climate model." *Journal of Geophysical Research*
19 https://dx.doi.org/10.1029/2012JD018059
20
21*/
23 double const Qp, // micromol / m^2 / s
24 double const leaf_temperature, // degrees C
25 double const ambient_temperature, // degrees C
26 double const relative_humidity, // dimensionless from Pa / Pa
27 double const Vcmax_at_25, // micromol / m^2 / s
28 double const alpha, // mol / mol
29 double const kparm, // mol / m^2 / s
30 double const theta, // dimensionless
31 double const beta, // dimensionless
32 double const RL_at_25, // micromol / m^2 / s
33 double const bb0, // mol / m^2 / s
34 double const bb1, // dimensionless from [mol / m^2 / s] / [mol / m^2 / s]
35 double const Gs_min, // mol / m^2 / s
36 double const StomaWS, // dimensionless
37 double const Ca, // micromol / mol
38 double const atmospheric_pressure, // Pa
39 double const upperT, // degrees C
40 double const lowerT, // degrees C
41 double const gbw // mol / m^2 / s
42)
43{
44 // Define infinity
45 double const inf = std::numeric_limits<double>::infinity();
46
47 // Check inputs
48 if (Qp < 0) {
49 throw std::out_of_range("Input `absorbed_ppfd` cannot be negative. Check `solar` is not negative.");
50 }
51
52 constexpr double k_Q10 = 2; // dimensionless. Increase in a reaction rate per temperature increase of 10 degrees Celsius.
53
54 double const Ca_pa = Ca * 1e-6 * atmospheric_pressure; // Pa
55
56 double const kT = kparm * pow(k_Q10, (leaf_temperature - 25.0) / 10.0); // mol / m^2 / s
57
58 // Collatz 1992. Appendix B. Equation set 5B.
59 double const Vtn = Vcmax_at_25 * pow(2, (leaf_temperature - 25.0) / 10.0); // micromol / m^2 / s
60 double const Vtd = (1 + exp(0.3 * (lowerT - leaf_temperature))) * (1 + exp(0.3 * (leaf_temperature - upperT))); // dimensionless
61 double const VT = Vtn / Vtd; // micromol / m^2 / s
62
63 // Collatz 1992. Appendix B. Equation set 5B.
64 double const Rtn = RL_at_25 * pow(2, (leaf_temperature - 25) / 10); // micromol / m^2 / s
65 double const Rtd = 1 + exp(1.3 * (leaf_temperature - 55)); // dimensionless
66 double const RT = Rtn / Rtd; // micromol / m^2 / s
67
68 // Collatz 1992. Appendix B. Quadratic coefficients from Equation 2B.
69 double const b0 = VT * alpha * Qp;
70 double const b1 = -(VT + alpha * Qp);
71 double const b2 = theta;
72
73 // Calculate the smaller of the two quadratic roots, as mentioned following
74 // Equation 3B in Collatz 1992.
75 double const M = quadratic_root_min(b2, b1, b0); // micromol / m^2 / s
76
77 // Adjust Ball-Berry parameters in response to water stress
78 double const bb0_adj = StomaWS * bb0 + Gs_min * (1.0 - StomaWS);
79 double const bb1_adj = StomaWS * bb1;
80
81 // Function to compute the biochemical assimilation rate according to the
82 // Collatz model. Here, InterCellularCO2 should be expressed in Pa.
83 auto collatz_assim = [=](double const InterCellularCO2) {
84 // Collatz 1992. Appendix B. Quadratic coefficients from Equation 3B.
85 double kT_IC_P = kT * InterCellularCO2 / atmospheric_pressure * 1e6; // micromol / m^2 / s
86 double a = beta;
87 double b = -(M + kT_IC_P);
88 double c = M * kT_IC_P;
89
90 // Calculate the smaller of the two quadratic roots, as mentioned
91 // following Equation 3B in Collatz 1992.
92 double gross_assim = quadratic_root_min(a, b, c); // micromol / m^2 / s
93 return gross_assim - RT; // micromol / m^2 / s
94 };
95
96 // Initialize loop variables. These will be updated as a side effect during
97 // the secant method's iterations.
98 stomata_outputs BB_res;
99 double Assim{0}; // micromol / mol (initial guess)
100 double Gs{1e3}; // mol / m^2 / s (initial guess)
101
102 // This lambda function equals zero only if Ci satisfies both the Collatz
103 // and Ball-Berry models. Here, Ci_pa should be expressed in Pa.
104 auto check_assim_rate = [=, &BB_res, &Assim, &Gs](double Ci_pa) {
105 // Use Ci to compute the assimilation rate according to the Collatz
106 // model.
107 Assim = collatz_assim(Ci_pa);
108
109 // Use Assim to compute the stomatal conductance according to the
110 // Ball-Berry model. If Assim is too high, Cs will take a negative
111 // value, which is not allowed by the Ball-Berry model. To avoid this,
112 // we clamp Assim to the value that produces Cs = 0; this will result
113 // in Gs = infinity.
114 BB_res = ball_berry_gs(
115 std::min(Assim, conductance_limited_assim(Ca, gbw, inf)) * 1e-6,
116 Ca * 1e-6,
117 relative_humidity,
118 bb0_adj,
119 bb1_adj,
120 gbw,
121 leaf_temperature,
122 ambient_temperature);
123
124 Gs = BB_res.gsw; // mol / m^2 / s
125
126 // Using Ci and Gs, make a new estimate of the assimilation rate. If
127 // the initial value of Ci was correct, this should be identical to
128 // Assim.
129 double Gt = sequential_conductance(gbw / dr_boundary, Gs / dr_stomata); // mol / m^2 / s
130
131 return Gt * (Ca_pa - Ci_pa) / atmospheric_pressure * 1e6 - Assim; // micromol / m^2 / s
132 };
133
134 // Max possible Ci value
135
136 double const Ci_max =
137 Ca_pa + 1e-6 * atmospheric_pressure * RT *
138 (dr_boundary / gbw + dr_stomata / bb0_adj); // Pa
139 // Run the dekker method
140 using namespace root_finding;
141 dekker solver(500, 1e-12, 1e-12);
142 result_t result = solver.solve(
143
144 check_assim_rate,
145 0.5 * Ca_pa,
146 0,
147 Ci_max * 1.01);
148
149 // throw exception if not converged
150 if (!is_successful(result.flag)) {
151 throw std::runtime_error(
152 "Ci solver reports failed convergence with termination flag:\n " +
153 flag_message(result.flag));
154 }
155
156 // Get final values
157 double const Ci = result.root / atmospheric_pressure * 1e6; // micromol / mol
158 double const an_conductance = conductance_limited_assim(Ca, gbw, Gs); // micromol / m^2 / s
159
161 /* .Assim = */ Assim, // micromol / m^2 /s
162 /* .Assim_check = */ result.residual, // micromol / m^2 / s
163 /* .Assim_conductance = */ an_conductance, // micromol / m^2 / s
164 /* .Ci = */ Ci, // micromol / mol
165 /* .Cs = */ BB_res.cs, // micromol / m^2 / s
166 /* .GrossAssim = */ Assim + RT, // micromol / m^2 / s
167 /* .Gs = */ Gs, // mol / m^2 / s
168 /* .RHs = */ BB_res.hs, // dimensionless from Pa / Pa
169 /* .RL = */ RT, // micromol / m^2 / s
170 /* .Rp = */ 0, // micromol / m^2 / s
171 /* .iterations = */ result.iteration // not a physical quantity
172 };
173}
stomata_outputs ball_berry_gs(double assimilation, double ambient_c, double ambient_rh, double bb_offset, double bb_slope, double gbw, double leaf_temperature, double ambient_air_temperature)
Calculates steady-state stomatal conductance to water vapor using the Ball-Berry model.
photosynthesis_outputs c4photoC(double const Qp, double const leaf_temperature, double const ambient_temperature, double const relative_humidity, double const Vcmax_at_25, double const alpha, double const kparm, double const theta, double const beta, double const RL_at_25, double const bb0, double const bb1, double const Gs_min, double const StomaWS, double const Ca, double const atmospheric_pressure, double const upperT, double const lowerT, double const gbw)
Definition: c4photo.cpp:22
double sequential_conductance(double const conductance_1, double const conductance_2)
Calculates the total conductance across two sequential gas paths.
double conductance_limited_assim(double Ca, double gbw, double gsw)
Computes the conductance-limited net CO2 assimilation rate.
A simple structure for holding the output of photosynthesis calculations.
A simple structure for holding the output of stomatal conductance calculations.
double gsw
Stomatal conductance to water vapor (mmol / m^2 / s)
double hs
Relative humidity at the leaf surface (dimensionless)
double cs
CO2 concentration at the leaf surface (micromol / mol)