3#include "../framework/constants.h"
4#include "../framework/quadratic_root.h"
8#include "../math/roots/onedim/dekker.h"
11using physical_constants::dr_boundary;
12using physical_constants::dr_stomata;
24 double const leaf_temperature,
25 double const ambient_temperature,
26 double const relative_humidity,
27 double const Vcmax_at_25,
32 double const RL_at_25,
38 double const atmospheric_pressure,
45 double const inf = std::numeric_limits<double>::infinity();
49 throw std::out_of_range(
"Input `absorbed_ppfd` cannot be negative. Check `solar` is not negative.");
52 constexpr double k_Q10 = 2;
54 double const Ca_pa = Ca * 1e-6 * atmospheric_pressure;
56 double const kT = kparm * pow(k_Q10, (leaf_temperature - 25.0) / 10.0);
59 double const Vtn = Vcmax_at_25 * pow(2, (leaf_temperature - 25.0) / 10.0);
60 double const Vtd = (1 + exp(0.3 * (lowerT - leaf_temperature))) * (1 + exp(0.3 * (leaf_temperature - upperT)));
61 double const VT = Vtn / Vtd;
64 double const Rtn = RL_at_25 * pow(2, (leaf_temperature - 25) / 10);
65 double const Rtd = 1 + exp(1.3 * (leaf_temperature - 55));
66 double const RT = Rtn / Rtd;
69 double const b0 = VT * alpha * Qp;
70 double const b1 = -(VT + alpha * Qp);
71 double const b2 = theta;
75 double const M = quadratic_root_min(b2, b1, b0);
78 double const bb0_adj = StomaWS * bb0 + Gs_min * (1.0 - StomaWS);
79 double const bb1_adj = StomaWS * bb1;
83 auto collatz_assim = [=](
double const InterCellularCO2) {
85 double kT_IC_P = kT * InterCellularCO2 / atmospheric_pressure * 1e6;
87 double b = -(M + kT_IC_P);
88 double c = M * kT_IC_P;
92 double gross_assim = quadratic_root_min(a, b, c);
93 return gross_assim - RT;
104 auto check_assim_rate = [=, &BB_res, &Assim, &Gs](
double Ci_pa) {
107 Assim = collatz_assim(Ci_pa);
122 ambient_temperature);
131 return Gt * (Ca_pa - Ci_pa) / atmospheric_pressure * 1e6 - Assim;
136 double const Ci_max =
137 Ca_pa + 1e-6 * atmospheric_pressure * RT *
138 (dr_boundary / gbw + dr_stomata / bb0_adj);
140 using namespace root_finding;
141 dekker solver(500, 1e-12, 1e-12);
142 result_t result = solver.solve(
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));
157 double const Ci = result.root / atmospheric_pressure * 1e6;
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)
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)