From 183a872f49f270c330c995cab066b6ba22cfb1b6 Mon Sep 17 00:00:00 2001 From: itowers1 <39288928+itowers1@users.noreply.github.com> Date: Fri, 28 Jun 2024 15:37:26 +1000 Subject: [PATCH 1/6] add leaf mods --- inst/RcppR6_classes.yml | 133 +++++++++ inst/include/plant/control.h | 6 + inst/include/plant/leaf_model.h | 225 +++++++++++++++ src/control.cpp | 5 + src/leaf_model.cpp | 472 ++++++++++++++++++++++++++++++++ tests/testthat/test-control.R | 7 +- tests/testthat/test-leaf.r | 398 +++++++++++++++++++++++++++ 7 files changed, 1245 insertions(+), 1 deletion(-) create mode 100644 inst/include/plant/leaf_model.h create mode 100644 src/leaf_model.cpp create mode 100644 tests/testthat/test-leaf.r diff --git a/inst/RcppR6_classes.yml b/inst/RcppR6_classes.yml index 835694b2..3922e81c 100644 --- a/inst/RcppR6_classes.yml +++ b/inst/RcppR6_classes.yml @@ -1,3 +1,132 @@ +Leaf: + name_cpp: "plant::Leaf" + constructor: + args: + - vcmax_25: double + - c: double + - b: double + - psi_crit: double + - beta2: double + - jmax_25: double + - hk_s: double + - a: double + - curv_fact_elec_trans: double + - curv_fact_colim: double + - GSS_tol_abs: double + - vulnerability_curve_ncontrol: double + - ci_abs_tol: double + - ci_niter: double + + active: + ci_: {type: double, access: field} + stom_cond_CO2_: {type: double, access: field} + assim_colimited_: {type: double, access: field} + transpiration_: {type: double, access: field} + profit_: {type: double, access: field} + psi_stem: {type: double, access: field} + lambda_: {type: double, access: field} + lambda_analytical_: {type: double, access: field} + electron_transport_: {type: double, access: field} + gamma_: {type: double, access: field} + ko_: {type: double, access: field} + kc_: {type: double, access: field} + km_: {type: double, access: field} + R_d_: {type: double, access: field} + leaf_specific_conductance_max_: {type: double, access: field} + vcmax_: {type: double, access: field} + jmax_: {type: double, access: field} + rho_: {type: double, access: field} + a_bio_: {type: double, access: field} + PPFD_: {type: double, access: field} + atm_vpd_: {type: double, access: field} + ca_: {type: double, access: field} + psi_soil_: {type: double, access: field} + leaf_temp_: {type: double, access: field} + atm_o2_kpa_: {type: double, access: field} + atm_kpa_: {type: double, access: field} + hydraulic_cost_: {type: double, access: field} + opt_psi_stem_: {type: double, access: field} + opt_ci_: {type: double, access: field} + count: {type: double, access: field} + + methods: + initialize_integrator: + return_type: void + args: [integration_rule: int, integration_tol: double] + set_physiology: + return_type: void + args: [rho: double, a_bio: double, PPFD: double, psi_soil: double, leaf_specific_conductance_max: double, atm_vpd: double, ca: double, sapwood_volume_per_leaf_area: double, leaf_temp: double, atm_o2_kpa: double, atm_kpa: double] + #transpiration functions + proportion_of_conductivity: + return_type: double + args: [psi: double] + arrh_curve: + return_type: double + args: [Ea: double, ref_value: double, leaf_temp: double] + peak_arrh_curve: + return_type: double + args: [Ea: double, ref_value: double, leaf_temp: double, H_d: double, d_S: double] + transpiration: + return_type: double + args: [psi_stem: double] + transpiration_full_integration: + return_type: double + args: [psi_stem: double] + stom_cond_CO2: + return_type: double + args: [psi_stem: double] + transpiration_to_psi_stem: + return_type: double + args: [transpiration_: double] + # assimilation functions + assim_rubisco_limited: + return_type: double + args: [ci_: double] + assim_electron_limited: + return_type: double + args: [ci_: double] + assim_colimited: + return_type: double + args: [ci_: double] + assim_minus_stom_cond_CO2: + return_type: double + args: [x: double, psi_stem: double] + electron_transport: + return_type: double + args: [] + set_leaf_states_rates_from_psi_stem: + return_type: void + args: [psi_stem: double] + psi_stem_to_ci: + return_type: double + args: [psi_stem: double] + #leaf economics functions + hydraulic_cost_Sperry: + return_type: double + args: [psi_stem: double] + hydraulic_cost_TF: + return_type: double + args: [psi_stem: double] + profit_psi_stem_Sperry: + return_type: double + args: [psi_stem: double] + profit_Sperry_ci: + return_type: double + args: [ci_: double] + profit_psi_stem_TF: + return_type: double + args: [psi_stem: double] + # optimiser functions + optimise_psi_stem_Sperry: + return_type: void + args: [] + optimise_ci_Sperry: + return_type: void + args: [max_ci: double] + optimise_psi_stem_TF: + return_type: void + args: [] + Lorenz: name_cpp: "plant::ode::test::Lorenz" constructor: @@ -124,6 +253,10 @@ Control: - schedule_eps: double - schedule_verbose: bool - save_RK45_cache: bool + - GSS_tol_abs: double + - vulnerability_curve_ncontrol: double + - ci_abs_tol: double + - ci_niter: double OdeControl: name_cpp: "plant::ode::OdeControl" diff --git a/inst/include/plant/control.h b/inst/include/plant/control.h index 6fd7f52e..2c3cfbe2 100644 --- a/inst/include/plant/control.h +++ b/inst/include/plant/control.h @@ -45,6 +45,12 @@ struct Control { bool schedule_verbose; bool save_RK45_cache; + + //TF24 control parameters + double GSS_tol_abs; + double vulnerability_curve_ncontrol; + double ci_abs_tol; + double ci_niter; }; inline ode::OdeControl make_ode_control(const Control& control) { diff --git a/inst/include/plant/leaf_model.h b/inst/include/plant/leaf_model.h new file mode 100644 index 00000000..f3222698 --- /dev/null +++ b/inst/include/plant/leaf_model.h @@ -0,0 +1,225 @@ +// -*-c++-*- +#ifndef PLANT_PLANT_LEAF_MODEL_H_ +#define PLANT_PLANT_LEAF_MODEL_H_ + +// TODO: replace with constants +// #define umol_per_mol_to_mol_per_mol 0.000... +// #define umol_per_mol_to_Pa ... +// #define kg_to_mol_h2o ... +// #define kPa_to_Pa ... + +#include +#include +#include + +namespace plant { + +// double check best namespace for constants (private vs global) +// converts vcmax to jmax 25 unitless (Sperry et el. (2017)) +static const double vcmax_25_to_jmax_25 = 1.67; + +// kJ mol ^-1 +static const double vcmax_ha = 60000; +// kJ mol ^-1 +static const double vcmax_H_d = 200000; +// kJ mol ^-1 +static const double vcmax_d_S = 650; + +// kJ mol ^-1 +static const double jmax_ha = 30000; +// kJ mol ^-1 +static const double jmax_H_d = 200000; +// kJ mol ^-1 +static const double jmax_d_S = 650; + +// umol ^ -1 mol ^ 1 +static const double gamma_25 = 42.75; +// dimensionless +static const double gamma_c = 19.02; +// kJ mol ^-1 +static const double gamma_ha = 37.83e3; + +// umol mol ^-1 +static const double kc_25 = 404.9 ; +// dimensionless +static const double kc_c = 38.05; +// kJ mol ^-1 +static const double kc_ha = 79.43e3; + +// umol mol ^-1 +static const double ko_25 = 278400 ; +// dimensionless +static const double ko_c = 20.30; +// kJ mol ^-1 +static const double ko_ha = 36.38e3; + +// Pa umol ^ -1 mol ^ 1 +static const double umol_per_mol_to_Pa = 0.1013; + +// mol H2o kg ^-1 +static const double kg_to_mol_h2o = 55.4939; +// mol mol ^-1 / (umol mol ^-1) +static const double umol_to_mol = 1e-6; +// Pa kPa^-1 +static const double kPa_to_Pa = 1000.0; + +// universal gas constant J mol^-1 K^-1 +static const double R = 8.314; + +//convert deg C to deg K +static const double C_to_K = 273.15; + +//H20:CO2 stomatal diffusion ratio +static const double H2O_CO2_stom_diff_ratio = 1.67; + +class Leaf { +public: + //anonymous Leaf function as in canopy.h + Leaf(); + + Leaf(double vcmax_25, + double c, + double b, + double psi_crit, + double beta2, + double jmax_25, + double hk_s, + double a, + double curv_fact_elec_trans, + double curv_fact_colim, + double GSS_tol_abs, + double vulnerability_curve_ncontrol, + double ci_abs_tol, + double ci_niter); + + quadrature::QAG integrator; + interpolator::Interpolator transpiration_from_psi; + interpolator::Interpolator psi_from_transpiration; + + // psi_from_E + + double vcmax_25; + double c; + double b; + double psi_crit; // derived from b and c + double beta2; + double jmax_25; + double hk_s; + double a; + double curv_fact_elec_trans; // unitless - obtained from Smith and Keenan (2020) + double curv_fact_colim; + double GSS_tol_abs; + double vulnerability_curve_ncontrol; + double ci_abs_tol; + double ci_niter; + + double ci_; + double stom_cond_CO2_; + double assim_colimited_; + double transpiration_; + double profit_; + double psi_stem; + double lambda_; + double lambda_analytical_; + double hydraulic_cost_; + + double electron_transport_; + double gamma_; + double ko_; + double kc_; + double km_; + double R_d_; + double leaf_specific_conductance_max_; + double sapwood_volume_per_leaf_area_; + double k_s_; + double rho_; + double vcmax_; + double jmax_; + double lma_; //kg m^-2 + double a_bio_; + + double psi_soil_; + double leaf_temp_; + double PPFD_; + double atm_vpd_; + double atm_o2_kpa_; + double atm_kpa_; + double ca_; + + double opt_psi_stem_; + double opt_ci_; + double count; + + // TODO: move into environment? + + // TODO: atm_vpd - now set in set_physiology although ideally should be moved to enviroment + double atm_vpd = 2.0; //kPa + double ca = 40.0; // Pa + double atm_kpa = 101.3; //kPa + //partial pressure o2 (kPa) + double atm_o2_kpa = 21; + //leaf temperature (deg C) + double leaf_temp = 25; + + // this might end up hard-coded + void initialize_integrator(int integration_rule = 21, + double integration_tol = 1e-3) { + + integrator = quadrature::QAG(integration_rule, + 1, // fixed integration + integration_tol, integration_tol); + } + + // set-up functions + void set_physiology(double rho, double a_bio, double PPFD, double psi_soil, double leaf_specific_conductance_max, double atm_vpd, double ca, double sapwood_volume_per_leaf_area, double leaf_temp, double atm_o2_kpa, double atm_kpa); + void setup_transpiration(double resolution); + void setup_clean_leaf(); + + double arrh_curve(double Ea, double ref_value, double leaf_temp) const; + double peak_arrh_curve(double Ea, double ref_value, double leaf_temp, double H_d, double d_S) const; + + // transpiration functions + + // proportion of conductivity in xylem at a given water potential (return: unitless) + double proportion_of_conductivity(double psi) const; + + // supply-side transpiration for a given water potential gradient between leaves and soil, + // references setup_transpiraiton for values (return: kg h20 s^-1 m^-2 LA) + // should be renamed to reflect supply-side + double transpiration(double psi_stem); + // supply-side transpiration for a given water potential gradient between leaves and soil, integrated internally (return: kg h20 s^-1 m^-2 LA) + // should be renamed to reflect supply-side + double transpiration_full_integration(double psi_stem); + // stomatal conductance rate of c02 (return: mol CO2 m^-2 s^-1) + double stom_cond_CO2(double psi_stem); // define as a constant + // converts transpiration in kg h20 s^-1 m^-2 LA to psi_stem (return: -MPa) + double transpiration_to_psi_stem(double transpiration_); + + // assimilation functions + + // + double assim_rubisco_limited(double ci_); + double electron_transport(); + double assim_electron_limited(double ci_); + double assim_colimited(double ci_); + double assim_minus_stom_cond_CO2(double x, double psi_stem); + double psi_stem_to_ci(double psi_stem); + void set_leaf_states_rates_from_psi_stem(double psi_stem); + + +// leaf economics functions + double hydraulic_cost_Sperry(double psi_stem); + double hydraulic_cost_TF(double psi_stem); + + double profit_psi_stem_Sperry(double psi_stem); + double profit_Sperry_ci(double ci_); + double profit_psi_stem_TF(double psi_stem); + +// optimiser functions + void optimise_psi_stem_Sperry(); + void optimise_ci_Sperry(double ci_guess); + void optimise_psi_stem_TF(); + +}; +} // namespace plant +#endif diff --git a/src/control.cpp b/src/control.cpp index 8666c2ed..bebd386c 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -29,6 +29,11 @@ Control::Control() { schedule_verbose = false; save_RK45_cache = false; + + GSS_tol_abs = 1e-3; + vulnerability_curve_ncontrol = 1e2; + ci_abs_tol = 1e-3; + ci_niter = 1e3; } } diff --git a/src/leaf_model.cpp b/src/leaf_model.cpp new file mode 100644 index 00000000..a6a0f8e1 --- /dev/null +++ b/src/leaf_model.cpp @@ -0,0 +1,472 @@ +#include +#include + +namespace plant { +Leaf::Leaf() + : + vcmax_25(96), // umol m^-2 s^-1 + c(2.680147), //unitless + b(3.898245), //-MPa + psi_crit(5.870283), //-MPa + beta2(1.5), //exponent for effect of hydraulic risk (unitless) + jmax_25(157.44), // maximum electron transport rate umol m^-2 s^-1 + hk_s(4), // maximum hydraulic-dependent sapwood turnover rate yr ^ -1 + a(0.30), //quantum yield of photosynthetic electron transport (mol mol^-1) + curv_fact_elec_trans(0.7), //curvature factor for the light response curve (unitless) + curv_fact_colim(0.99), //curvature factor for the colimited photosythnthesis equatiom + GSS_tol_abs(1e-3), + vulnerability_curve_ncontrol(100), + ci_abs_tol(1e-3), + ci_niter(1000) + { + setup_transpiration(100); // arg: num control points for integration + setup_clean_leaf(); +} + +Leaf::Leaf(double vcmax_25, double c, double b, + double psi_crit, // derived from b and c, + double beta2, double jmax_25, double hk_s, + double a, double curv_fact_elec_trans, double curv_fact_colim, + double GSS_tol_abs, + double vulnerability_curve_ncontrol, + double ci_abs_tol, + double ci_niter) + : vcmax_25(vcmax_25), // umol m^-2 s^-1 + c(c), //unitless + b(b), //-MPa + psi_crit(psi_crit), //-MPa + beta2(beta2), //exponent for effect of hydraulic risk (unitless) + jmax_25(jmax_25), // maximum electron transport rate umol m^-2 s^-1 + hk_s(hk_s), // maximum hydraulic-dependent sapwood turnover rate yr ^ -1 + a(a), //quantum yield of photosynthetic electron transport (mol mol^-1) + curv_fact_elec_trans(curv_fact_elec_trans), //curvature factor for the light response curve (unitless) + curv_fact_colim(curv_fact_colim), //curvature factor for the colimited photosythnthesis equation + GSS_tol_abs(GSS_tol_abs), + vulnerability_curve_ncontrol(vulnerability_curve_ncontrol), + ci_abs_tol(ci_abs_tol), + ci_niter(ci_niter) + { + setup_transpiration(vulnerability_curve_ncontrol); // arg: num control points for integration + setup_clean_leaf(); +} + +// set various states and physiology parameters obtained from TF24 to NA to clean leaf object +void Leaf::setup_clean_leaf() { + ci_ = NA_REAL; // Pa + stom_cond_CO2_= NA_REAL; //mol Co2 m^-2 s^-1 + assim_colimited_= NA_REAL; // umol C m^-2 s^-1 + transpiration_= NA_REAL; // kg m^-2 s^-1 + profit_= NA_REAL; // umol C m^-2 s^-1 + lambda_= NA_REAL; // umol C m^-2 s^-1 kg^-1 m^2 s^1 + lambda_analytical_= NA_REAL; // umol C m^-2 s^-1 kg^-1 m^2 s^1 + hydraulic_cost_= NA_REAL; // umol C m^-2 s^-1 + electron_transport_= NA_REAL; //electron transport rate umol m^-2 s^-1 + gamma_= NA_REAL; + ko_= NA_REAL; + kc_= NA_REAL; + km_= NA_REAL; + R_d_= NA_REAL; + leaf_specific_conductance_max_= NA_REAL; //kg m^-2 s^-1 MPa^-1 + sapwood_volume_per_leaf_area_ = NA_REAL; //m^3 SA m^-2 LA + rho_= NA_REAL; //kg m^-3 + vcmax_= NA_REAL; //kg m^-3 + jmax_= NA_REAL; //kg m^-3 + a_bio_= NA_REAL; //kg mol^-1 + psi_soil_= NA_REAL; //-MPa + leaf_temp_= NA_REAL; // deg C + PPFD_= NA_REAL; //umol m^-2 s^-1 + atm_vpd_= NA_REAL; //kPa + atm_o2_kpa_= NA_REAL; // kPa + atm_kpa_= NA_REAL; // kPa + ca_= NA_REAL; //Pa + opt_psi_stem_= NA_REAL; //-MPa + opt_ci_= NA_REAL; //Pa +} + +//sets various parameters which are constant for a given node at a given time + +void Leaf::set_physiology(double rho, double a_bio, double PPFD, double psi_soil, double leaf_specific_conductance_max, double atm_vpd, double ca, double sapwood_volume_per_leaf_area, double leaf_temp, double atm_o2_kpa, double atm_kpa) { + rho_ = rho; + a_bio_ = a_bio; + atm_vpd_ = atm_vpd; + leaf_temp_ = leaf_temp; + atm_kpa_ = atm_kpa; + atm_o2_kpa_ = atm_o2_kpa; + PPFD_ = PPFD; + psi_soil_ = psi_soil; + leaf_specific_conductance_max_ = leaf_specific_conductance_max; + sapwood_volume_per_leaf_area_ = sapwood_volume_per_leaf_area; + ca_ = ca; + vcmax_ = peak_arrh_curve(vcmax_ha, vcmax_25, leaf_temp_, vcmax_H_d, vcmax_d_S); + jmax_ = peak_arrh_curve(jmax_ha, jmax_25, leaf_temp_, jmax_H_d, jmax_d_S); + electron_transport_ = electron_transport(); + gamma_ = arrh_curve(gamma_ha, gamma_25, leaf_temp_); + ko_ = arrh_curve(ko_ha, ko_25, leaf_temp_); + kc_ = arrh_curve(kc_ha, kc_25, leaf_temp_); + R_d_ = vcmax_*0.015; + km_ = (kc_*umol_per_mol_to_Pa)*(1 + (atm_o2_kpa_*kPa_to_Pa)/(ko_*umol_per_mol_to_Pa)); + + +// set lambda, if psi_soil is higher than psi_crit, then set to 0. Currently doing both the numerical and analytical version. Ideally would do one. + // if(psi_soil >= psi_crit){ + // lambda_ = 0; + // lambda_analytical_ = 0; + + // } else { + // set_leaf_states_rates_from_psi_stem(psi_crit); + // lambda_ = assim_colimited(ci_) / hydraulic_cost_Sperry(psi_crit); + // set_leaf_states_rates_from_psi_stem_analytical(psi_crit); + // lambda_analytical_ = assim_colimited_analytical(ci_) / hydraulic_cost_Sperry(psi_crit); + // } +} + +double Leaf::arrh_curve(double Ea, double ref_value, double leaf_temp) const { + return ref_value*exp(Ea*((leaf_temp+C_to_K) - (25 + C_to_K))/((25 + C_to_K)*R*(leaf_temp+C_to_K))); +} + +double Leaf::peak_arrh_curve(double Ea, double ref_value, double leaf_temp, double H_d, double d_S) const { + double arrh = arrh_curve(Ea, ref_value, leaf_temp); + double arg2 = 1 + exp((d_S*(25 + C_to_K) - H_d)/(R*(25 + C_to_K))); + double arg3 = 1 + exp((d_S*(leaf_temp + C_to_K) - H_d)/(R*(leaf_temp + C_to_K))); + + return arrh * arg2/arg3; +} + + +// transpiration supply functions + +// returns proportion of conductance taken from hydraulic vulnerability curve (unitless) +double Leaf::proportion_of_conductivity(double psi) const { + return exp(-pow((psi / b), c)); +} + +// set spline for proportion of conductivity +void Leaf::setup_transpiration(double resolution) { + // integrate and accumulate results + auto x_psi_ = std::vector{0.0}; // {0.0} + auto y_cumulative_transpiration_ = std::vector{0.0}; // {0.0} + double step = (b*pow((log(1/0.01)),(1/c)))/resolution; + + for (double psi_spline = 0.0 + step; psi_spline <= (b*pow((log(1/0.01)),(1/c))); psi_spline += step) { + + double E_psi = step * ((proportion_of_conductivity(psi_spline-step) + proportion_of_conductivity(psi_spline))/2) + y_cumulative_transpiration_.back(); + x_psi_.push_back(psi_spline); // x values for spline + y_cumulative_transpiration_.push_back(E_psi); // y values for spline +} +// setup interpolator +transpiration_from_psi.init(x_psi_, y_cumulative_transpiration_); +transpiration_from_psi.set_extrapolate(false); + +psi_from_transpiration.init(y_cumulative_transpiration_, x_psi_); +psi_from_transpiration.set_extrapolate(false); +} + +// replace f with some other function, returns E kg m^-2 s^-1 + +double Leaf::transpiration_full_integration(double psi_stem) { + std::function f; + f = [&](double psi) -> double { return proportion_of_conductivity(psi); }; + + return leaf_specific_conductance_max_ * integrator.integrate(f, psi_soil_, psi_stem); + } + +//calculates supply-side transpiration from psi_stem and psi_soil, returns kg h20 s^-1 m^-2 LA +double Leaf::transpiration(double psi_stem) { + // integration of proportion_of_conductivity over [psi_soil_, psi_stem] + return leaf_specific_conductance_max_ * (transpiration_from_psi.eval(psi_stem) - transpiration_from_psi.eval(psi_soil_)); + // return (transpiration_full_integration(psi_stem)); + + +} + +// converts a known transpiration to its corresponding psi_stem, returns -MPa +double Leaf::transpiration_to_psi_stem(double transpiration_) { + // integration of proportion_of_conductivity over [psi_soil_, psi_stem] + double E_psi_stem = transpiration_/leaf_specific_conductance_max_ + transpiration_from_psi.eval(psi_soil_); + return psi_from_transpiration.eval(E_psi_stem); + } + +// returns stomatal conductance to CO2, mol C m^-2 LA s^-1 +double Leaf:: stom_cond_CO2(double psi_stem) { + double transpiration_ = transpiration(psi_stem); + return atm_kpa_ * transpiration_ * kg_to_mol_h2o / atm_vpd_ / H2O_CO2_stom_diff_ratio; +} + + +// biochemical photosynthesis model equations +//ensure that units of PPFD_ actually correspond to something real. +// electron trnansport rate based on light availability and vcmax assuming co-limitation hypothesis +double Leaf::electron_transport() { + + + + double electron_transport_ = (a * PPFD_ + jmax_ - sqrt(pow(a * PPFD_ + jmax_, 2) - + 4 * curv_fact_elec_trans * a * PPFD_ * jmax_)) / (2 * curv_fact_elec_trans); // check brackets are correct + + // double electron_transport_ = (4*a*PPFD_)/sqrt(pow(4*a*PPFD_/jmax_,2)+ 1); + return electron_transport_; +} + +//calculate the rubisco-limited assimilation rate, returns umol m^-2 s^-1 +double Leaf::assim_rubisco_limited(double ci_) { + + return (vcmax_ * (ci_ - gamma_ * umol_per_mol_to_Pa)) / (ci_ + km_); + +} + +//calculate the light-limited assimilation rate, returns umol m^-2 s^-1 +double Leaf::assim_electron_limited(double ci_) { + + + return electron_transport_ / 4 * + ((ci_ - gamma_ * umol_per_mol_to_Pa) / (ci_ + 2 * gamma_ * umol_per_mol_to_Pa)); +} + +// returns co-limited assimilation umol m^-2 s^-1 +double Leaf::assim_colimited(double ci_) { + + double assim_rubisco_limited_ = assim_rubisco_limited(ci_) ; + double assim_electron_limited_ = assim_electron_limited(ci_); + + // no dark respiration included at the moment + return (assim_rubisco_limited_ + assim_electron_limited_ - sqrt(pow(assim_rubisco_limited_ + assim_electron_limited_, 2) - 4 * curv_fact_colim * assim_rubisco_limited_ * assim_electron_limited_)) / + (2 * curv_fact_colim)- R_d_; + + +} + + +// A - gc curves + +// returns difference between co-limited assimilation and stom_cond_CO2, to be minimised (umol m^-2 s^-1) +double Leaf::assim_minus_stom_cond_CO2(double x, double psi_stem) { + + double assim_colimited_x_ = assim_colimited(x); + + double stom_cond_CO2_x_ = stom_cond_CO2(psi_stem); + return assim_colimited_x_ * umol_to_mol - + (stom_cond_CO2_x_ * (ca_ - x) / (atm_kpa_ * kPa_to_Pa)); +} + +// converts psi stem to ci, used to find ci which makes A(ci) = gc(ca - ci) +double Leaf::psi_stem_to_ci(double psi_stem) { + // not clear what x is here + + + auto target = [&](double x) mutable -> double { + return assim_minus_stom_cond_CO2(x, psi_stem); + }; + + // tol and iterations copied from control defaults (for now) - changed recently to 1e-6 + return ci_ = util::uniroot(target, gamma_ * umol_per_mol_to_Pa, ca_, ci_abs_tol, ci_niter); +} + +// given psi_stem, find assimilation, transpiration and stomal conductance to c02 +void Leaf::set_leaf_states_rates_from_psi_stem(double psi_stem) { + + if (psi_soil_ >= psi_stem){ + ci_ = gamma_*umol_per_mol_to_Pa; + transpiration_ = 0; + stom_cond_CO2_ = 0; + } else{ + ci_ = psi_stem_to_ci(psi_stem); + transpiration_ = transpiration(psi_stem); + stom_cond_CO2_ = atm_kpa_ * transpiration_ * kg_to_mol_h2o / atm_vpd_ / H2O_CO2_stom_diff_ratio; + } + + assim_colimited_ = assim_colimited(ci_); + + +} + + +// Hydraulic cost equations + +// Sperry et al. 2017; Sabot et al. 2020 implementation + +double Leaf::hydraulic_cost_Sperry(double psi_stem) { + double k_l_soil_ = leaf_specific_conductance_max_ * proportion_of_conductivity(psi_soil_); + double k_l_stem_ = leaf_specific_conductance_max_ * proportion_of_conductivity(psi_stem); + + hydraulic_cost_ = k_l_soil_ - k_l_stem_; + + return hydraulic_cost_; +} + +double Leaf::hydraulic_cost_TF(double psi_stem) { +hydraulic_cost_ = 1e6 * + hk_s /(365*24*60*60)* + (1/a_bio_) * + rho_ * sapwood_volume_per_leaf_area_ * pow((1 - proportion_of_conductivity(psi_stem)), beta2); + +return hydraulic_cost_; +} + +// Profit functions + +double Leaf::profit_psi_stem_Sperry(double psi_stem) { + +set_leaf_states_rates_from_psi_stem(psi_stem); + + double benefit_ = assim_colimited_; + double hydraulic_cost_ = hydraulic_cost_Sperry(psi_stem); + + return benefit_ - lambda_ * hydraulic_cost_; +} + + +double Leaf::profit_psi_stem_TF(double psi_stem) { +set_leaf_states_rates_from_psi_stem(psi_stem); + + double benefit_ = assim_colimited_; + double hydraulic_cost_ = hydraulic_cost_TF(psi_stem); + + return benefit_ - hydraulic_cost_; +} + +double Leaf::profit_Sperry_ci(double ci_) { + double benefit_ = + assim_colimited(ci_); + double stom_cond_CO2_ = (benefit_ * umol_to_mol * atm_kpa_ * kPa_to_Pa)/(ca_ - ci_); + double transpiration_ = stom_cond_CO2_ * H2O_CO2_stom_diff_ratio * atm_vpd_ / kg_to_mol_h2o / atm_kpa_; + + double psi_stem = transpiration_to_psi_stem(transpiration_); + double hydraulic_cost_ = hydraulic_cost_Sperry(psi_stem); + + return benefit_ - lambda_*hydraulic_cost_; +} + +//optimisation functions + + +// need docs on Golden Section Search. +void Leaf::optimise_psi_stem_Sperry() { + + double gr = (sqrt(5) + 1) / 2; + opt_psi_stem_ = psi_soil_; + + + if ((PPFD_ < 1.5e-8 )| (psi_soil_ > psi_crit)){ + profit_ = 0; + transpiration_ = 0; + stom_cond_CO2_ = 0; + return; + } + + // optimise for stem water potential + double bound_a = psi_soil_; + double bound_b = psi_crit; + + double bound_c = bound_b - (bound_b - bound_a) / gr; + double bound_d = bound_a + (bound_b - bound_a) / gr; + + while (abs(bound_b - bound_a) > GSS_tol_abs) { + + double profit_at_c = + profit_psi_stem_Sperry(bound_c); + + double profit_at_d = + profit_psi_stem_Sperry(bound_d); + + if (profit_at_c > profit_at_d) { + bound_b = bound_d; + } else { + bound_a = bound_c; + } + + bound_c = bound_b - (bound_b - bound_a) / gr; + bound_d = bound_a + (bound_b - bound_a) / gr; + } + + opt_psi_stem_ = ((bound_b + bound_a) / 2); + profit_ = profit_psi_stem_Sperry(opt_psi_stem_); + + } + + +void Leaf::optimise_ci_Sperry(double max_ci) { + + // Early exit -- XXXX + if (psi_soil_ > psi_crit){ + + opt_ci_ = gamma_*umol_per_mol_to_Pa; + profit_ = 0.0; + transpiration_ = 0.0; + return; + } + + double gr = (sqrt(5) + 1) / 2; + + + // optimise for stem water potential + double bound_a = gamma_*umol_per_mol_to_Pa; + double bound_b = max_ci; + + double bound_c = bound_b - (bound_b - bound_a) / gr; + double bound_d = bound_a + (bound_b - bound_a) / gr; + while (abs(bound_b - bound_a) > GSS_tol_abs) { + + double profit_at_c = profit_Sperry_ci(bound_c); + + double profit_at_d = profit_Sperry_ci(bound_d); + + if (profit_at_c > profit_at_d) { + bound_b = bound_d; + } else { + bound_a = bound_c; + } + + bound_c = bound_b - (bound_b - bound_a) / gr; + bound_d = bound_a + (bound_b - bound_a) / gr; + } + + opt_ci_ = ((bound_b + bound_a) / 2); + profit_ = profit_Sperry_ci(opt_ci_); + + + return; + + } + + +void Leaf::optimise_psi_stem_TF() { + + double gr = (sqrt(5) + 1) / 2; + opt_psi_stem_ = psi_soil_; + + if (psi_soil_ > psi_crit){ + profit_ = profit_psi_stem_TF(psi_soil_); + return; + } + + // optimise for stem water potential + double bound_a = psi_soil_; + double bound_b = psi_crit; + + double bound_c = bound_b - (bound_b - bound_a) / gr; + double bound_d = bound_a + (bound_b - bound_a) / gr; + while (abs(bound_b - bound_a) > GSS_tol_abs) { + + double profit_at_c = + profit_psi_stem_TF(bound_c); + + double profit_at_d = + profit_psi_stem_TF(bound_d); + + if (profit_at_c > profit_at_d) { + bound_b = bound_d; + } else { + bound_a = bound_c; + } + + bound_c = bound_b - (bound_b - bound_a) / gr; + bound_d = bound_a + (bound_b - bound_a) / gr; + } + + opt_psi_stem_ = ((bound_b + bound_a) / 2); + profit_ = profit_psi_stem_TF(opt_psi_stem_); + + return; + } + +} // namespace plant diff --git a/tests/testthat/test-control.R b/tests/testthat/test-control.R index 530c920a..0fdeac44 100644 --- a/tests/testthat/test-control.R +++ b/tests/testthat/test-control.R @@ -24,7 +24,12 @@ test_that("Defaults", { schedule_nsteps = 20, # size_t schedule_eps = 1e-3, - schedule_verbose = FALSE + schedule_verbose = FALSE, + + GSS_tol_abs = 1e-3, + vulnerability_curve_ncontrol = 1e2, + ci_abs_tol = 1e-3, + ci_niter = 1000 ) keys <- sort(names(expected)) diff --git a/tests/testthat/test-leaf.r b/tests/testthat/test-leaf.r new file mode 100644 index 00000000..ffd74429 --- /dev/null +++ b/tests/testthat/test-leaf.r @@ -0,0 +1,398 @@ +context("SCM-general") + +test_that("Basic functions", { + #first set physiological parameters + + # TF24_strategy <- TF24_Strategy() + + vcmax_25 = 100 #maximum carboxylation rate (umol m^-2 s^-1) + jmax_25 = vcmax_25*167 #maximum electron transport rate (umol m^-2 s^-1) + p_50 = 2 #stem water potential at 50% loss of conductivity + c = 2.04 #shape parameter for hydraulic vulnerability curve (unitless) estimated from trait data in Austraits from Choat et al. 2012 + b = 3 #shape parameter for vulnerability curve, point of 37% conductance (-MPa) + psi_crit = 5 #stem water potential at which conductance is 95% + theta = 0.000157 #huber value (m^2 sapwood area m^-2 leaf area) + K_s = 1 #stem-specific conductivity (kg h2o m^-1 stem s^-1 MPa^-1) + h = 5 #height or path length (m) + beta2 = 1 + hk_s = 75 + curv_fact_elec_trans = 0.7 + a = 0.3 + curv_fact_colim = 0.99 + + GSS_tol_abs = 1e-8 + vulnerability_curve_ncontrol = 100 + ci_abs_tol = 1e-6 + ci_niter = 1000 + + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, + GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + + #without setting physiology, PPFD_, k_l_max_, and psi_soil_ should all be NA + + expect_true(is.na(l$PPFD_)) + expect_true(is.na(l$leaf_specific_conductance_max_)) + expect_true(is.na(l$psi_soil_)) + expect_true(is.na(l$atm_vpd_)) + expect_true(is.na(l$ca_)) + expect_true(is.na(l$lambda_)) + expect_true(is.na(l$lambda_analytical_)) + expect_true(is.na(l$atm_o2_kpa_)) + expect_true(is.na(l$leaf_temp_)) + + #now set physiology, PPFD_, k_l_max_, and psi_soil_, atm_vpd_ should be not NA + + PPFD = 900 + sapwood_volume_per_leaf_area = theta*h + leaf_specific_conductance_max = K_s*theta/h + psi_soil = 2 + atm_vpd = 2 + ca = 40 + atm_o2_kpa_ = 21 + leaf_temp_ = 25 + atm_kpa_ = 101.3 + + l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + + expect_equal(l$PPFD_, PPFD) + expect_equal(l$leaf_specific_conductance_max_, leaf_specific_conductance_max) + expect_equal(l$psi_soil_, psi_soil) + expect_equal(l$ca_, ca) + expect_equal(l$atm_vpd_, atm_vpd) + expect_equal(l$atm_o2_kpa_, atm_o2_kpa_) + expect_equal(l$leaf_temp_, leaf_temp_) + + #generating a new leaf object should wipe the previously stored values + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + + expect_true(is.na(l$PPFD_)) + expect_true(is.na(l$leaf_specific_conductance_max_)) + expect_true(is.na(l$psi_soil_)) + expect_true(is.na(l$atm_vpd_)) + expect_true(is.na(l$ca_)) + expect_true(is.na(l$lambda_)) + expect_true(is.na(l$lambda_analytical_)) + expect_true(is.na(l$atm_o2_kpa_)) + expect_true(is.na(l$leaf_temp_)) + + #set physiology again for testing + l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + psi <- 1 #nominated value for water potential for testing vulnerability curve equations only (-MPa) + + #test conducitvity vulnerability, should be proportion value. + expect_equal(l$proportion_of_conductivity(psi), 0.8991241827) + + #test calcuation of transpiration stream based on water potential of stem (-MPa) + + #for situations where psi_soil is < than psi_crit and psi_stem is greater than psi_soil + psi_stem <- psi_soil+1 #stem water potential (-MPa) + expect_true(l$transpiration(psi_stem) > 0) + + #for situations where psi_soil is < than psi_crit and psi_stem is less than psi_soil, creates negative value. Ordinarily an undesirable property which is typically banned (stem assumed to have minimum water potential at psi_soil) + psi_stem <- psi_soil-1 #stem water potential (-MPa) + expect_true(l$transpiration(psi_stem) < 0) + + #for situations where psi_soil is < than psi_crit and psi_stem is equal to psi_soil + psi_stem <- psi_soil #stem water potential (-MPa) + expect_true(l$transpiration(psi_stem) == 0) + + upper_bound_int <- 3*((log(1/1e-5))^(1/2.04)) + #for situations where psi_stem exceeds tolerance of integrator + expect_error(l$transpiration(upper_bound_int), "Extrapolation disabled and evaluation point outside of interpolated domain.") + + #for situations where psi_soil exceeds psi_crit + tolerance + + psi_soil = upper_bound_int + l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + psi_stem = psi_soil + + expect_error(l$transpiration(psi_stem), "Extrapolation disabled and evaluation point outside of interpolated domain.") + + #test that fast E supply calculation is closely approximating full integration + psi_soil = 0 + l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + psi_stem = psi_soil + 3 + + expect_equal(l$transpiration(psi_stem), l$transpiration_full_integration(psi_stem)) + + #test that conversion between psi and E works properly + + expect_equal(l$transpiration_to_psi_stem(l$transpiration(psi_stem)), psi_stem) + + c_i = 30 #intra-cellular carbon dioxide parital pressure (Pa) + + #test a function which retrieves various leaf-level states and rates from a given psi_stem value + #for situations where psi stem is lower than psi soil + + psi_soil = 2 + + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + + #note that this scenario should not occur in model anyway + l$set_leaf_states_rates_from_psi_stem(psi_soil - 1) + + #assimilation becomes dark respiration + expect_equal(l$assim_colimited_, -l$R_d_) + #stomatal conductance becomes 0 + expect_equal(l$stom_cond_CO2_, 0) + #transpiration becomes 0 + expect_equal(l$transpiration_, 0) + + #costs 0 when psi_stem == psi_soil == 0 + expect_equal(l$hydraulic_cost_Sperry(psi_soil) == 0, TRUE) + + #costs positive even when transpiration stream is 0 in hydraulic cost tf + expect_equal(l$hydraulic_cost_TF(psi_soil) > 0, TRUE) + + #when psi stem is greater than psi soil + psi_soil = 2 + + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + + l$set_leaf_states_rates_from_psi_stem(psi_soil + 1) + + + #assimilation becomes greater than 0 + expect_equal(l$assim_colimited_ >0, TRUE) + #stomatal conductance becomes greater than 0 + expect_equal(l$stom_cond_CO2_ >0, TRUE) + #transpiration becomes greater than 0 + expect_equal(l$transpiration_ >0, TRUE) + + #when psi stem is equal to psi soil + psi_soil = 2 + + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + + l$set_leaf_states_rates_from_psi_stem(psi_soil) + + + #calculate the hydraulic cost usign the sperry method, should be 0 when psi_soil is equivalent to psi_stem + expect_equal(l$hydraulic_cost_Sperry(psi_soil) == 0, TRUE) + #calculate hydraulic cost using TF method, should be greater than 0 when psi_soil is greater than 0 + expect_equal(l$hydraulic_cost_TF(psi_soil) > 0, TRUE) + + expect_equal(l$hydraulic_cost_Sperry(psi_soil + 1) > 0, TRUE) + expect_equal(l$hydraulic_cost_TF(psi_soil + 1) > 0, TRUE) + + #ensure that hydraulic_cost returns 0 cost at 0 psi_soil/psi_stem + psi_soil = 0 + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + + l$set_leaf_states_rates_from_psi_stem(0) + expect_equal(l$hydraulic_cost_TF(psi_soil) == 0, TRUE) + expect_equal(l$hydraulic_cost_Sperry(psi_soil) == 0, TRUE) + + #psi_soil == psi_stem means A == -R_d_ + expect_equal(l$assim_colimited_, -l$R_d_) + #stomatal conductance becomes 0 + expect_equal(l$stom_cond_CO2_, 0) + #transpiration becomes 0 + expect_equal(l$transpiration_, 0) + + #test behaviours related to low Ci + expect_equal(l$assim_rubisco_limited(l$gamma_*0.1013), 0) + expect_equal(l$assim_electron_limited(l$gamma_*0.1013), 0) + expect_equal(l$assim_colimited(l$gamma_*0.1013), -l$R_d_) + + + #under almost all scenarios, max ci (i.e when psi stem is set to psi crit) should be less than ca + + #plain version use a uniroot solving method to find ci + l$set_leaf_states_rates_from_psi_stem(psi_crit) + expect_equal(l$ci_< ca, TRUE) + + #test whether conversion between E and psi is equivalent between R and C++ + + psi_soil = 0.5 + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + + l$set_leaf_states_rates_from_psi_stem(psi_crit) + c_i = l$ci_ + benefit_ = l$assim_colimited_ + + kg_to_mol_h2o = 55.4939 + umol_to_mol = 1e-6 + kPa_to_Pa = 1e3 + + g_c_ci = ((benefit_)* umol_to_mol * l$atm_kpa_ * kPa_to_Pa)/(l$ca_ - l$ci_); + + E_ci = g_c_ci * 1.67 * l$atm_vpd_ / kg_to_mol_h2o / l$atm_kpa_; + psi_stem = l$transpiration_to_psi_stem(E_ci) + + #conversion back and forth is not perfect + expect_equal(psi_stem, psi_crit, tolerance = 1e-05) + + #let's start testing profit functions + + #first off- what happens when we moving psi_soil around + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + psi_soil = 0 + + #first off- what happens when we moving psi_soil around + l$set_physiology(PPFD = PPFD, psi_soil = psi_crit+1, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + l$optimise_psi_stem_TF() + + expect_equal(l$transpiration_, 0) + expect_equal(l$opt_psi_stem_, psi_crit+1) + expect_equal(l$stom_cond_CO2_, 0) + expect_equal(l$ci_, l$gamma_*0.1013) + expect_true(l$profit_ < 0) + + l$set_physiology(PPFD = PPFD, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + l$optimise_psi_stem_TF() + expect_true(l$profit_ > 0) + expect_true(l$opt_psi_stem_ > 0) + expect_true(l$stom_cond_CO2_ > 0) + expect_true(l$transpiration_ > 0) + expect_true(l$hydraulic_cost_ > 0) + + #profit should be NA when psi stem is NA + expect_true(is.na(l$profit_psi_stem_TF(NA))) + + #test various responses to environmental gradients to check that behaviour is being conserved + + #light + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + l$optimise_psi_stem_TF() + + high_light <- l$profit_ + + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, + GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l$set_physiology(PPFD = 500, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + l$optimise_psi_stem_TF() + + low_light <- l$profit_ + + expect_true(high_light > low_light) + + #soil moist + + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, + GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + l$optimise_psi_stem_TF() + + high_moist <- l$profit_ + + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, + GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l$set_physiology(PPFD = 1000, psi_soil = 2, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + l$optimise_psi_stem_TF() + + low_moist <- l$profit_ + + expect_true(high_moist > low_moist) + + + #vpd' + + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, + GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = 1, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + l$optimise_psi_stem_TF() + + low_vpd <- l$profit_ + + l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, + GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = 2, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + l$optimise_psi_stem_TF() + + high_vpd <- l$profit_ + + expect_true(high_vpd < low_vpd) + + #vcmax_25 + + l <- plant:::Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, + GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = 1, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + l$optimise_psi_stem_TF() + + low_vcmax <- l$profit_ + + l <- plant:::Leaf(vcmax_25 = 150, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, + GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + + + l$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = 1, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + l$optimise_psi_stem_TF() + + high_vcmax <- l$profit_ + + expect_true(high_vcmax > low_vcmax) + + #test effect of leaf temperature + + l_low_temp <-plant:::Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, + GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l_low_temp$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = 1, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = 20, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + + l_ref_temp <- plant:::Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, + GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l_ref_temp$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = 1, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = 25, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + + l_high_temp <- plant:::Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, + GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l_high_temp$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = 1, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = 30, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + + expect_true(l_low_temp$gamma_ < l_ref_temp$gamma_ & l_ref_temp$gamma_ < l_high_temp$gamma_) + + l_high_temp <-plant:::Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, + GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, + ci_niter = ci_niter) + l_high_temp$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = 1, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = 40, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) + + expect_equal(round(l_high_temp$ko_, 1), round(562314.4,1)) + expect_equal(round(l_high_temp$kc_, 1), round(1879.0751,1)) + expect_equal(round(l_high_temp$gamma_, 1), round(88.800391,1)) + expect_equal(round(l_high_temp$vcmax_, 1), round(35.2,1)) + + }) From b923dcf6c029bc81f56b70ab705380e8e56ebb51 Mon Sep 17 00:00:00 2001 From: itowers1 <39288928+itowers1@users.noreply.github.com> Date: Mon, 1 Jul 2024 10:46:01 +1000 Subject: [PATCH 2/6] remove plant::: from tests --- tests/testthat/test-leaf.r | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/testthat/test-leaf.r b/tests/testthat/test-leaf.r index ffd74429..89990b41 100644 --- a/tests/testthat/test-leaf.r +++ b/tests/testthat/test-leaf.r @@ -25,7 +25,7 @@ test_that("Basic functions", { ci_abs_tol = 1e-6 ci_niter = 1000 - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) @@ -65,7 +65,7 @@ test_that("Basic functions", { expect_equal(l$leaf_temp_, leaf_temp_) #generating a new leaf object should wipe the previously stored values - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) @@ -130,7 +130,7 @@ test_that("Basic functions", { psi_soil = 2 - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) @@ -154,7 +154,7 @@ test_that("Basic functions", { #when psi stem is greater than psi soil psi_soil = 2 - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) @@ -172,7 +172,7 @@ test_that("Basic functions", { #when psi stem is equal to psi soil psi_soil = 2 - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) @@ -190,7 +190,7 @@ test_that("Basic functions", { #ensure that hydraulic_cost returns 0 cost at 0 psi_soil/psi_stem psi_soil = 0 - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) @@ -221,7 +221,7 @@ test_that("Basic functions", { #test whether conversion between E and psi is equivalent between R and C++ psi_soil = 0.5 - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) l$set_physiology(PPFD = PPFD, psi_soil = psi_soil, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) @@ -245,7 +245,7 @@ test_that("Basic functions", { #let's start testing profit functions #first off- what happens when we moving psi_soil around - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) psi_soil = 0 @@ -274,7 +274,7 @@ test_that("Basic functions", { #test various responses to environmental gradients to check that behaviour is being conserved #light - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = 1000, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) l$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = atm_vpd, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = leaf_temp_, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) @@ -282,7 +282,7 @@ test_that("Basic functions", { high_light <- l$profit_ - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) @@ -295,7 +295,7 @@ test_that("Basic functions", { #soil moist - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) @@ -304,7 +304,7 @@ test_that("Basic functions", { high_moist <- l$profit_ - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) @@ -318,7 +318,7 @@ test_that("Basic functions", { #vpd' - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) @@ -327,7 +327,7 @@ test_that("Basic functions", { low_vpd <- l$profit_ - l <- plant:::Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = vcmax_25, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) @@ -340,7 +340,7 @@ test_that("Basic functions", { #vcmax_25 - l <- plant:::Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) @@ -349,7 +349,7 @@ test_that("Basic functions", { low_vcmax <- l$profit_ - l <- plant:::Leaf(vcmax_25 = 150, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l <- Leaf(vcmax_25 = 150, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) @@ -364,19 +364,19 @@ test_that("Basic functions", { #test effect of leaf temperature - l_low_temp <-plant:::Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l_low_temp <-Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) l_low_temp$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = 1, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = 20, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) - l_ref_temp <- plant:::Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l_ref_temp <- Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) l_ref_temp$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = leaf_specific_conductance_max, atm_vpd = 1, ca = ca, sapwood_volume_per_leaf_area = sapwood_volume_per_leaf_area, rho = 608, a_bio = 0.0245, leaf_temp = 25, atm_o2_kpa = atm_o2_kpa_, atm_kpa = atm_kpa_) - l_high_temp <- plant:::Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l_high_temp <- Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) @@ -384,7 +384,7 @@ test_that("Basic functions", { expect_true(l_low_temp$gamma_ < l_ref_temp$gamma_ & l_ref_temp$gamma_ < l_high_temp$gamma_) - l_high_temp <-plant:::Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, + l_high_temp <-Leaf(vcmax_25 = 50, jmax_25 = jmax_25, c = c, b = b, psi_crit = psi_crit, beta2= beta2, hk_s = hk_s, a = a, curv_fact_elec_trans = curv_fact_elec_trans, curv_fact_colim = curv_fact_colim, GSS_tol_abs = GSS_tol_abs, vulnerability_curve_ncontrol = vulnerability_curve_ncontrol, ci_abs_tol = ci_abs_tol, ci_niter = ci_niter) From 867b7143469a3cf986e933670efe4be16848e3c4 Mon Sep 17 00:00:00 2001 From: itowers1 <39288928+itowers1@users.noreply.github.com> Date: Mon, 1 Jul 2024 10:46:35 +1000 Subject: [PATCH 3/6] add leaf to yml, add argument descriptions --- inst/RcppR6_classes.yml | 19 +++++++++++++++++++ inst/include/plant.h | 1 + 2 files changed, 20 insertions(+) diff --git a/inst/RcppR6_classes.yml b/inst/RcppR6_classes.yml index 3922e81c..19cdb8ef 100644 --- a/inst/RcppR6_classes.yml +++ b/inst/RcppR6_classes.yml @@ -1,6 +1,25 @@ Leaf: name_cpp: "plant::Leaf" constructor: + roxygen: | + Leaf model + @param vcmax_25 Maximum Carboxylation Rate (umol m^-2 s^-1) + @param c shape parameter of hydraulic vulnerability curve (unitless) + @param b sensitivity parameter of hydraulic vulnerability curve (MPa) + @param psi_crit critical psi stem (-MPa ) + @param beta2 exponent for effect of hydraulic risk (unitless) + @param jmax_25 maximum rate of electron transport (umol m^-2 s^-1) + @param hk_s maximum hydraulic-dependent sapwood turnover rate yr ^ -1 + @param a quantum yield of photosynthetic electron transport (mol mol^-1) + @param curv_fact_elec_trans curvature factor for the light response curve (unitless) + @param curv_fact_colim curvature factor for the colimited photosythnthesis equatiom + @param GSS_tol_abs tolereance parameter for golden section search + @param vulnerability_curve_ncontrol number of points for pre-calculating vulnerability curve + @param ci_abs_tol absolute tolerance value for root-solving ci + @param ci_niter maximum number of iterations for root-solving ci + + + @export args: - vcmax_25: double - c: double diff --git a/inst/include/plant.h b/inst/include/plant.h index 60c96c87..269aee35 100644 --- a/inst/include/plant.h +++ b/inst/include/plant.h @@ -33,6 +33,7 @@ #include #include #include +#include // Getting more serious down here. #include From a24a5f6552ad752dfcf06039e097f59e32c68777 Mon Sep 17 00:00:00 2001 From: itowers1 <39288928+itowers1@users.noreply.github.com> Date: Mon, 1 Jul 2024 10:48:30 +1000 Subject: [PATCH 4/6] Create leaf_submodel_documentation.Rmd --- vignettes/leaf_submodel_documentation.Rmd | 340 ++++++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 vignettes/leaf_submodel_documentation.Rmd diff --git a/vignettes/leaf_submodel_documentation.Rmd b/vignettes/leaf_submodel_documentation.Rmd new file mode 100644 index 00000000..8bd92243 --- /dev/null +++ b/vignettes/leaf_submodel_documentation.Rmd @@ -0,0 +1,340 @@ +--- +title: "tf24w_documentation" +output: html_document +date: "2023-01-10" +--- + +```{r setup, include=FALSE} +knitr::opts_chunk$set(echo = TRUE) +``` + +This is the documentation for the tf24w strategy + +#Introduction + +tf24w is an implementation of the tf24 strategy including water dynamics. This includes an updated strategy object `tf24w`, a physiological stomatal optimisation sub-model which determines how plants assimilate carbon and transpire water dynamically in response to water availability, vapour pressure deficit, leaf temperature, in a trait-dependent manner, and a soil-water submodel which takes rainfall as an input and determines how much soil moisture is available to plants. + +We can compare the two strategy objects to first understand the new traits that have been introduced in `tf24w` + +```{r} +devtools::load_all() +library(tidyverse) +``` + + +```{r} +s <- tf24_Strategy() +sw <- tf24w_Strategy() + +names(s) +names(sw) +``` + +There are 9 new traits thus far: + +-vcmax: the maximum rate carboxylation ($\mu mol~m^{-2}~s^{-1}$) +-p_50: The leaf water potential ($\psi_l$) at which 50% of conductivity is lost +-K_s: The maximum hydraulic conductivity ($kg~m^{-2}~s^{-1}~MPa^{-1}) +-c: Shape parameter for the hydraulic vulnerability curve (unitless) +-b: Sensitivity parameter for the hydraulic vulnerability curve (-MPa) +-psi_crit: $\psi_l$ at which 95% of conductivity is lost. Maximum water potential. (-MPa) + +For the most part, these traits, in combination with traits from `tf24`, determine how plant assimilate carbon and tranpsire water via the physiological `Leaf` submodel. We can start by exploring the theory behind how the `Leaf` submodel works, found in `leaf_model.cpp`. + +#Profitmax + +Plants are known to vary the aperture of their stomata, which control the rate of conductance of $H_2O$ for $CO_2$, in response to environmental stimuli including the amount of available soil moisture. But how do plants determine the optimum rate of exchange? Multiple theoretical frameworks exist to address this question, but currently `tf24w` employs the `profitmax` model. The profitmax models states that the optimum stomatal conductance is the point at which profits, $P~(\mu mol~m^{-2}~s^{-1})$, is maximimised. + +$P (\mu mol~m^{-2}~s^{-1})$ is the difference between photosynthetic revenue, $A~(\mu mol~m^{-2}~s^{-1})$ and the costs,$C~(\mu mol~m^{-2}~s^{-1})$ required to maintain the transpirational pathway which supplies water for transpiration through the stomates: + +\begin{equation} +P~(\psi_l) = A~(\psi_l) - C~(\psi_l). +\end{equation} + +$\psi_l~(-MPa)$ is the water potential of the canopy xylem. This can considered equivalent to the rate of stomatal conductance, because the larger that the leaf water potential gets, the greater the stomatal conductance, all else being equal, which we return to later. What is clear from the equation is that, because both $R$ and $C$ are functions of $\psi_l$, there is a value of $\psi_l$ which can be found which results in $max(P)$. In other words, the maximum profit. We will return to how we numerically solve this function later. + +For now, lets go through how the cost and revenue are calculated as a function of $\psi_l$. + +#Revenue + +Revenue is `profitmax` is the photosynthetic assimilate $A~(\mu mol~m^{-2}~s^{-1})$ that can produced at a given level of stomatal conductance before taking away costs associated with transpiration. + +$A~(\mu mol~m^{-2}~s^{-1})$ is related to stomatal behaviour via a coupled-stomatal conductance model, which employs Fick's first law to describe the flux of $CO_2$ across a concentration gradients from the atmosphere $C_a~(Pa)$ to the inter-cellular spaces in the leaf $C_i~(Pa)$: + +\begin{equation} +A~(C_i) = \frac{g_c(\psi_{l})(C_a - C_i)}{P_{atm}}. +\end{equation} + +In the above equation, $P_{atm}~(kPa)$ is the atmospheric pressure and $g_c$ is the stomatal conducatance to $CO_2$, which is calculated as + +\begin{equation} +g_c(\psi_{l}) = \frac{g_w(\psi_{l})}{1.6}, +\end{equation} + +where $g_w$ is the stomatal conducatance to $H_2O$ and 1.6 is ratio of exchange of $CO_2$ and $H_2O$ at the stomatal boundary. For now, we will treat $g_c$ as a constant, because $\psi_l$ varies when maximising the profit function. As can be seen in the coupled stomatal model, $C_i$ is present on both sides of the equation, meaning that we must solve for the value of $C_i$. To better understand this, we first need to understand how $A$ relates to $C_i$ + +$A$ is itself a function of $C_i$ and is calculated using a biochemical photosynthetic model (Farquhar et al. 1980) which incorporates both the rubisco-limited, $A_c~(umol~m^{-2}~s^{-1})$ and electron-transport limited photosythnetic rate $A_j~(umol~m^{-2}~s^{-1})$. Net $A$ occurs at the most limiting of these two rate using a smoothing transitiion function. + +The standard electron-transport limited photosynthetic rate equation describes how photosynthesis varies with light availability and $C_i$: + +\begin{equation} +A_j=\frac{J(C_i-\Gamma^*)}{4(C_i+2\Gamma^*)}, +\end{equation} + +where $\Gamma^*~(Pa)$ is the CO2 compensation point of photosynthesis. $J~(umol~m^{-2}~s^{-1})$ describes the effect of light availability on photosythnesis, being the irradiance dependence of electron transport: + +\begin{equation} +J=\frac{aQ+J_{max}-\sqrt{(aQ+J_{max})^2-4caQJ_{max}}}{2c}, +\end{equation} + +where $a~(mol~photon~mol^{-1}~electron)$ is the effective quantum yield of electron transport, $Q~(umol~m^{-2}~s^{-1})$ is the PPFD (i.e. the light), $c (unitless)$ is the curvature of the the response of the electron transport rate to light and $J_{max}~(umol~m^{-2}~s^{-1})$ is the maximum electron transport rate. + +$A_c$ is calculated as: + +\begin{equation} +A_c=\frac{V_{c,max}(C_i-\Gamma*)}{C_i + K_m}, +\end{equation} + +where $K_m~(Pa)$ is the effective Michaelis-Menten constant. $V_{c,max}$, $\Gamma*$ and $K_m$ are all temperature dependent variables. + +We can view the functional form of $A_c$ and $A_j$ a function of $C_i$ below. + +First, we need to initialise a leaf with some traits and some environmental information. We can extract them from the strategy object. Remember, we only need to initalise the leaf object with traits which are related to leaf physiological sub-model, rather than the whole plant as would be required for growing an `Individual` or a `patch`. + +The `Leaf` function creates a `Leaf` object, which contains most of the internal functions which are used when calculating the photosynthetic assimilation and water use of a unit of leaf area when using `tf24w`. We initialise the `Leaf` object with a set of traits. + +```{r} +leaf <- Leaf(vcmax= sw$vcmax_25, b = sw$b, c = sw$c, psi_crit = sw$psi_crit, epsilon_leaf = sw$epsilon_leaf, jmax_25 = sw$jmax_25, hk_s = sw$hk_s, a = sw$a, curv_fact_elec_trans = sw$curv_fact_elec_trans, curv_fact_colim = sw$curv_fact_colim) +``` + +We also need to set a series of variables which describe the environmment and physiology of the plant at a given time using the `set_physiology` function. Whereas the traits set using the `Leaf` function describe a species' strategy and do not vary over time, the variables set in `set_physiology` do vary. This becomes more relevant for when we dynamically running an individual plant or forest. For now, we will set some constants, based on plant height. + +```{r} +height = 1 +leaf$K_s = 2 + +leaf$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = 4.8e-05, atm_vpd = 2, ca = 40, sapwood_volume_per_leaf_area = 1.8e-04, rho = 608, a_bio = 0.0245, leaf_temp = 25, atm_o2_kpa = 21, atm_kpa = 101.3) +``` + +Set some $C_i$ values. + +```{r} +C_i = seq(0,40,1) +``` + +Plot $A_j$ and $A_c$ against $C_i$ + +```{r} +tibble(C_i = C_i) %>% + mutate(A_j = map_dbl(C_i, leaf$assim_electron_limited), + A_c = map_dbl(C_i, leaf$assim_rubisco_limited)) %>% + pivot_longer(cols = c(A_j, A_c), names_to = "limit", values_to = "assim") %>% + ggplot(aes(x = C_i, y = assim))+ + geom_line(aes(colour = limit, group = limit)) + + theme_classic() +``` + +As can be seen in the plot, $A$ increases with $C_i$ regardless of whether it is rubisco or light-limited. However, the most-limiting rate changes as $C_i$ increases, which can be captured using a smoothing function (see paper for details.) + +```{r} +tibble(C_i = C_i) %>% + mutate(A_j = map_dbl(C_i, leaf$assim_electron_limited), + A_c = map_dbl(C_i, leaf$assim_rubisco_limited)) %>% + mutate(A_net = map_dbl(C_i, leaf$assim_colimited)) %>% + mutate(A_net_plus_R_d = A_net + leaf$R_d_) %>% + pivot_longer(cols = c(A_j, A_c,A_net, A_net_plus_R_d), names_to = "rate", values_to = "assim") %>% + ggplot(aes(x = C_i, y = assim))+ + geom_line(aes(colour = rate, group = rate)) + + theme_classic() +``` + +The A_net function also includes a carbon deduction associated with dark respiration, so we can add this back on to show correspondence between the A_net curve and A_c/Aj. + +#Cost + +In order for plants to photosynthesise, plants must move from water from the soil to the canopy via the xylem. To do this, the downstream water potential must be lower (i.e. more negative) than the soil. In `profitmax`, the hydraulic cost incurred by plants is associated with the fact that as the xylem water potential increases, the hydraulic conductance $k_{l,max}~(\mu mol~m^{-2}~s^{-1}~MPa^{-1})$ of the xylem pathway declines, which is assumed to be caused by an increased risk of embolism in the xylem. For simplicity, in `tf24w`, we currently represent the xylem pathway as a single element representing the roots, stem and leaves. We acknowledge that in reality these elements would each have seperate hydraulic conductances. The decline in hydraulic conductance with increasing $\psi_l$ follows the hydraulic vulnerability curve: + +\begin{equation} +k_l = k_{l,max}e^{-{(\frac{\psi_l}{b})}^c}. +\end{equation} + +We can this demonstrated graphically using the traits from above. + +```{r} +tibble(psi_stem = seq(0, 5, length.out = 100)) %>% + mutate(proportion_conductance = map_dbl(psi_stem, leaf$proportion_of_conductivity)) %>% + mutate(conductance = 4.8e-05*proportion_conductance) %>% + ggplot(aes(x = psi_stem, y = conductance)) + + geom_line() + + theme_classic() +``` + + +$b~(MPa)$ and $c~(unitless)$ are the sensitivity and shape parameters of the hydraulic vulnerability curve. $b$ is calculated as: + +$$b = \frac{p_{50}}{-log(1-\frac{50}{100}^{\frac{1}{c}})},$$ +where $p_{50}$ is the $\psi_l$ at which 50% of hydraulic conductance is lost. $c$ can be calculated if two hydraulic vulnerability (i.e. $p_{x}$) values are known. Instead, we use an empirical value for $c$ obtained from Austraits. + +$p_{50}$, in turn, is calculated from an empirical relaitonship between $p_50$ and the hydraulic conductivity of the xylem pathway, where more conductive stems lose conductivity at a less negative water potential (Liu et al. 2019): + +$$p_{50} = 1.73\frac{K_s}{2}^{-0.72}$$ + +$k_{l,max}$ is the maximum hydraulic conductance achievable by the plant at $\psi_l = 0$ and is calculated as: + +\begin{equation} +$$k_{l,max} = \frac{K_s\theta}{h\eta_c},$$ +\end{equation} + +where $\theta~(m^2~sapwood~m^{-2}~leaf~area)$ is the huber value (described in `tf24`), $h$ is the height of the plant and $eta_c~(unitless)[0,1]$ (described in `tf24`) is the average relative position of leaves in the canopy. Input traits required to parameterise these equations beyond those required in `tf24` are therefore: $K_s$, $\theta$ and $c$, with the remaining traits being handled by the `tf24w` hyperparameterisation function. $h$ is the height of the plant, and is therefore resolved dynamically when running `plant` + +The total volume of water transpiring through a given unit area of leaf is given by the following equation: + +\begin{equation} +$$E_{supply} = \int^{\psi_l}_{\psi_s}k_l(\psi)\delta\psi $$ +\end{equation} + +Again, visualising this below, the water supplied for transpiration is equivalent to the area under the curve between the soil water potential ($\psi_s~(-MPa)$) and the xylem water potential ($\psi_l~(-MPa)$). + +```{r} +tibble(psi_stem = seq(0, 5, length.out = 100)) %>% + mutate(proportion_conductance = map_dbl(psi_stem, leaf$proportion_of_conductivity)) %>% + mutate(conductance = 4.8e-05*proportion_conductance) %>% + ggplot(aes(x = psi_stem, y = conductance)) + + geom_line() + + theme_classic() + + geom_area(aes(ifelse(psi_stem > 2 | psi_stem < 1, NA, psi_stem), conductance), fill = "red", alpha= 0.5) + + geom_vline(xintercept = 2, col = "red", size = 2, linetype = "dashed") + + geom_vline(xintercept = 1, col = "red", size = 2, linetype = "dashed") + + annotate("text", x = 1.2, y = 4.8e-05, label = expression(psi[s]), col = "red") + + annotate("text", x = 2.2, y = 4.8e-05, label = expression(psi[l]), col = "red") +``` + +Or, put another way, for a given $\psi_s$, this is the $E_{supply}$ that could be achieved as $psi_l$ becomes more negative. It can be seen that $E_{supply}$ slowly tapers off as $psi_s$ increases, owing to the shape of the hydraulic vulnerability curve. This is important as it implies declining marginal returns to transpired water as $psi_stem$ becomes increasingly negative. + +```{r} +tibble(psi_stem = seq(1, 5, length.out = 100)) %>% + mutate(E_supply = map_dbl(psi_stem, leaf$transpiration_full_integration)) %>% + ggplot(aes(x = psi_stem, y = E_supply)) + + geom_line() + + theme_classic() +``` + +We assume an upper critical limit to $\psi_l$ beyond which catastrophic xylem failure would occur, $\psi_{crit}$. Here, $psi_{crit}$ is assumed to the $\psi_l$ at which 95% of conductance is lost. + +Recall from the `Revenue` section that $g_c$ is required in order to determine the $A$. We can take advantage of the robust assumption that plants optimally allocate water transport resources to ensure that $E_{supply}$, that is, the water transpired from the soil to the canopy, is equivalent to $E_{demand}$, which is the atmospheric demand for water. In other words, we assume: + +$$E_{supply} = E_{demand}$$ + +$E_{demand}$ is calculated according to the following equation: + +$$E_{demand} = \frac{g_sD}{P_{atm}},$$ + +where $D~(kPa)$ is the atmospheric vapour pressure deficit. For simplicity, we assume that it is the atmospheric VPD, not the leaf-to-atmoshpere VPD, which emerges from variation in leaf temperature relative to air temperature, that drives $E_demand$, although we acknolwedge that this could have important consequences for stomatal behaviour. From the equation above, it is clear to see that all else being held equal, $E_{demand}$ increases when either the $g_s$ or $D$ increases. The key point here is that, all else being equal, in order for the assimilation of carbon into the leaf to increase via an increase in $g_s$, there must be an increase in $E_{demand}$, which in turns requires an increasingly negative $\psi_l$, which, in turn, means that there is further drop in hydraulic conductance. This captures the inherent trade-off of stomatal conductance between greater assimilation and a higher risk of xylem damage. + +To represent the risk of xylem damage as a cost in units of carbon, we calculate $H~(\psi_l)$ (from the profit equation) as: +$$H(\psi_l) = b_1z(1-e^{-{(\frac{\psi_l}{b})}^c})^{b_2}.$$ +Here, $z~(m^3~sapwood~m^{-2}~leaf~area}$ is the sapwood volume per leaf area, $b_1(\mu mol~m^{-2}~s^{-1})$ is the carbon cost per unit of conductivity lost and $b^2~(unitless)$ is a shape parameter. The second term in the brackets is the proportion of conductivity remaining at a $\psi_l$, such that $H=0$ when $\psi_l = 0$. + +$z$ is calculated based on the size of the tree and $theta$, representing the total amount of sapwood supplying transpiration: + +$$z = \frac{\theta*h}{\eta_c}$$ +#Profit + +The relative forms of the $R$ and $H$ curves in relation to $\psi_l$ means that a single $psi_l$ which maximises profit emerges. Let's demonstrate this below, graphically. + + +```{r} +tibble(psi_stem = seq(1, 4, length.out = 100)) %>% + mutate(R = map_dbl(psi_stem, ~{ + leaf$set_leaf_states_rates_from_psi_stem_analytical(.x) + leaf$assim_colimited_} + )) %>% + mutate(C = map_dbl(psi_stem, ~leaf$hydraulic_cost_TF(.x)))-> data + +data %>% + mutate(P = R-C) %>% + pivot_longer(cols = c(P, R,C)) %>% + ggplot(aes(x = psi_stem, y = value)) + + geom_line(aes(colour = name, group = name)) + + theme_classic() + + geom_vline(xintercept = 2.05, linetype = "dashed") +``` + +That's a pretty complicated way to do it though. We can just automatically calculated these values using a given profit funciton. For example, the in-built profit funciton in `tf24w` is the `profit_psi_stem_TF`. + +```{r} +tibble(psi_stem = seq(1, 4, length.out = 100)) %>% + mutate(outcomes = map(.x = psi_stem, ~{ + leaf$profit_psi_stem_TF(.x) + return(tibble(H = leaf$hydraulic_cost_, R = leaf$assim_colimited_, P = R-H, )) + }))-> data + +data %>% + unnest(outcomes) %>% + pivot_longer(cols = c(H,R,P)) %>% + ggplot(aes(x = psi_stem, y = value)) + + geom_line(aes(colour = name, group = name)) + + theme_classic() +``` + +#Optimising profit + +Recall that the goal of the leaf physiology sub-model is to calculate the $CO_2$ assimilation and water use of a given unit of leaf area given the presiding environmental conditions and plant state. In order to do this, then, a numerical method is required to find the $\psi_l$ which maximises $P$. This also allows $E$ to be calculated, which is used in the soil hydrology sub-model (discussed elsewhere). + +The preferred method for numerical optimisation at the time of writing for `tf24` is the Golden Section Search algorthim. This algorithm finds local maxima or minima by successively narrowing the position of two initial boundary values until the distance of movement is below a defined tolerance values. As above, the x-values of the method is $\psi_l$, and the two initial boundary values in this case are $\psi_s$ and $psi_{crit}$; $psi_l$ cannot be less negative than $psi_s$ and is assumed to not surpass $psi_crit$. + +A manual demonstration is shown below, and then the method implemented in `tf24w` + +```{r} +#golden ratio +gr = (sqrt(5) + 1) / 2; + +bound_a = NA +bound_b = NA +bound_c = NA +bound_d = NA + +#set lower boundary to psi_soil +bound_a = leaf$psi_soil_; + +#set upper boundary to psi_crit +bound_b = sw$psi_crit; + +#tolerance value +delta_crit = 0.01; + +bound_c = bound_b - (bound_b - bound_a) / gr; +bound_d = bound_a + (bound_b - bound_a) / gr; + +while (abs(bound_b - bound_a) > delta_crit) { + + profit_at_c = leaf$profit_psi_stem_TF(bound_c); + profit_at_d = leaf$profit_psi_stem_TF(bound_d); + + if (profit_at_c > profit_at_d) { + bound_b = bound_d; + } else { + bound_a = bound_c; + } + + bound_c = bound_b - (bound_b - bound_a) / gr; + bound_d = bound_a + (bound_b - bound_a) / gr; + + } + + opt_psi_stem = ((bound_b + bound_a) / 2); + profit = leaf$optimise_psi_stem_TF(); + transpiration = leaf$transpiration_ +``` + +`tf24w` implementation. + +```{r} +leaf$optimise_psi_stem_TF() +leaf$profit_ +leaf$transpiration_ +``` + +ion_ +``` + From 99b1e1439b43f3f7795b84645dc314e323b8e320 Mon Sep 17 00:00:00 2001 From: itowers1 <39288928+itowers1@users.noreply.github.com> Date: Mon, 1 Jul 2024 11:10:12 +1000 Subject: [PATCH 5/6] package build --- NAMESPACE | 1 + R/RcppExports.R | 340 +++++++++ R/RcppR6.R | 302 +++++++- inst/include/plant/RcppR6_post.hpp | 21 + inst/include/plant/RcppR6_pre.hpp | 2 + man/Leaf.Rd | 29 + src/RcppExports.cpp | 1066 ++++++++++++++++++++++++++++ src/RcppR6.cpp | 371 ++++++++++ 8 files changed, 2131 insertions(+), 1 deletion(-) create mode 100644 man/Leaf.Rd diff --git a/NAMESPACE b/NAMESPACE index b7fd528d..c81883eb 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -33,6 +33,7 @@ export(K93_Strategy) export(K93_fixed_environment) export(K93_hyperpar) export(K93_make_environment) +export(Leaf) export(No_Disturbance) export(NodeSchedule) export(TF24_Environment) diff --git a/R/RcppExports.R b/R/RcppExports.R index 9be32c9f..a0dc250e 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -1,6 +1,346 @@ # Generated by using Rcpp::compileAttributes() -> do not edit by hand # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 +Leaf__ctor <- function(vcmax_25, c, b, psi_crit, beta2, jmax_25, hk_s, a, curv_fact_elec_trans, curv_fact_colim, GSS_tol_abs, vulnerability_curve_ncontrol, ci_abs_tol, ci_niter) { + .Call('_plant_Leaf__ctor', PACKAGE = 'plant', vcmax_25, c, b, psi_crit, beta2, jmax_25, hk_s, a, curv_fact_elec_trans, curv_fact_colim, GSS_tol_abs, vulnerability_curve_ncontrol, ci_abs_tol, ci_niter) +} + +Leaf__initialize_integrator <- function(obj_, integration_rule, integration_tol) { + invisible(.Call('_plant_Leaf__initialize_integrator', PACKAGE = 'plant', obj_, integration_rule, integration_tol)) +} + +Leaf__set_physiology <- function(obj_, rho, a_bio, PPFD, psi_soil, leaf_specific_conductance_max, atm_vpd, ca, sapwood_volume_per_leaf_area, leaf_temp, atm_o2_kpa, atm_kpa) { + invisible(.Call('_plant_Leaf__set_physiology', PACKAGE = 'plant', obj_, rho, a_bio, PPFD, psi_soil, leaf_specific_conductance_max, atm_vpd, ca, sapwood_volume_per_leaf_area, leaf_temp, atm_o2_kpa, atm_kpa)) +} + +Leaf__proportion_of_conductivity <- function(obj_, psi) { + .Call('_plant_Leaf__proportion_of_conductivity', PACKAGE = 'plant', obj_, psi) +} + +Leaf__arrh_curve <- function(obj_, Ea, ref_value, leaf_temp) { + .Call('_plant_Leaf__arrh_curve', PACKAGE = 'plant', obj_, Ea, ref_value, leaf_temp) +} + +Leaf__peak_arrh_curve <- function(obj_, Ea, ref_value, leaf_temp, H_d, d_S) { + .Call('_plant_Leaf__peak_arrh_curve', PACKAGE = 'plant', obj_, Ea, ref_value, leaf_temp, H_d, d_S) +} + +Leaf__transpiration <- function(obj_, psi_stem) { + .Call('_plant_Leaf__transpiration', PACKAGE = 'plant', obj_, psi_stem) +} + +Leaf__transpiration_full_integration <- function(obj_, psi_stem) { + .Call('_plant_Leaf__transpiration_full_integration', PACKAGE = 'plant', obj_, psi_stem) +} + +Leaf__stom_cond_CO2 <- function(obj_, psi_stem) { + .Call('_plant_Leaf__stom_cond_CO2', PACKAGE = 'plant', obj_, psi_stem) +} + +Leaf__transpiration_to_psi_stem <- function(obj_, transpiration_) { + .Call('_plant_Leaf__transpiration_to_psi_stem', PACKAGE = 'plant', obj_, transpiration_) +} + +Leaf__assim_rubisco_limited <- function(obj_, ci_) { + .Call('_plant_Leaf__assim_rubisco_limited', PACKAGE = 'plant', obj_, ci_) +} + +Leaf__assim_electron_limited <- function(obj_, ci_) { + .Call('_plant_Leaf__assim_electron_limited', PACKAGE = 'plant', obj_, ci_) +} + +Leaf__assim_colimited <- function(obj_, ci_) { + .Call('_plant_Leaf__assim_colimited', PACKAGE = 'plant', obj_, ci_) +} + +Leaf__assim_minus_stom_cond_CO2 <- function(obj_, x, psi_stem) { + .Call('_plant_Leaf__assim_minus_stom_cond_CO2', PACKAGE = 'plant', obj_, x, psi_stem) +} + +Leaf__electron_transport <- function(obj_) { + .Call('_plant_Leaf__electron_transport', PACKAGE = 'plant', obj_) +} + +Leaf__set_leaf_states_rates_from_psi_stem <- function(obj_, psi_stem) { + invisible(.Call('_plant_Leaf__set_leaf_states_rates_from_psi_stem', PACKAGE = 'plant', obj_, psi_stem)) +} + +Leaf__psi_stem_to_ci <- function(obj_, psi_stem) { + .Call('_plant_Leaf__psi_stem_to_ci', PACKAGE = 'plant', obj_, psi_stem) +} + +Leaf__hydraulic_cost_Sperry <- function(obj_, psi_stem) { + .Call('_plant_Leaf__hydraulic_cost_Sperry', PACKAGE = 'plant', obj_, psi_stem) +} + +Leaf__hydraulic_cost_TF <- function(obj_, psi_stem) { + .Call('_plant_Leaf__hydraulic_cost_TF', PACKAGE = 'plant', obj_, psi_stem) +} + +Leaf__profit_psi_stem_Sperry <- function(obj_, psi_stem) { + .Call('_plant_Leaf__profit_psi_stem_Sperry', PACKAGE = 'plant', obj_, psi_stem) +} + +Leaf__profit_Sperry_ci <- function(obj_, ci_) { + .Call('_plant_Leaf__profit_Sperry_ci', PACKAGE = 'plant', obj_, ci_) +} + +Leaf__profit_psi_stem_TF <- function(obj_, psi_stem) { + .Call('_plant_Leaf__profit_psi_stem_TF', PACKAGE = 'plant', obj_, psi_stem) +} + +Leaf__optimise_psi_stem_Sperry <- function(obj_) { + invisible(.Call('_plant_Leaf__optimise_psi_stem_Sperry', PACKAGE = 'plant', obj_)) +} + +Leaf__optimise_ci_Sperry <- function(obj_, max_ci) { + invisible(.Call('_plant_Leaf__optimise_ci_Sperry', PACKAGE = 'plant', obj_, max_ci)) +} + +Leaf__optimise_psi_stem_TF <- function(obj_) { + invisible(.Call('_plant_Leaf__optimise_psi_stem_TF', PACKAGE = 'plant', obj_)) +} + +Leaf__ci___get <- function(obj_) { + .Call('_plant_Leaf__ci___get', PACKAGE = 'plant', obj_) +} + +Leaf__ci___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__ci___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__stom_cond_CO2___get <- function(obj_) { + .Call('_plant_Leaf__stom_cond_CO2___get', PACKAGE = 'plant', obj_) +} + +Leaf__stom_cond_CO2___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__stom_cond_CO2___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__assim_colimited___get <- function(obj_) { + .Call('_plant_Leaf__assim_colimited___get', PACKAGE = 'plant', obj_) +} + +Leaf__assim_colimited___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__assim_colimited___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__transpiration___get <- function(obj_) { + .Call('_plant_Leaf__transpiration___get', PACKAGE = 'plant', obj_) +} + +Leaf__transpiration___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__transpiration___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__profit___get <- function(obj_) { + .Call('_plant_Leaf__profit___get', PACKAGE = 'plant', obj_) +} + +Leaf__profit___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__profit___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__psi_stem__get <- function(obj_) { + .Call('_plant_Leaf__psi_stem__get', PACKAGE = 'plant', obj_) +} + +Leaf__psi_stem__set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__psi_stem__set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__lambda___get <- function(obj_) { + .Call('_plant_Leaf__lambda___get', PACKAGE = 'plant', obj_) +} + +Leaf__lambda___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__lambda___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__lambda_analytical___get <- function(obj_) { + .Call('_plant_Leaf__lambda_analytical___get', PACKAGE = 'plant', obj_) +} + +Leaf__lambda_analytical___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__lambda_analytical___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__electron_transport___get <- function(obj_) { + .Call('_plant_Leaf__electron_transport___get', PACKAGE = 'plant', obj_) +} + +Leaf__electron_transport___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__electron_transport___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__gamma___get <- function(obj_) { + .Call('_plant_Leaf__gamma___get', PACKAGE = 'plant', obj_) +} + +Leaf__gamma___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__gamma___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__ko___get <- function(obj_) { + .Call('_plant_Leaf__ko___get', PACKAGE = 'plant', obj_) +} + +Leaf__ko___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__ko___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__kc___get <- function(obj_) { + .Call('_plant_Leaf__kc___get', PACKAGE = 'plant', obj_) +} + +Leaf__kc___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__kc___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__km___get <- function(obj_) { + .Call('_plant_Leaf__km___get', PACKAGE = 'plant', obj_) +} + +Leaf__km___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__km___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__R_d___get <- function(obj_) { + .Call('_plant_Leaf__R_d___get', PACKAGE = 'plant', obj_) +} + +Leaf__R_d___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__R_d___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__leaf_specific_conductance_max___get <- function(obj_) { + .Call('_plant_Leaf__leaf_specific_conductance_max___get', PACKAGE = 'plant', obj_) +} + +Leaf__leaf_specific_conductance_max___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__leaf_specific_conductance_max___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__vcmax___get <- function(obj_) { + .Call('_plant_Leaf__vcmax___get', PACKAGE = 'plant', obj_) +} + +Leaf__vcmax___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__vcmax___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__jmax___get <- function(obj_) { + .Call('_plant_Leaf__jmax___get', PACKAGE = 'plant', obj_) +} + +Leaf__jmax___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__jmax___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__rho___get <- function(obj_) { + .Call('_plant_Leaf__rho___get', PACKAGE = 'plant', obj_) +} + +Leaf__rho___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__rho___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__a_bio___get <- function(obj_) { + .Call('_plant_Leaf__a_bio___get', PACKAGE = 'plant', obj_) +} + +Leaf__a_bio___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__a_bio___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__PPFD___get <- function(obj_) { + .Call('_plant_Leaf__PPFD___get', PACKAGE = 'plant', obj_) +} + +Leaf__PPFD___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__PPFD___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__atm_vpd___get <- function(obj_) { + .Call('_plant_Leaf__atm_vpd___get', PACKAGE = 'plant', obj_) +} + +Leaf__atm_vpd___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__atm_vpd___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__ca___get <- function(obj_) { + .Call('_plant_Leaf__ca___get', PACKAGE = 'plant', obj_) +} + +Leaf__ca___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__ca___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__psi_soil___get <- function(obj_) { + .Call('_plant_Leaf__psi_soil___get', PACKAGE = 'plant', obj_) +} + +Leaf__psi_soil___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__psi_soil___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__leaf_temp___get <- function(obj_) { + .Call('_plant_Leaf__leaf_temp___get', PACKAGE = 'plant', obj_) +} + +Leaf__leaf_temp___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__leaf_temp___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__atm_o2_kpa___get <- function(obj_) { + .Call('_plant_Leaf__atm_o2_kpa___get', PACKAGE = 'plant', obj_) +} + +Leaf__atm_o2_kpa___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__atm_o2_kpa___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__atm_kpa___get <- function(obj_) { + .Call('_plant_Leaf__atm_kpa___get', PACKAGE = 'plant', obj_) +} + +Leaf__atm_kpa___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__atm_kpa___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__hydraulic_cost___get <- function(obj_) { + .Call('_plant_Leaf__hydraulic_cost___get', PACKAGE = 'plant', obj_) +} + +Leaf__hydraulic_cost___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__hydraulic_cost___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__opt_psi_stem___get <- function(obj_) { + .Call('_plant_Leaf__opt_psi_stem___get', PACKAGE = 'plant', obj_) +} + +Leaf__opt_psi_stem___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__opt_psi_stem___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__opt_ci___get <- function(obj_) { + .Call('_plant_Leaf__opt_ci___get', PACKAGE = 'plant', obj_) +} + +Leaf__opt_ci___set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__opt_ci___set', PACKAGE = 'plant', obj_, value)) +} + +Leaf__count__get <- function(obj_) { + .Call('_plant_Leaf__count__get', PACKAGE = 'plant', obj_) +} + +Leaf__count__set <- function(obj_, value) { + invisible(.Call('_plant_Leaf__count__set', PACKAGE = 'plant', obj_, value)) +} + Lorenz__ctor <- function(sigma, R, b) { .Call('_plant_Lorenz__ctor', PACKAGE = 'plant', sigma, R, b) } diff --git a/R/RcppR6.R b/R/RcppR6.R index 1a99cd58..594a055a 100644 --- a/R/RcppR6.R +++ b/R/RcppR6.R @@ -1,6 +1,6 @@ ## Generated by RcppR6: do not edit by hand ## Version: 0.2.4 -## Hash: bbf062e0a16bb3911c8fd115f95cef6b +## Hash: 043af93437cdd051ba21605b6850a1ed ##' @importFrom Rcpp evalCpp ##' @importFrom R6 R6Class @@ -21,6 +21,306 @@ check_type <- function(type, valid) { names(valid)[[i]] } +##' Leaf model +##' @param vcmax_25 rubisco rate +##' @export +`Leaf` <- function(vcmax_25, c, b, psi_crit, beta2, jmax_25, hk_s, a, curv_fact_elec_trans, curv_fact_colim, GSS_tol_abs, vulnerability_curve_ncontrol, ci_abs_tol, ci_niter) { + Leaf__ctor(vcmax_25, c, b, psi_crit, beta2, jmax_25, hk_s, a, curv_fact_elec_trans, curv_fact_colim, GSS_tol_abs, vulnerability_curve_ncontrol, ci_abs_tol, ci_niter) +} +.R6_Leaf <- + R6::R6Class( + "Leaf", + inherit=, + portable=TRUE, + public=list( + .ptr=NULL, + initialize = function(ptr) { + self$.ptr <- ptr + }, + initialize_integrator = function(integration_rule, integration_tol) { + Leaf__initialize_integrator(self, integration_rule, integration_tol) + }, + set_physiology = function(rho, a_bio, PPFD, psi_soil, leaf_specific_conductance_max, atm_vpd, ca, sapwood_volume_per_leaf_area, leaf_temp, atm_o2_kpa, atm_kpa) { + Leaf__set_physiology(self, rho, a_bio, PPFD, psi_soil, leaf_specific_conductance_max, atm_vpd, ca, sapwood_volume_per_leaf_area, leaf_temp, atm_o2_kpa, atm_kpa) + }, + proportion_of_conductivity = function(psi) { + Leaf__proportion_of_conductivity(self, psi) + }, + arrh_curve = function(Ea, ref_value, leaf_temp) { + Leaf__arrh_curve(self, Ea, ref_value, leaf_temp) + }, + peak_arrh_curve = function(Ea, ref_value, leaf_temp, H_d, d_S) { + Leaf__peak_arrh_curve(self, Ea, ref_value, leaf_temp, H_d, d_S) + }, + transpiration = function(psi_stem) { + Leaf__transpiration(self, psi_stem) + }, + transpiration_full_integration = function(psi_stem) { + Leaf__transpiration_full_integration(self, psi_stem) + }, + stom_cond_CO2 = function(psi_stem) { + Leaf__stom_cond_CO2(self, psi_stem) + }, + transpiration_to_psi_stem = function(transpiration_) { + Leaf__transpiration_to_psi_stem(self, transpiration_) + }, + assim_rubisco_limited = function(ci_) { + Leaf__assim_rubisco_limited(self, ci_) + }, + assim_electron_limited = function(ci_) { + Leaf__assim_electron_limited(self, ci_) + }, + assim_colimited = function(ci_) { + Leaf__assim_colimited(self, ci_) + }, + assim_minus_stom_cond_CO2 = function(x, psi_stem) { + Leaf__assim_minus_stom_cond_CO2(self, x, psi_stem) + }, + electron_transport = function() { + Leaf__electron_transport(self) + }, + set_leaf_states_rates_from_psi_stem = function(psi_stem) { + Leaf__set_leaf_states_rates_from_psi_stem(self, psi_stem) + }, + psi_stem_to_ci = function(psi_stem) { + Leaf__psi_stem_to_ci(self, psi_stem) + }, + hydraulic_cost_Sperry = function(psi_stem) { + Leaf__hydraulic_cost_Sperry(self, psi_stem) + }, + hydraulic_cost_TF = function(psi_stem) { + Leaf__hydraulic_cost_TF(self, psi_stem) + }, + profit_psi_stem_Sperry = function(psi_stem) { + Leaf__profit_psi_stem_Sperry(self, psi_stem) + }, + profit_Sperry_ci = function(ci_) { + Leaf__profit_Sperry_ci(self, ci_) + }, + profit_psi_stem_TF = function(psi_stem) { + Leaf__profit_psi_stem_TF(self, psi_stem) + }, + optimise_psi_stem_Sperry = function() { + Leaf__optimise_psi_stem_Sperry(self) + }, + optimise_ci_Sperry = function(max_ci) { + Leaf__optimise_ci_Sperry(self, max_ci) + }, + optimise_psi_stem_TF = function() { + Leaf__optimise_psi_stem_TF(self) + }), + active=list( + ci_ = function(value) { + if (missing(value)) { + Leaf__ci___get(self) + } else { + Leaf__ci___set(self, value) + } + }, + stom_cond_CO2_ = function(value) { + if (missing(value)) { + Leaf__stom_cond_CO2___get(self) + } else { + Leaf__stom_cond_CO2___set(self, value) + } + }, + assim_colimited_ = function(value) { + if (missing(value)) { + Leaf__assim_colimited___get(self) + } else { + Leaf__assim_colimited___set(self, value) + } + }, + transpiration_ = function(value) { + if (missing(value)) { + Leaf__transpiration___get(self) + } else { + Leaf__transpiration___set(self, value) + } + }, + profit_ = function(value) { + if (missing(value)) { + Leaf__profit___get(self) + } else { + Leaf__profit___set(self, value) + } + }, + psi_stem = function(value) { + if (missing(value)) { + Leaf__psi_stem__get(self) + } else { + Leaf__psi_stem__set(self, value) + } + }, + lambda_ = function(value) { + if (missing(value)) { + Leaf__lambda___get(self) + } else { + Leaf__lambda___set(self, value) + } + }, + lambda_analytical_ = function(value) { + if (missing(value)) { + Leaf__lambda_analytical___get(self) + } else { + Leaf__lambda_analytical___set(self, value) + } + }, + electron_transport_ = function(value) { + if (missing(value)) { + Leaf__electron_transport___get(self) + } else { + Leaf__electron_transport___set(self, value) + } + }, + gamma_ = function(value) { + if (missing(value)) { + Leaf__gamma___get(self) + } else { + Leaf__gamma___set(self, value) + } + }, + ko_ = function(value) { + if (missing(value)) { + Leaf__ko___get(self) + } else { + Leaf__ko___set(self, value) + } + }, + kc_ = function(value) { + if (missing(value)) { + Leaf__kc___get(self) + } else { + Leaf__kc___set(self, value) + } + }, + km_ = function(value) { + if (missing(value)) { + Leaf__km___get(self) + } else { + Leaf__km___set(self, value) + } + }, + R_d_ = function(value) { + if (missing(value)) { + Leaf__R_d___get(self) + } else { + Leaf__R_d___set(self, value) + } + }, + leaf_specific_conductance_max_ = function(value) { + if (missing(value)) { + Leaf__leaf_specific_conductance_max___get(self) + } else { + Leaf__leaf_specific_conductance_max___set(self, value) + } + }, + vcmax_ = function(value) { + if (missing(value)) { + Leaf__vcmax___get(self) + } else { + Leaf__vcmax___set(self, value) + } + }, + jmax_ = function(value) { + if (missing(value)) { + Leaf__jmax___get(self) + } else { + Leaf__jmax___set(self, value) + } + }, + rho_ = function(value) { + if (missing(value)) { + Leaf__rho___get(self) + } else { + Leaf__rho___set(self, value) + } + }, + a_bio_ = function(value) { + if (missing(value)) { + Leaf__a_bio___get(self) + } else { + Leaf__a_bio___set(self, value) + } + }, + PPFD_ = function(value) { + if (missing(value)) { + Leaf__PPFD___get(self) + } else { + Leaf__PPFD___set(self, value) + } + }, + atm_vpd_ = function(value) { + if (missing(value)) { + Leaf__atm_vpd___get(self) + } else { + Leaf__atm_vpd___set(self, value) + } + }, + ca_ = function(value) { + if (missing(value)) { + Leaf__ca___get(self) + } else { + Leaf__ca___set(self, value) + } + }, + psi_soil_ = function(value) { + if (missing(value)) { + Leaf__psi_soil___get(self) + } else { + Leaf__psi_soil___set(self, value) + } + }, + leaf_temp_ = function(value) { + if (missing(value)) { + Leaf__leaf_temp___get(self) + } else { + Leaf__leaf_temp___set(self, value) + } + }, + atm_o2_kpa_ = function(value) { + if (missing(value)) { + Leaf__atm_o2_kpa___get(self) + } else { + Leaf__atm_o2_kpa___set(self, value) + } + }, + atm_kpa_ = function(value) { + if (missing(value)) { + Leaf__atm_kpa___get(self) + } else { + Leaf__atm_kpa___set(self, value) + } + }, + hydraulic_cost_ = function(value) { + if (missing(value)) { + Leaf__hydraulic_cost___get(self) + } else { + Leaf__hydraulic_cost___set(self, value) + } + }, + opt_psi_stem_ = function(value) { + if (missing(value)) { + Leaf__opt_psi_stem___get(self) + } else { + Leaf__opt_psi_stem___set(self, value) + } + }, + opt_ci_ = function(value) { + if (missing(value)) { + Leaf__opt_ci___get(self) + } else { + Leaf__opt_ci___set(self, value) + } + }, + count = function(value) { + if (missing(value)) { + Leaf__count__get(self) + } else { + Leaf__count__set(self, value) + } + })) + `Lorenz` <- function(sigma, R, b) { Lorenz__ctor(sigma, R, b) diff --git a/inst/include/plant/RcppR6_post.hpp b/inst/include/plant/RcppR6_post.hpp index 4554bf9c..29650583 100644 --- a/inst/include/plant/RcppR6_post.hpp +++ b/inst/include/plant/RcppR6_post.hpp @@ -8,6 +8,9 @@ namespace plant { namespace RcppR6 { namespace traits { +template <> inline std::string class_name_r() {return "Leaf";} +template <> inline std::string package_name() {return "plant";} +template <> inline std::string generator_name() {return ".R6_Leaf";} template <> inline std::string class_name_r() {return "Lorenz";} template <> inline std::string package_name() {return "plant";} template <> inline std::string generator_name() {return ".R6_Lorenz";} @@ -315,6 +318,12 @@ class Exporter > { }; } +template <> inline SEXP wrap(const plant::Leaf& x) { + return wrap(plant::RcppR6::RcppR6(x)); +} +template <> inline plant::Leaf as(SEXP x) { + return *(plant::RcppR6::RcppR6(x)); +} template <> inline SEXP wrap(const plant::ode::test::Lorenz& x) { return wrap(plant::RcppR6::RcppR6(x)); } @@ -407,6 +416,10 @@ template <> inline SEXP wrap(const plant::Control& x) { ret["schedule_eps"] = Rcpp::wrap(x.schedule_eps); ret["schedule_verbose"] = Rcpp::wrap(x.schedule_verbose); ret["save_RK45_cache"] = Rcpp::wrap(x.save_RK45_cache); + ret["GSS_tol_abs"] = Rcpp::wrap(x.GSS_tol_abs); + ret["vulnerability_curve_ncontrol"] = Rcpp::wrap(x.vulnerability_curve_ncontrol); + ret["ci_abs_tol"] = Rcpp::wrap(x.ci_abs_tol); + ret["ci_niter"] = Rcpp::wrap(x.ci_niter); ret.attr("class") = "Control"; return ret; } @@ -455,6 +468,14 @@ template <> inline plant::Control as(SEXP x) { ret.schedule_verbose = Rcpp::as(xl["schedule_verbose"]); // ret.save_RK45_cache = Rcpp::as(xl["save_RK45_cache"]); ret.save_RK45_cache = Rcpp::as(xl["save_RK45_cache"]); + // ret.GSS_tol_abs = Rcpp::as(xl["GSS_tol_abs"]); + ret.GSS_tol_abs = Rcpp::as(xl["GSS_tol_abs"]); + // ret.vulnerability_curve_ncontrol = Rcpp::as(xl["vulnerability_curve_ncontrol"]); + ret.vulnerability_curve_ncontrol = Rcpp::as(xl["vulnerability_curve_ncontrol"]); + // ret.ci_abs_tol = Rcpp::as(xl["ci_abs_tol"]); + ret.ci_abs_tol = Rcpp::as(xl["ci_abs_tol"]); + // ret.ci_niter = Rcpp::as(xl["ci_niter"]); + ret.ci_niter = Rcpp::as(xl["ci_niter"]); return ret; } template <> inline SEXP wrap(const plant::ode::OdeControl& x) { diff --git a/inst/include/plant/RcppR6_pre.hpp b/inst/include/plant/RcppR6_pre.hpp index 1f1c074e..379deb2d 100644 --- a/inst/include/plant/RcppR6_pre.hpp +++ b/inst/include/plant/RcppR6_pre.hpp @@ -19,6 +19,8 @@ namespace traits { template class Exporter >; } +template <> SEXP wrap(const plant::Leaf&); +template <> plant::Leaf as(SEXP); template <> SEXP wrap(const plant::ode::test::Lorenz&); template <> plant::ode::test::Lorenz as(SEXP); template <> SEXP wrap(const plant::ode::test::OdeR&); diff --git a/man/Leaf.Rd b/man/Leaf.Rd new file mode 100644 index 00000000..9ca2acf5 --- /dev/null +++ b/man/Leaf.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/RcppR6.R +\name{Leaf} +\alias{Leaf} +\title{Leaf model} +\usage{ +Leaf( + vcmax_25, + c, + b, + psi_crit, + beta2, + jmax_25, + hk_s, + a, + curv_fact_elec_trans, + curv_fact_colim, + GSS_tol_abs, + vulnerability_curve_ncontrol, + ci_abs_tol, + ci_niter +) +} +\arguments{ +\item{vcmax_25}{rubisco rate} +} +\description{ +Leaf model +} diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index e8d8b048..c6385ed8 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -11,6 +11,987 @@ Rcpp::Rostream& Rcpp::Rcout = Rcpp::Rcpp_cout_get(); Rcpp::Rostream& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get(); #endif +// Leaf__ctor +plant::Leaf Leaf__ctor(double vcmax_25, double c, double b, double psi_crit, double beta2, double jmax_25, double hk_s, double a, double curv_fact_elec_trans, double curv_fact_colim, double GSS_tol_abs, double vulnerability_curve_ncontrol, double ci_abs_tol, double ci_niter); +RcppExport SEXP _plant_Leaf__ctor(SEXP vcmax_25SEXP, SEXP cSEXP, SEXP bSEXP, SEXP psi_critSEXP, SEXP beta2SEXP, SEXP jmax_25SEXP, SEXP hk_sSEXP, SEXP aSEXP, SEXP curv_fact_elec_transSEXP, SEXP curv_fact_colimSEXP, SEXP GSS_tol_absSEXP, SEXP vulnerability_curve_ncontrolSEXP, SEXP ci_abs_tolSEXP, SEXP ci_niterSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< double >::type vcmax_25(vcmax_25SEXP); + Rcpp::traits::input_parameter< double >::type c(cSEXP); + Rcpp::traits::input_parameter< double >::type b(bSEXP); + Rcpp::traits::input_parameter< double >::type psi_crit(psi_critSEXP); + Rcpp::traits::input_parameter< double >::type beta2(beta2SEXP); + Rcpp::traits::input_parameter< double >::type jmax_25(jmax_25SEXP); + Rcpp::traits::input_parameter< double >::type hk_s(hk_sSEXP); + Rcpp::traits::input_parameter< double >::type a(aSEXP); + Rcpp::traits::input_parameter< double >::type curv_fact_elec_trans(curv_fact_elec_transSEXP); + Rcpp::traits::input_parameter< double >::type curv_fact_colim(curv_fact_colimSEXP); + Rcpp::traits::input_parameter< double >::type GSS_tol_abs(GSS_tol_absSEXP); + Rcpp::traits::input_parameter< double >::type vulnerability_curve_ncontrol(vulnerability_curve_ncontrolSEXP); + Rcpp::traits::input_parameter< double >::type ci_abs_tol(ci_abs_tolSEXP); + Rcpp::traits::input_parameter< double >::type ci_niter(ci_niterSEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__ctor(vcmax_25, c, b, psi_crit, beta2, jmax_25, hk_s, a, curv_fact_elec_trans, curv_fact_colim, GSS_tol_abs, vulnerability_curve_ncontrol, ci_abs_tol, ci_niter)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__initialize_integrator +void Leaf__initialize_integrator(plant::RcppR6::RcppR6 obj_, int integration_rule, double integration_tol); +RcppExport SEXP _plant_Leaf__initialize_integrator(SEXP obj_SEXP, SEXP integration_ruleSEXP, SEXP integration_tolSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< int >::type integration_rule(integration_ruleSEXP); + Rcpp::traits::input_parameter< double >::type integration_tol(integration_tolSEXP); + Leaf__initialize_integrator(obj_, integration_rule, integration_tol); + return R_NilValue; +END_RCPP +} +// Leaf__set_physiology +void Leaf__set_physiology(plant::RcppR6::RcppR6 obj_, double rho, double a_bio, double PPFD, double psi_soil, double leaf_specific_conductance_max, double atm_vpd, double ca, double sapwood_volume_per_leaf_area, double leaf_temp, double atm_o2_kpa, double atm_kpa); +RcppExport SEXP _plant_Leaf__set_physiology(SEXP obj_SEXP, SEXP rhoSEXP, SEXP a_bioSEXP, SEXP PPFDSEXP, SEXP psi_soilSEXP, SEXP leaf_specific_conductance_maxSEXP, SEXP atm_vpdSEXP, SEXP caSEXP, SEXP sapwood_volume_per_leaf_areaSEXP, SEXP leaf_tempSEXP, SEXP atm_o2_kpaSEXP, SEXP atm_kpaSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type rho(rhoSEXP); + Rcpp::traits::input_parameter< double >::type a_bio(a_bioSEXP); + Rcpp::traits::input_parameter< double >::type PPFD(PPFDSEXP); + Rcpp::traits::input_parameter< double >::type psi_soil(psi_soilSEXP); + Rcpp::traits::input_parameter< double >::type leaf_specific_conductance_max(leaf_specific_conductance_maxSEXP); + Rcpp::traits::input_parameter< double >::type atm_vpd(atm_vpdSEXP); + Rcpp::traits::input_parameter< double >::type ca(caSEXP); + Rcpp::traits::input_parameter< double >::type sapwood_volume_per_leaf_area(sapwood_volume_per_leaf_areaSEXP); + Rcpp::traits::input_parameter< double >::type leaf_temp(leaf_tempSEXP); + Rcpp::traits::input_parameter< double >::type atm_o2_kpa(atm_o2_kpaSEXP); + Rcpp::traits::input_parameter< double >::type atm_kpa(atm_kpaSEXP); + Leaf__set_physiology(obj_, rho, a_bio, PPFD, psi_soil, leaf_specific_conductance_max, atm_vpd, ca, sapwood_volume_per_leaf_area, leaf_temp, atm_o2_kpa, atm_kpa); + return R_NilValue; +END_RCPP +} +// Leaf__proportion_of_conductivity +double Leaf__proportion_of_conductivity(plant::RcppR6::RcppR6 obj_, double psi); +RcppExport SEXP _plant_Leaf__proportion_of_conductivity(SEXP obj_SEXP, SEXP psiSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type psi(psiSEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__proportion_of_conductivity(obj_, psi)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__arrh_curve +double Leaf__arrh_curve(plant::RcppR6::RcppR6 obj_, double Ea, double ref_value, double leaf_temp); +RcppExport SEXP _plant_Leaf__arrh_curve(SEXP obj_SEXP, SEXP EaSEXP, SEXP ref_valueSEXP, SEXP leaf_tempSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type Ea(EaSEXP); + Rcpp::traits::input_parameter< double >::type ref_value(ref_valueSEXP); + Rcpp::traits::input_parameter< double >::type leaf_temp(leaf_tempSEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__arrh_curve(obj_, Ea, ref_value, leaf_temp)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__peak_arrh_curve +double Leaf__peak_arrh_curve(plant::RcppR6::RcppR6 obj_, double Ea, double ref_value, double leaf_temp, double H_d, double d_S); +RcppExport SEXP _plant_Leaf__peak_arrh_curve(SEXP obj_SEXP, SEXP EaSEXP, SEXP ref_valueSEXP, SEXP leaf_tempSEXP, SEXP H_dSEXP, SEXP d_SSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type Ea(EaSEXP); + Rcpp::traits::input_parameter< double >::type ref_value(ref_valueSEXP); + Rcpp::traits::input_parameter< double >::type leaf_temp(leaf_tempSEXP); + Rcpp::traits::input_parameter< double >::type H_d(H_dSEXP); + Rcpp::traits::input_parameter< double >::type d_S(d_SSEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__peak_arrh_curve(obj_, Ea, ref_value, leaf_temp, H_d, d_S)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__transpiration +double Leaf__transpiration(plant::RcppR6::RcppR6 obj_, double psi_stem); +RcppExport SEXP _plant_Leaf__transpiration(SEXP obj_SEXP, SEXP psi_stemSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type psi_stem(psi_stemSEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__transpiration(obj_, psi_stem)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__transpiration_full_integration +double Leaf__transpiration_full_integration(plant::RcppR6::RcppR6 obj_, double psi_stem); +RcppExport SEXP _plant_Leaf__transpiration_full_integration(SEXP obj_SEXP, SEXP psi_stemSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type psi_stem(psi_stemSEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__transpiration_full_integration(obj_, psi_stem)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__stom_cond_CO2 +double Leaf__stom_cond_CO2(plant::RcppR6::RcppR6 obj_, double psi_stem); +RcppExport SEXP _plant_Leaf__stom_cond_CO2(SEXP obj_SEXP, SEXP psi_stemSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type psi_stem(psi_stemSEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__stom_cond_CO2(obj_, psi_stem)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__transpiration_to_psi_stem +double Leaf__transpiration_to_psi_stem(plant::RcppR6::RcppR6 obj_, double transpiration_); +RcppExport SEXP _plant_Leaf__transpiration_to_psi_stem(SEXP obj_SEXP, SEXP transpiration_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type transpiration_(transpiration_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__transpiration_to_psi_stem(obj_, transpiration_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__assim_rubisco_limited +double Leaf__assim_rubisco_limited(plant::RcppR6::RcppR6 obj_, double ci_); +RcppExport SEXP _plant_Leaf__assim_rubisco_limited(SEXP obj_SEXP, SEXP ci_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type ci_(ci_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__assim_rubisco_limited(obj_, ci_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__assim_electron_limited +double Leaf__assim_electron_limited(plant::RcppR6::RcppR6 obj_, double ci_); +RcppExport SEXP _plant_Leaf__assim_electron_limited(SEXP obj_SEXP, SEXP ci_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type ci_(ci_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__assim_electron_limited(obj_, ci_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__assim_colimited +double Leaf__assim_colimited(plant::RcppR6::RcppR6 obj_, double ci_); +RcppExport SEXP _plant_Leaf__assim_colimited(SEXP obj_SEXP, SEXP ci_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type ci_(ci_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__assim_colimited(obj_, ci_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__assim_minus_stom_cond_CO2 +double Leaf__assim_minus_stom_cond_CO2(plant::RcppR6::RcppR6 obj_, double x, double psi_stem); +RcppExport SEXP _plant_Leaf__assim_minus_stom_cond_CO2(SEXP obj_SEXP, SEXP xSEXP, SEXP psi_stemSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type x(xSEXP); + Rcpp::traits::input_parameter< double >::type psi_stem(psi_stemSEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__assim_minus_stom_cond_CO2(obj_, x, psi_stem)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__electron_transport +double Leaf__electron_transport(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__electron_transport(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__electron_transport(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__set_leaf_states_rates_from_psi_stem +void Leaf__set_leaf_states_rates_from_psi_stem(plant::RcppR6::RcppR6 obj_, double psi_stem); +RcppExport SEXP _plant_Leaf__set_leaf_states_rates_from_psi_stem(SEXP obj_SEXP, SEXP psi_stemSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type psi_stem(psi_stemSEXP); + Leaf__set_leaf_states_rates_from_psi_stem(obj_, psi_stem); + return R_NilValue; +END_RCPP +} +// Leaf__psi_stem_to_ci +double Leaf__psi_stem_to_ci(plant::RcppR6::RcppR6 obj_, double psi_stem); +RcppExport SEXP _plant_Leaf__psi_stem_to_ci(SEXP obj_SEXP, SEXP psi_stemSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type psi_stem(psi_stemSEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__psi_stem_to_ci(obj_, psi_stem)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__hydraulic_cost_Sperry +double Leaf__hydraulic_cost_Sperry(plant::RcppR6::RcppR6 obj_, double psi_stem); +RcppExport SEXP _plant_Leaf__hydraulic_cost_Sperry(SEXP obj_SEXP, SEXP psi_stemSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type psi_stem(psi_stemSEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__hydraulic_cost_Sperry(obj_, psi_stem)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__hydraulic_cost_TF +double Leaf__hydraulic_cost_TF(plant::RcppR6::RcppR6 obj_, double psi_stem); +RcppExport SEXP _plant_Leaf__hydraulic_cost_TF(SEXP obj_SEXP, SEXP psi_stemSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type psi_stem(psi_stemSEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__hydraulic_cost_TF(obj_, psi_stem)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__profit_psi_stem_Sperry +double Leaf__profit_psi_stem_Sperry(plant::RcppR6::RcppR6 obj_, double psi_stem); +RcppExport SEXP _plant_Leaf__profit_psi_stem_Sperry(SEXP obj_SEXP, SEXP psi_stemSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type psi_stem(psi_stemSEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__profit_psi_stem_Sperry(obj_, psi_stem)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__profit_Sperry_ci +double Leaf__profit_Sperry_ci(plant::RcppR6::RcppR6 obj_, double ci_); +RcppExport SEXP _plant_Leaf__profit_Sperry_ci(SEXP obj_SEXP, SEXP ci_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type ci_(ci_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__profit_Sperry_ci(obj_, ci_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__profit_psi_stem_TF +double Leaf__profit_psi_stem_TF(plant::RcppR6::RcppR6 obj_, double psi_stem); +RcppExport SEXP _plant_Leaf__profit_psi_stem_TF(SEXP obj_SEXP, SEXP psi_stemSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type psi_stem(psi_stemSEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__profit_psi_stem_TF(obj_, psi_stem)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__optimise_psi_stem_Sperry +void Leaf__optimise_psi_stem_Sperry(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__optimise_psi_stem_Sperry(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Leaf__optimise_psi_stem_Sperry(obj_); + return R_NilValue; +END_RCPP +} +// Leaf__optimise_ci_Sperry +void Leaf__optimise_ci_Sperry(plant::RcppR6::RcppR6 obj_, double max_ci); +RcppExport SEXP _plant_Leaf__optimise_ci_Sperry(SEXP obj_SEXP, SEXP max_ciSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type max_ci(max_ciSEXP); + Leaf__optimise_ci_Sperry(obj_, max_ci); + return R_NilValue; +END_RCPP +} +// Leaf__optimise_psi_stem_TF +void Leaf__optimise_psi_stem_TF(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__optimise_psi_stem_TF(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Leaf__optimise_psi_stem_TF(obj_); + return R_NilValue; +END_RCPP +} +// Leaf__ci___get +double Leaf__ci___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__ci___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__ci___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__ci___set +void Leaf__ci___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__ci___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__ci___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__stom_cond_CO2___get +double Leaf__stom_cond_CO2___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__stom_cond_CO2___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__stom_cond_CO2___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__stom_cond_CO2___set +void Leaf__stom_cond_CO2___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__stom_cond_CO2___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__stom_cond_CO2___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__assim_colimited___get +double Leaf__assim_colimited___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__assim_colimited___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__assim_colimited___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__assim_colimited___set +void Leaf__assim_colimited___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__assim_colimited___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__assim_colimited___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__transpiration___get +double Leaf__transpiration___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__transpiration___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__transpiration___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__transpiration___set +void Leaf__transpiration___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__transpiration___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__transpiration___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__profit___get +double Leaf__profit___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__profit___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__profit___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__profit___set +void Leaf__profit___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__profit___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__profit___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__psi_stem__get +double Leaf__psi_stem__get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__psi_stem__get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__psi_stem__get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__psi_stem__set +void Leaf__psi_stem__set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__psi_stem__set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__psi_stem__set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__lambda___get +double Leaf__lambda___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__lambda___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__lambda___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__lambda___set +void Leaf__lambda___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__lambda___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__lambda___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__lambda_analytical___get +double Leaf__lambda_analytical___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__lambda_analytical___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__lambda_analytical___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__lambda_analytical___set +void Leaf__lambda_analytical___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__lambda_analytical___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__lambda_analytical___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__electron_transport___get +double Leaf__electron_transport___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__electron_transport___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__electron_transport___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__electron_transport___set +void Leaf__electron_transport___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__electron_transport___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__electron_transport___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__gamma___get +double Leaf__gamma___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__gamma___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__gamma___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__gamma___set +void Leaf__gamma___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__gamma___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__gamma___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__ko___get +double Leaf__ko___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__ko___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__ko___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__ko___set +void Leaf__ko___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__ko___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__ko___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__kc___get +double Leaf__kc___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__kc___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__kc___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__kc___set +void Leaf__kc___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__kc___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__kc___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__km___get +double Leaf__km___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__km___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__km___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__km___set +void Leaf__km___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__km___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__km___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__R_d___get +double Leaf__R_d___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__R_d___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__R_d___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__R_d___set +void Leaf__R_d___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__R_d___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__R_d___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__leaf_specific_conductance_max___get +double Leaf__leaf_specific_conductance_max___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__leaf_specific_conductance_max___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__leaf_specific_conductance_max___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__leaf_specific_conductance_max___set +void Leaf__leaf_specific_conductance_max___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__leaf_specific_conductance_max___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__leaf_specific_conductance_max___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__vcmax___get +double Leaf__vcmax___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__vcmax___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__vcmax___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__vcmax___set +void Leaf__vcmax___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__vcmax___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__vcmax___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__jmax___get +double Leaf__jmax___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__jmax___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__jmax___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__jmax___set +void Leaf__jmax___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__jmax___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__jmax___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__rho___get +double Leaf__rho___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__rho___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__rho___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__rho___set +void Leaf__rho___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__rho___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__rho___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__a_bio___get +double Leaf__a_bio___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__a_bio___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__a_bio___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__a_bio___set +void Leaf__a_bio___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__a_bio___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__a_bio___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__PPFD___get +double Leaf__PPFD___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__PPFD___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__PPFD___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__PPFD___set +void Leaf__PPFD___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__PPFD___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__PPFD___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__atm_vpd___get +double Leaf__atm_vpd___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__atm_vpd___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__atm_vpd___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__atm_vpd___set +void Leaf__atm_vpd___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__atm_vpd___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__atm_vpd___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__ca___get +double Leaf__ca___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__ca___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__ca___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__ca___set +void Leaf__ca___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__ca___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__ca___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__psi_soil___get +double Leaf__psi_soil___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__psi_soil___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__psi_soil___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__psi_soil___set +void Leaf__psi_soil___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__psi_soil___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__psi_soil___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__leaf_temp___get +double Leaf__leaf_temp___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__leaf_temp___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__leaf_temp___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__leaf_temp___set +void Leaf__leaf_temp___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__leaf_temp___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__leaf_temp___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__atm_o2_kpa___get +double Leaf__atm_o2_kpa___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__atm_o2_kpa___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__atm_o2_kpa___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__atm_o2_kpa___set +void Leaf__atm_o2_kpa___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__atm_o2_kpa___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__atm_o2_kpa___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__atm_kpa___get +double Leaf__atm_kpa___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__atm_kpa___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__atm_kpa___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__atm_kpa___set +void Leaf__atm_kpa___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__atm_kpa___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__atm_kpa___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__hydraulic_cost___get +double Leaf__hydraulic_cost___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__hydraulic_cost___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__hydraulic_cost___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__hydraulic_cost___set +void Leaf__hydraulic_cost___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__hydraulic_cost___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__hydraulic_cost___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__opt_psi_stem___get +double Leaf__opt_psi_stem___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__opt_psi_stem___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__opt_psi_stem___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__opt_psi_stem___set +void Leaf__opt_psi_stem___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__opt_psi_stem___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__opt_psi_stem___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__opt_ci___get +double Leaf__opt_ci___get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__opt_ci___get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__opt_ci___get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__opt_ci___set +void Leaf__opt_ci___set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__opt_ci___set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__opt_ci___set(obj_, value); + return R_NilValue; +END_RCPP +} +// Leaf__count__get +double Leaf__count__get(plant::RcppR6::RcppR6 obj_); +RcppExport SEXP _plant_Leaf__count__get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Leaf__count__get(obj_)); + return rcpp_result_gen; +END_RCPP +} +// Leaf__count__set +void Leaf__count__set(plant::RcppR6::RcppR6 obj_, double value); +RcppExport SEXP _plant_Leaf__count__set(SEXP obj_SEXP, SEXP valueSEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 >::type obj_(obj_SEXP); + Rcpp::traits::input_parameter< double >::type value(valueSEXP); + Leaf__count__set(obj_, value); + return R_NilValue; +END_RCPP +} // Lorenz__ctor plant::ode::test::Lorenz Lorenz__ctor(double sigma, double R, double b); RcppExport SEXP _plant_Lorenz__ctor(SEXP sigmaSEXP, SEXP RSEXP, SEXP bSEXP) { @@ -12251,6 +13232,91 @@ END_RCPP } static const R_CallMethodDef CallEntries[] = { + {"_plant_Leaf__ctor", (DL_FUNC) &_plant_Leaf__ctor, 14}, + {"_plant_Leaf__initialize_integrator", (DL_FUNC) &_plant_Leaf__initialize_integrator, 3}, + {"_plant_Leaf__set_physiology", (DL_FUNC) &_plant_Leaf__set_physiology, 12}, + {"_plant_Leaf__proportion_of_conductivity", (DL_FUNC) &_plant_Leaf__proportion_of_conductivity, 2}, + {"_plant_Leaf__arrh_curve", (DL_FUNC) &_plant_Leaf__arrh_curve, 4}, + {"_plant_Leaf__peak_arrh_curve", (DL_FUNC) &_plant_Leaf__peak_arrh_curve, 6}, + {"_plant_Leaf__transpiration", (DL_FUNC) &_plant_Leaf__transpiration, 2}, + {"_plant_Leaf__transpiration_full_integration", (DL_FUNC) &_plant_Leaf__transpiration_full_integration, 2}, + {"_plant_Leaf__stom_cond_CO2", (DL_FUNC) &_plant_Leaf__stom_cond_CO2, 2}, + {"_plant_Leaf__transpiration_to_psi_stem", (DL_FUNC) &_plant_Leaf__transpiration_to_psi_stem, 2}, + {"_plant_Leaf__assim_rubisco_limited", (DL_FUNC) &_plant_Leaf__assim_rubisco_limited, 2}, + {"_plant_Leaf__assim_electron_limited", (DL_FUNC) &_plant_Leaf__assim_electron_limited, 2}, + {"_plant_Leaf__assim_colimited", (DL_FUNC) &_plant_Leaf__assim_colimited, 2}, + {"_plant_Leaf__assim_minus_stom_cond_CO2", (DL_FUNC) &_plant_Leaf__assim_minus_stom_cond_CO2, 3}, + {"_plant_Leaf__electron_transport", (DL_FUNC) &_plant_Leaf__electron_transport, 1}, + {"_plant_Leaf__set_leaf_states_rates_from_psi_stem", (DL_FUNC) &_plant_Leaf__set_leaf_states_rates_from_psi_stem, 2}, + {"_plant_Leaf__psi_stem_to_ci", (DL_FUNC) &_plant_Leaf__psi_stem_to_ci, 2}, + {"_plant_Leaf__hydraulic_cost_Sperry", (DL_FUNC) &_plant_Leaf__hydraulic_cost_Sperry, 2}, + {"_plant_Leaf__hydraulic_cost_TF", (DL_FUNC) &_plant_Leaf__hydraulic_cost_TF, 2}, + {"_plant_Leaf__profit_psi_stem_Sperry", (DL_FUNC) &_plant_Leaf__profit_psi_stem_Sperry, 2}, + {"_plant_Leaf__profit_Sperry_ci", (DL_FUNC) &_plant_Leaf__profit_Sperry_ci, 2}, + {"_plant_Leaf__profit_psi_stem_TF", (DL_FUNC) &_plant_Leaf__profit_psi_stem_TF, 2}, + {"_plant_Leaf__optimise_psi_stem_Sperry", (DL_FUNC) &_plant_Leaf__optimise_psi_stem_Sperry, 1}, + {"_plant_Leaf__optimise_ci_Sperry", (DL_FUNC) &_plant_Leaf__optimise_ci_Sperry, 2}, + {"_plant_Leaf__optimise_psi_stem_TF", (DL_FUNC) &_plant_Leaf__optimise_psi_stem_TF, 1}, + {"_plant_Leaf__ci___get", (DL_FUNC) &_plant_Leaf__ci___get, 1}, + {"_plant_Leaf__ci___set", (DL_FUNC) &_plant_Leaf__ci___set, 2}, + {"_plant_Leaf__stom_cond_CO2___get", (DL_FUNC) &_plant_Leaf__stom_cond_CO2___get, 1}, + {"_plant_Leaf__stom_cond_CO2___set", (DL_FUNC) &_plant_Leaf__stom_cond_CO2___set, 2}, + {"_plant_Leaf__assim_colimited___get", (DL_FUNC) &_plant_Leaf__assim_colimited___get, 1}, + {"_plant_Leaf__assim_colimited___set", (DL_FUNC) &_plant_Leaf__assim_colimited___set, 2}, + {"_plant_Leaf__transpiration___get", (DL_FUNC) &_plant_Leaf__transpiration___get, 1}, + {"_plant_Leaf__transpiration___set", (DL_FUNC) &_plant_Leaf__transpiration___set, 2}, + {"_plant_Leaf__profit___get", (DL_FUNC) &_plant_Leaf__profit___get, 1}, + {"_plant_Leaf__profit___set", (DL_FUNC) &_plant_Leaf__profit___set, 2}, + {"_plant_Leaf__psi_stem__get", (DL_FUNC) &_plant_Leaf__psi_stem__get, 1}, + {"_plant_Leaf__psi_stem__set", (DL_FUNC) &_plant_Leaf__psi_stem__set, 2}, + {"_plant_Leaf__lambda___get", (DL_FUNC) &_plant_Leaf__lambda___get, 1}, + {"_plant_Leaf__lambda___set", (DL_FUNC) &_plant_Leaf__lambda___set, 2}, + {"_plant_Leaf__lambda_analytical___get", (DL_FUNC) &_plant_Leaf__lambda_analytical___get, 1}, + {"_plant_Leaf__lambda_analytical___set", (DL_FUNC) &_plant_Leaf__lambda_analytical___set, 2}, + {"_plant_Leaf__electron_transport___get", (DL_FUNC) &_plant_Leaf__electron_transport___get, 1}, + {"_plant_Leaf__electron_transport___set", (DL_FUNC) &_plant_Leaf__electron_transport___set, 2}, + {"_plant_Leaf__gamma___get", (DL_FUNC) &_plant_Leaf__gamma___get, 1}, + {"_plant_Leaf__gamma___set", (DL_FUNC) &_plant_Leaf__gamma___set, 2}, + {"_plant_Leaf__ko___get", (DL_FUNC) &_plant_Leaf__ko___get, 1}, + {"_plant_Leaf__ko___set", (DL_FUNC) &_plant_Leaf__ko___set, 2}, + {"_plant_Leaf__kc___get", (DL_FUNC) &_plant_Leaf__kc___get, 1}, + {"_plant_Leaf__kc___set", (DL_FUNC) &_plant_Leaf__kc___set, 2}, + {"_plant_Leaf__km___get", (DL_FUNC) &_plant_Leaf__km___get, 1}, + {"_plant_Leaf__km___set", (DL_FUNC) &_plant_Leaf__km___set, 2}, + {"_plant_Leaf__R_d___get", (DL_FUNC) &_plant_Leaf__R_d___get, 1}, + {"_plant_Leaf__R_d___set", (DL_FUNC) &_plant_Leaf__R_d___set, 2}, + {"_plant_Leaf__leaf_specific_conductance_max___get", (DL_FUNC) &_plant_Leaf__leaf_specific_conductance_max___get, 1}, + {"_plant_Leaf__leaf_specific_conductance_max___set", (DL_FUNC) &_plant_Leaf__leaf_specific_conductance_max___set, 2}, + {"_plant_Leaf__vcmax___get", (DL_FUNC) &_plant_Leaf__vcmax___get, 1}, + {"_plant_Leaf__vcmax___set", (DL_FUNC) &_plant_Leaf__vcmax___set, 2}, + {"_plant_Leaf__jmax___get", (DL_FUNC) &_plant_Leaf__jmax___get, 1}, + {"_plant_Leaf__jmax___set", (DL_FUNC) &_plant_Leaf__jmax___set, 2}, + {"_plant_Leaf__rho___get", (DL_FUNC) &_plant_Leaf__rho___get, 1}, + {"_plant_Leaf__rho___set", (DL_FUNC) &_plant_Leaf__rho___set, 2}, + {"_plant_Leaf__a_bio___get", (DL_FUNC) &_plant_Leaf__a_bio___get, 1}, + {"_plant_Leaf__a_bio___set", (DL_FUNC) &_plant_Leaf__a_bio___set, 2}, + {"_plant_Leaf__PPFD___get", (DL_FUNC) &_plant_Leaf__PPFD___get, 1}, + {"_plant_Leaf__PPFD___set", (DL_FUNC) &_plant_Leaf__PPFD___set, 2}, + {"_plant_Leaf__atm_vpd___get", (DL_FUNC) &_plant_Leaf__atm_vpd___get, 1}, + {"_plant_Leaf__atm_vpd___set", (DL_FUNC) &_plant_Leaf__atm_vpd___set, 2}, + {"_plant_Leaf__ca___get", (DL_FUNC) &_plant_Leaf__ca___get, 1}, + {"_plant_Leaf__ca___set", (DL_FUNC) &_plant_Leaf__ca___set, 2}, + {"_plant_Leaf__psi_soil___get", (DL_FUNC) &_plant_Leaf__psi_soil___get, 1}, + {"_plant_Leaf__psi_soil___set", (DL_FUNC) &_plant_Leaf__psi_soil___set, 2}, + {"_plant_Leaf__leaf_temp___get", (DL_FUNC) &_plant_Leaf__leaf_temp___get, 1}, + {"_plant_Leaf__leaf_temp___set", (DL_FUNC) &_plant_Leaf__leaf_temp___set, 2}, + {"_plant_Leaf__atm_o2_kpa___get", (DL_FUNC) &_plant_Leaf__atm_o2_kpa___get, 1}, + {"_plant_Leaf__atm_o2_kpa___set", (DL_FUNC) &_plant_Leaf__atm_o2_kpa___set, 2}, + {"_plant_Leaf__atm_kpa___get", (DL_FUNC) &_plant_Leaf__atm_kpa___get, 1}, + {"_plant_Leaf__atm_kpa___set", (DL_FUNC) &_plant_Leaf__atm_kpa___set, 2}, + {"_plant_Leaf__hydraulic_cost___get", (DL_FUNC) &_plant_Leaf__hydraulic_cost___get, 1}, + {"_plant_Leaf__hydraulic_cost___set", (DL_FUNC) &_plant_Leaf__hydraulic_cost___set, 2}, + {"_plant_Leaf__opt_psi_stem___get", (DL_FUNC) &_plant_Leaf__opt_psi_stem___get, 1}, + {"_plant_Leaf__opt_psi_stem___set", (DL_FUNC) &_plant_Leaf__opt_psi_stem___set, 2}, + {"_plant_Leaf__opt_ci___get", (DL_FUNC) &_plant_Leaf__opt_ci___get, 1}, + {"_plant_Leaf__opt_ci___set", (DL_FUNC) &_plant_Leaf__opt_ci___set, 2}, + {"_plant_Leaf__count__get", (DL_FUNC) &_plant_Leaf__count__get, 1}, + {"_plant_Leaf__count__set", (DL_FUNC) &_plant_Leaf__count__set, 2}, {"_plant_Lorenz__ctor", (DL_FUNC) &_plant_Lorenz__ctor, 3}, {"_plant_Lorenz__ode_size__get", (DL_FUNC) &_plant_Lorenz__ode_size__get, 1}, {"_plant_Lorenz__ode_state__get", (DL_FUNC) &_plant_Lorenz__ode_state__get, 1}, diff --git a/src/RcppR6.cpp b/src/RcppR6.cpp index 4f5d1bfa..d5a6642d 100644 --- a/src/RcppR6.cpp +++ b/src/RcppR6.cpp @@ -1,6 +1,377 @@ // Generated by RcppR6 (0.2.4): do not edit by hand #include +// [[Rcpp::export]] +plant::Leaf Leaf__ctor(double vcmax_25, double c, double b, double psi_crit, double beta2, double jmax_25, double hk_s, double a, double curv_fact_elec_trans, double curv_fact_colim, double GSS_tol_abs, double vulnerability_curve_ncontrol, double ci_abs_tol, double ci_niter) { + return plant::Leaf(vcmax_25, c, b, psi_crit, beta2, jmax_25, hk_s, a, curv_fact_elec_trans, curv_fact_colim, GSS_tol_abs, vulnerability_curve_ncontrol, ci_abs_tol, ci_niter); +} +// [[Rcpp::export]] +void Leaf__initialize_integrator(plant::RcppR6::RcppR6 obj_, int integration_rule, double integration_tol) { + obj_->initialize_integrator(integration_rule, integration_tol); +} +// [[Rcpp::export]] +void Leaf__set_physiology(plant::RcppR6::RcppR6 obj_, double rho, double a_bio, double PPFD, double psi_soil, double leaf_specific_conductance_max, double atm_vpd, double ca, double sapwood_volume_per_leaf_area, double leaf_temp, double atm_o2_kpa, double atm_kpa) { + obj_->set_physiology(rho, a_bio, PPFD, psi_soil, leaf_specific_conductance_max, atm_vpd, ca, sapwood_volume_per_leaf_area, leaf_temp, atm_o2_kpa, atm_kpa); +} +// [[Rcpp::export]] +double Leaf__proportion_of_conductivity(plant::RcppR6::RcppR6 obj_, double psi) { + return obj_->proportion_of_conductivity(psi); +} +// [[Rcpp::export]] +double Leaf__arrh_curve(plant::RcppR6::RcppR6 obj_, double Ea, double ref_value, double leaf_temp) { + return obj_->arrh_curve(Ea, ref_value, leaf_temp); +} +// [[Rcpp::export]] +double Leaf__peak_arrh_curve(plant::RcppR6::RcppR6 obj_, double Ea, double ref_value, double leaf_temp, double H_d, double d_S) { + return obj_->peak_arrh_curve(Ea, ref_value, leaf_temp, H_d, d_S); +} +// [[Rcpp::export]] +double Leaf__transpiration(plant::RcppR6::RcppR6 obj_, double psi_stem) { + return obj_->transpiration(psi_stem); +} +// [[Rcpp::export]] +double Leaf__transpiration_full_integration(plant::RcppR6::RcppR6 obj_, double psi_stem) { + return obj_->transpiration_full_integration(psi_stem); +} +// [[Rcpp::export]] +double Leaf__stom_cond_CO2(plant::RcppR6::RcppR6 obj_, double psi_stem) { + return obj_->stom_cond_CO2(psi_stem); +} +// [[Rcpp::export]] +double Leaf__transpiration_to_psi_stem(plant::RcppR6::RcppR6 obj_, double transpiration_) { + return obj_->transpiration_to_psi_stem(transpiration_); +} +// [[Rcpp::export]] +double Leaf__assim_rubisco_limited(plant::RcppR6::RcppR6 obj_, double ci_) { + return obj_->assim_rubisco_limited(ci_); +} +// [[Rcpp::export]] +double Leaf__assim_electron_limited(plant::RcppR6::RcppR6 obj_, double ci_) { + return obj_->assim_electron_limited(ci_); +} +// [[Rcpp::export]] +double Leaf__assim_colimited(plant::RcppR6::RcppR6 obj_, double ci_) { + return obj_->assim_colimited(ci_); +} +// [[Rcpp::export]] +double Leaf__assim_minus_stom_cond_CO2(plant::RcppR6::RcppR6 obj_, double x, double psi_stem) { + return obj_->assim_minus_stom_cond_CO2(x, psi_stem); +} +// [[Rcpp::export]] +double Leaf__electron_transport(plant::RcppR6::RcppR6 obj_) { + return obj_->electron_transport(); +} +// [[Rcpp::export]] +void Leaf__set_leaf_states_rates_from_psi_stem(plant::RcppR6::RcppR6 obj_, double psi_stem) { + obj_->set_leaf_states_rates_from_psi_stem(psi_stem); +} +// [[Rcpp::export]] +double Leaf__psi_stem_to_ci(plant::RcppR6::RcppR6 obj_, double psi_stem) { + return obj_->psi_stem_to_ci(psi_stem); +} +// [[Rcpp::export]] +double Leaf__hydraulic_cost_Sperry(plant::RcppR6::RcppR6 obj_, double psi_stem) { + return obj_->hydraulic_cost_Sperry(psi_stem); +} +// [[Rcpp::export]] +double Leaf__hydraulic_cost_TF(plant::RcppR6::RcppR6 obj_, double psi_stem) { + return obj_->hydraulic_cost_TF(psi_stem); +} +// [[Rcpp::export]] +double Leaf__profit_psi_stem_Sperry(plant::RcppR6::RcppR6 obj_, double psi_stem) { + return obj_->profit_psi_stem_Sperry(psi_stem); +} +// [[Rcpp::export]] +double Leaf__profit_Sperry_ci(plant::RcppR6::RcppR6 obj_, double ci_) { + return obj_->profit_Sperry_ci(ci_); +} +// [[Rcpp::export]] +double Leaf__profit_psi_stem_TF(plant::RcppR6::RcppR6 obj_, double psi_stem) { + return obj_->profit_psi_stem_TF(psi_stem); +} +// [[Rcpp::export]] +void Leaf__optimise_psi_stem_Sperry(plant::RcppR6::RcppR6 obj_) { + obj_->optimise_psi_stem_Sperry(); +} +// [[Rcpp::export]] +void Leaf__optimise_ci_Sperry(plant::RcppR6::RcppR6 obj_, double max_ci) { + obj_->optimise_ci_Sperry(max_ci); +} +// [[Rcpp::export]] +void Leaf__optimise_psi_stem_TF(plant::RcppR6::RcppR6 obj_) { + obj_->optimise_psi_stem_TF(); +} +// [[Rcpp::export]] +double Leaf__ci___get(plant::RcppR6::RcppR6 obj_) { + return obj_->ci_; +} +// [[Rcpp::export]] +void Leaf__ci___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->ci_ = value; +} + +// [[Rcpp::export]] +double Leaf__stom_cond_CO2___get(plant::RcppR6::RcppR6 obj_) { + return obj_->stom_cond_CO2_; +} +// [[Rcpp::export]] +void Leaf__stom_cond_CO2___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->stom_cond_CO2_ = value; +} + +// [[Rcpp::export]] +double Leaf__assim_colimited___get(plant::RcppR6::RcppR6 obj_) { + return obj_->assim_colimited_; +} +// [[Rcpp::export]] +void Leaf__assim_colimited___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->assim_colimited_ = value; +} + +// [[Rcpp::export]] +double Leaf__transpiration___get(plant::RcppR6::RcppR6 obj_) { + return obj_->transpiration_; +} +// [[Rcpp::export]] +void Leaf__transpiration___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->transpiration_ = value; +} + +// [[Rcpp::export]] +double Leaf__profit___get(plant::RcppR6::RcppR6 obj_) { + return obj_->profit_; +} +// [[Rcpp::export]] +void Leaf__profit___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->profit_ = value; +} + +// [[Rcpp::export]] +double Leaf__psi_stem__get(plant::RcppR6::RcppR6 obj_) { + return obj_->psi_stem; +} +// [[Rcpp::export]] +void Leaf__psi_stem__set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->psi_stem = value; +} + +// [[Rcpp::export]] +double Leaf__lambda___get(plant::RcppR6::RcppR6 obj_) { + return obj_->lambda_; +} +// [[Rcpp::export]] +void Leaf__lambda___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->lambda_ = value; +} + +// [[Rcpp::export]] +double Leaf__lambda_analytical___get(plant::RcppR6::RcppR6 obj_) { + return obj_->lambda_analytical_; +} +// [[Rcpp::export]] +void Leaf__lambda_analytical___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->lambda_analytical_ = value; +} + +// [[Rcpp::export]] +double Leaf__electron_transport___get(plant::RcppR6::RcppR6 obj_) { + return obj_->electron_transport_; +} +// [[Rcpp::export]] +void Leaf__electron_transport___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->electron_transport_ = value; +} + +// [[Rcpp::export]] +double Leaf__gamma___get(plant::RcppR6::RcppR6 obj_) { + return obj_->gamma_; +} +// [[Rcpp::export]] +void Leaf__gamma___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->gamma_ = value; +} + +// [[Rcpp::export]] +double Leaf__ko___get(plant::RcppR6::RcppR6 obj_) { + return obj_->ko_; +} +// [[Rcpp::export]] +void Leaf__ko___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->ko_ = value; +} + +// [[Rcpp::export]] +double Leaf__kc___get(plant::RcppR6::RcppR6 obj_) { + return obj_->kc_; +} +// [[Rcpp::export]] +void Leaf__kc___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->kc_ = value; +} + +// [[Rcpp::export]] +double Leaf__km___get(plant::RcppR6::RcppR6 obj_) { + return obj_->km_; +} +// [[Rcpp::export]] +void Leaf__km___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->km_ = value; +} + +// [[Rcpp::export]] +double Leaf__R_d___get(plant::RcppR6::RcppR6 obj_) { + return obj_->R_d_; +} +// [[Rcpp::export]] +void Leaf__R_d___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->R_d_ = value; +} + +// [[Rcpp::export]] +double Leaf__leaf_specific_conductance_max___get(plant::RcppR6::RcppR6 obj_) { + return obj_->leaf_specific_conductance_max_; +} +// [[Rcpp::export]] +void Leaf__leaf_specific_conductance_max___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->leaf_specific_conductance_max_ = value; +} + +// [[Rcpp::export]] +double Leaf__vcmax___get(plant::RcppR6::RcppR6 obj_) { + return obj_->vcmax_; +} +// [[Rcpp::export]] +void Leaf__vcmax___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->vcmax_ = value; +} + +// [[Rcpp::export]] +double Leaf__jmax___get(plant::RcppR6::RcppR6 obj_) { + return obj_->jmax_; +} +// [[Rcpp::export]] +void Leaf__jmax___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->jmax_ = value; +} + +// [[Rcpp::export]] +double Leaf__rho___get(plant::RcppR6::RcppR6 obj_) { + return obj_->rho_; +} +// [[Rcpp::export]] +void Leaf__rho___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->rho_ = value; +} + +// [[Rcpp::export]] +double Leaf__a_bio___get(plant::RcppR6::RcppR6 obj_) { + return obj_->a_bio_; +} +// [[Rcpp::export]] +void Leaf__a_bio___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->a_bio_ = value; +} + +// [[Rcpp::export]] +double Leaf__PPFD___get(plant::RcppR6::RcppR6 obj_) { + return obj_->PPFD_; +} +// [[Rcpp::export]] +void Leaf__PPFD___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->PPFD_ = value; +} + +// [[Rcpp::export]] +double Leaf__atm_vpd___get(plant::RcppR6::RcppR6 obj_) { + return obj_->atm_vpd_; +} +// [[Rcpp::export]] +void Leaf__atm_vpd___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->atm_vpd_ = value; +} + +// [[Rcpp::export]] +double Leaf__ca___get(plant::RcppR6::RcppR6 obj_) { + return obj_->ca_; +} +// [[Rcpp::export]] +void Leaf__ca___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->ca_ = value; +} + +// [[Rcpp::export]] +double Leaf__psi_soil___get(plant::RcppR6::RcppR6 obj_) { + return obj_->psi_soil_; +} +// [[Rcpp::export]] +void Leaf__psi_soil___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->psi_soil_ = value; +} + +// [[Rcpp::export]] +double Leaf__leaf_temp___get(plant::RcppR6::RcppR6 obj_) { + return obj_->leaf_temp_; +} +// [[Rcpp::export]] +void Leaf__leaf_temp___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->leaf_temp_ = value; +} + +// [[Rcpp::export]] +double Leaf__atm_o2_kpa___get(plant::RcppR6::RcppR6 obj_) { + return obj_->atm_o2_kpa_; +} +// [[Rcpp::export]] +void Leaf__atm_o2_kpa___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->atm_o2_kpa_ = value; +} + +// [[Rcpp::export]] +double Leaf__atm_kpa___get(plant::RcppR6::RcppR6 obj_) { + return obj_->atm_kpa_; +} +// [[Rcpp::export]] +void Leaf__atm_kpa___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->atm_kpa_ = value; +} + +// [[Rcpp::export]] +double Leaf__hydraulic_cost___get(plant::RcppR6::RcppR6 obj_) { + return obj_->hydraulic_cost_; +} +// [[Rcpp::export]] +void Leaf__hydraulic_cost___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->hydraulic_cost_ = value; +} + +// [[Rcpp::export]] +double Leaf__opt_psi_stem___get(plant::RcppR6::RcppR6 obj_) { + return obj_->opt_psi_stem_; +} +// [[Rcpp::export]] +void Leaf__opt_psi_stem___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->opt_psi_stem_ = value; +} + +// [[Rcpp::export]] +double Leaf__opt_ci___get(plant::RcppR6::RcppR6 obj_) { + return obj_->opt_ci_; +} +// [[Rcpp::export]] +void Leaf__opt_ci___set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->opt_ci_ = value; +} + +// [[Rcpp::export]] +double Leaf__count__get(plant::RcppR6::RcppR6 obj_) { + return obj_->count; +} +// [[Rcpp::export]] +void Leaf__count__set(plant::RcppR6::RcppR6 obj_, double value) { + obj_->count = value; +} + + // [[Rcpp::export]] plant::ode::test::Lorenz Lorenz__ctor(double sigma, double R, double b) { return plant::ode::test::Lorenz(sigma, R, b); From eb4b8614de00af9559beb0cd7f9dfc94d517b776 Mon Sep 17 00:00:00 2001 From: Daniel Falster Date: Mon, 1 Jul 2024 17:56:44 +1000 Subject: [PATCH 6/6] Vignette edits and rename --- .../strategy_TF24-Leaf.Rmd} | 171 ++++++++++-------- 1 file changed, 95 insertions(+), 76 deletions(-) rename vignettes/{leaf_submodel_documentation.Rmd => models/strategy_TF24-Leaf.Rmd} (73%) diff --git a/vignettes/leaf_submodel_documentation.Rmd b/vignettes/models/strategy_TF24-Leaf.Rmd similarity index 73% rename from vignettes/leaf_submodel_documentation.Rmd rename to vignettes/models/strategy_TF24-Leaf.Rmd index 8bd92243..f62be2c4 100644 --- a/vignettes/leaf_submodel_documentation.Rmd +++ b/vignettes/models/strategy_TF24-Leaf.Rmd @@ -1,49 +1,42 @@ --- -title: "tf24w_documentation" +title: "TF24 Leaf model - Hydraulics and optimal stomatal behaviour" output: html_document date: "2023-01-10" --- +**authors**: Isaac Towers +**date**: 2024 + ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) -``` - -This is the documentation for the tf24w strategy - -#Introduction - -tf24w is an implementation of the tf24 strategy including water dynamics. This includes an updated strategy object `tf24w`, a physiological stomatal optimisation sub-model which determines how plants assimilate carbon and transpire water dynamically in response to water availability, vapour pressure deficit, leaf temperature, in a trait-dependent manner, and a soil-water submodel which takes rainfall as an input and determines how much soil moisture is available to plants. - -We can compare the two strategy objects to first understand the new traits that have been introduced in `tf24w` -```{r} -devtools::load_all() -library(tidyverse) +library(plant) +library(ggplot2) +library(dplyr) +library(tidyr) +library(purrr) ``` +This is the documentation for the Leaf model within the `TF24` strategy. -```{r} -s <- tf24_Strategy() -sw <- tf24w_Strategy() +# Introduction -names(s) -names(sw) -``` +The TF24 strategy will include water dynamics, built off a physiological stomatal optimisation sub-model which determines how plants assimilate carbon and transpire water dynamically in response to water availability, vapour pressure deficit, leaf temperature, in a trait-dependent manner, and a soil-water submodel which takes rainfall as an input and determines how much soil moisture is available to plants. -There are 9 new traits thus far: +The strategy will enable several new parameters to be considered: --vcmax: the maximum rate carboxylation ($\mu mol~m^{-2}~s^{-1}$) --p_50: The leaf water potential ($\psi_l$) at which 50% of conductivity is lost --K_s: The maximum hydraulic conductivity ($kg~m^{-2}~s^{-1}~MPa^{-1}) --c: Shape parameter for the hydraulic vulnerability curve (unitless) --b: Sensitivity parameter for the hydraulic vulnerability curve (-MPa) --psi_crit: $\psi_l$ at which 95% of conductivity is lost. Maximum water potential. (-MPa) +- `vcmax`: the maximum rate carboxylation ($\mu mol~m^{-2}~s^{-1}$) +- `p_50`: The leaf water potential ($\psi_l$) at which 50% of conductivity is lost +- `K_s`: The maximum hydraulic conductivity ($kg~m^{-2}~s^{-1}~MPa^{-1}) +- `c`: Shape parameter for the hydraulic vulnerability curve (unitless) +- `b`: Sensitivity parameter for the hydraulic vulnerability curve (-MPa) +- `psi_crit`: $\psi_l$ at which 95% of conductivity is lost. Maximum water potential. (-MPa) -For the most part, these traits, in combination with traits from `tf24`, determine how plant assimilate carbon and tranpsire water via the physiological `Leaf` submodel. We can start by exploring the theory behind how the `Leaf` submodel works, found in `leaf_model.cpp`. +For the most part, these traits, in combination with traits from `TF24`, determine how plant assimilate carbon and transpire water via the physiological `Leaf` submodel. We can start by exploring the theory behind how the `Leaf` submodel works, found in `leaf_model.cpp`. -#Profitmax +# Profitmax -Plants are known to vary the aperture of their stomata, which control the rate of conductance of $H_2O$ for $CO_2$, in response to environmental stimuli including the amount of available soil moisture. But how do plants determine the optimum rate of exchange? Multiple theoretical frameworks exist to address this question, but currently `tf24w` employs the `profitmax` model. The profitmax models states that the optimum stomatal conductance is the point at which profits, $P~(\mu mol~m^{-2}~s^{-1})$, is maximimised. +Plants are known to vary the aperture of their stomata, which control the rate of conductance of $H_2O$ for $CO_2$, in response to environmental stimuli including the amount of available soil moisture. But how do plants determine the optimum rate of exchange? Multiple theoretical frameworks exist to address this question, but currently `TF24` employs the `profitmax` model. The profitmax models states that the optimum stomatal conductance is the point at which profits, $P~(\mu mol~m^{-2}~s^{-1})$, is maximised. $P (\mu mol~m^{-2}~s^{-1})$ is the difference between photosynthetic revenue, $A~(\mu mol~m^{-2}~s^{-1})$ and the costs,$C~(\mu mol~m^{-2}~s^{-1})$ required to maintain the transpirational pathway which supplies water for transpiration through the stomates: @@ -55,9 +48,9 @@ $\psi_l~(-MPa)$ is the water potential of the canopy xylem. This can considered For now, lets go through how the cost and revenue are calculated as a function of $\psi_l$. -#Revenue +# Revenue -Revenue is `profitmax` is the photosynthetic assimilate $A~(\mu mol~m^{-2}~s^{-1})$ that can produced at a given level of stomatal conductance before taking away costs associated with transpiration. +Revenue in `profitmax` is the photosynthetic assimilate $A~(\mu mol~m^{-2}~s^{-1})$ that can produced at a given level of stomatal conductance before taking away costs associated with transpiration. $A~(\mu mol~m^{-2}~s^{-1})$ is related to stomatal behaviour via a coupled-stomatal conductance model, which employs Fick's first law to describe the flux of $CO_2$ across a concentration gradients from the atmosphere $C_a~(Pa)$ to the inter-cellular spaces in the leaf $C_i~(Pa)$: @@ -99,20 +92,36 @@ where $K_m~(Pa)$ is the effective Michaelis-Menten constant. $V_{c,max}$, $\Gamm We can view the functional form of $A_c$ and $A_j$ a function of $C_i$ below. -First, we need to initialise a leaf with some traits and some environmental information. We can extract them from the strategy object. Remember, we only need to initalise the leaf object with traits which are related to leaf physiological sub-model, rather than the whole plant as would be required for growing an `Individual` or a `patch`. +First, we need to initialise a leaf with some traits and some environmental information. We can extract them from the strategy object. Remember, we only need to initialise the leaf object with traits which are related to leaf physiological sub-model, rather than the whole plant as would be required for growing an `Individual` or a `patch`. -The `Leaf` function creates a `Leaf` object, which contains most of the internal functions which are used when calculating the photosynthetic assimilation and water use of a unit of leaf area when using `tf24w`. We initialise the `Leaf` object with a set of traits. +The `Leaf` function creates a `Leaf` object, which contains most of the internal functions which are used when calculating the photosynthetic assimilation and water use of a unit of leaf area when using `TF24`. We initialise the `Leaf` object with a set of traits. ```{r} -leaf <- Leaf(vcmax= sw$vcmax_25, b = sw$b, c = sw$c, psi_crit = sw$psi_crit, epsilon_leaf = sw$epsilon_leaf, jmax_25 = sw$jmax_25, hk_s = sw$hk_s, a = sw$a, curv_fact_elec_trans = sw$curv_fact_elec_trans, curv_fact_colim = sw$curv_fact_colim) +sw <- list( + vcmax_25 = 6, # umol m^-2 s^-1 + c = 2.680147, # unitless + b = 3.898245, # -MPa + psi_crit = 5.870283, # -MPa + beta1 = 20000, # hydraulic cost for Bartlett method umol m^-3 s^-1 + beta2 = 1.5, # exponent for effect of hydraulic risk (unitless) + jmax_25 = 157.44, # maximum electron transport rate umol m^-2 s^-1 + hk_s = 4, # maximum hydraulic-dependent sapwood turnover rate yr ^ -1 + a = 0.30, # quantum yield of photosynthetic electron transport (mol mol^-1) + curv_fact_elec_trans = 0.7, # curvature factor for the light response curve (unitless) + curv_fact_colim = 0.99, # curvature factor for the colimited photosythnthesis equatiom + GSS_tol_abs = 1e-3, # ??? + vulnerability_curve_ncontrol = 100, # ???? + ci_abs_tol = 1e-3, # ??? + ci_niter = 1000 +) + +leaf <- Leaf(vcmax= sw$vcmax_25, b = sw$b, c = sw$c, psi_crit = sw$psi_crit, + beta2 = sw$beta2, jmax_25 = sw$jmax_25, hk_s = sw$hk_s, a = sw$a, curv_fact_elec_trans = sw$curv_fact_elec_trans, curv_fact_colim = sw$curv_fact_colim, GSS_tol_abs = sw$GSS_tol_abs, vulnerability_curve_ncontrol = sw$vulnerability_curve_ncontrol, ci_abs_tol = sw$ci_abs_tol, ci_niter = sw$ci_niter) ``` We also need to set a series of variables which describe the environmment and physiology of the plant at a given time using the `set_physiology` function. Whereas the traits set using the `Leaf` function describe a species' strategy and do not vary over time, the variables set in `set_physiology` do vary. This becomes more relevant for when we dynamically running an individual plant or forest. For now, we will set some constants, based on plant height. ```{r} -height = 1 -leaf$K_s = 2 - leaf$set_physiology(PPFD = 1000, psi_soil = 0, leaf_specific_conductance_max = 4.8e-05, atm_vpd = 2, ca = 40, sapwood_volume_per_leaf_area = 1.8e-04, rho = 608, a_bio = 0.0245, leaf_temp = 25, atm_o2_kpa = 21, atm_kpa = 101.3) ``` @@ -150,9 +159,9 @@ tibble(C_i = C_i) %>% The A_net function also includes a carbon deduction associated with dark respiration, so we can add this back on to show correspondence between the A_net curve and A_c/Aj. -#Cost +# Cost -In order for plants to photosynthesise, plants must move from water from the soil to the canopy via the xylem. To do this, the downstream water potential must be lower (i.e. more negative) than the soil. In `profitmax`, the hydraulic cost incurred by plants is associated with the fact that as the xylem water potential increases, the hydraulic conductance $k_{l,max}~(\mu mol~m^{-2}~s^{-1}~MPa^{-1})$ of the xylem pathway declines, which is assumed to be caused by an increased risk of embolism in the xylem. For simplicity, in `tf24w`, we currently represent the xylem pathway as a single element representing the roots, stem and leaves. We acknowledge that in reality these elements would each have seperate hydraulic conductances. The decline in hydraulic conductance with increasing $\psi_l$ follows the hydraulic vulnerability curve: +In order for plants to photosynthesise, plants must move from water from the soil to the canopy via the xylem. To do this, the downstream water potential must be lower (i.e. more negative) than the soil. In `profitmax`, the hydraulic cost incurred by plants is associated with the fact that as the xylem water potential increases, the hydraulic conductance $k_{l,max}~(\mu mol~m^{-2}~s^{-1}~MPa^{-1})$ of the xylem pathway declines, which is assumed to be caused by an increased risk of embolism in the xylem. For simplicity, in `TF24`, we currently represent the xylem pathway as a single element representing the roots, stem and leaves. We acknowledge that in reality these elements would each have separate hydraulic conductance. The decline in hydraulic conductance with increasing $\psi_l$ follows the hydraulic vulnerability curve: \begin{equation} k_l = k_{l,max}e^{-{(\frac{\psi_l}{b})}^c}. @@ -161,9 +170,14 @@ k_l = k_{l,max}e^{-{(\frac{\psi_l}{b})}^c}. We can this demonstrated graphically using the traits from above. ```{r} -tibble(psi_stem = seq(0, 5, length.out = 100)) %>% - mutate(proportion_conductance = map_dbl(psi_stem, leaf$proportion_of_conductivity)) %>% - mutate(conductance = 4.8e-05*proportion_conductance) %>% +data <- + tibble(psi_stem = seq(0, 5, length.out = 100)) %>% + mutate( + proportion_conductance = map_dbl(psi_stem, leaf$proportion_of_conductivity), + conductance = 4.8e-05*proportion_conductance + ) + +data %>% ggplot(aes(x = psi_stem, y = conductance)) + geom_line() + theme_classic() @@ -185,7 +199,7 @@ $k_{l,max}$ is the maximum hydraulic conductance achievable by the plant at $\ps $$k_{l,max} = \frac{K_s\theta}{h\eta_c},$$ \end{equation} -where $\theta~(m^2~sapwood~m^{-2}~leaf~area)$ is the huber value (described in `tf24`), $h$ is the height of the plant and $eta_c~(unitless)[0,1]$ (described in `tf24`) is the average relative position of leaves in the canopy. Input traits required to parameterise these equations beyond those required in `tf24` are therefore: $K_s$, $\theta$ and $c$, with the remaining traits being handled by the `tf24w` hyperparameterisation function. $h$ is the height of the plant, and is therefore resolved dynamically when running `plant` +where $\theta~(m^2~sapwood~m^{-2}~leaf~area)$ is the huber value (described in `TF24`), $h$ is the height of the plant and $eta_c~(unitless)[0,1]$ (described in `TF24`) is the average relative position of leaves in the canopy. Input traits required to parameterise these equations beyond those required in `TF24` are therefore: $K_s$, $\theta$ and $c$, with the remaining traits being handled by the `TF24` hyperparameterisation function. $h$ is the height of the plant, and is therefore resolved dynamically when running `plant` The total volume of water transpiring through a given unit area of leaf is given by the following equation: @@ -196,15 +210,13 @@ $$E_{supply} = \int^{\psi_l}_{\psi_s}k_l(\psi)\delta\psi $$ Again, visualising this below, the water supplied for transpiration is equivalent to the area under the curve between the soil water potential ($\psi_s~(-MPa)$) and the xylem water potential ($\psi_l~(-MPa)$). ```{r} -tibble(psi_stem = seq(0, 5, length.out = 100)) %>% - mutate(proportion_conductance = map_dbl(psi_stem, leaf$proportion_of_conductivity)) %>% - mutate(conductance = 4.8e-05*proportion_conductance) %>% +data %>% ggplot(aes(x = psi_stem, y = conductance)) + geom_line() + theme_classic() + geom_area(aes(ifelse(psi_stem > 2 | psi_stem < 1, NA, psi_stem), conductance), fill = "red", alpha= 0.5) + - geom_vline(xintercept = 2, col = "red", size = 2, linetype = "dashed") + - geom_vline(xintercept = 1, col = "red", size = 2, linetype = "dashed") + + geom_vline(xintercept = 2, col = "red", linewidth = 2, linetype = "dashed") + + geom_vline(xintercept = 1, col = "red", linewidth = 2, linetype = "dashed") + annotate("text", x = 1.2, y = 4.8e-05, label = expression(psi[s]), col = "red") + annotate("text", x = 2.2, y = 4.8e-05, label = expression(psi[l]), col = "red") ``` @@ -212,7 +224,7 @@ tibble(psi_stem = seq(0, 5, length.out = 100)) %>% Or, put another way, for a given $\psi_s$, this is the $E_{supply}$ that could be achieved as $psi_l$ becomes more negative. It can be seen that $E_{supply}$ slowly tapers off as $psi_s$ increases, owing to the shape of the hydraulic vulnerability curve. This is important as it implies declining marginal returns to transpired water as $psi_stem$ becomes increasingly negative. ```{r} -tibble(psi_stem = seq(1, 5, length.out = 100)) %>% +data %>% mutate(E_supply = map_dbl(psi_stem, leaf$transpiration_full_integration)) %>% ggplot(aes(x = psi_stem, y = E_supply)) + geom_line() + @@ -238,52 +250,62 @@ Here, $z~(m^3~sapwood~m^{-2}~leaf~area}$ is the sapwood volume per leaf area, $b $z$ is calculated based on the size of the tree and $theta$, representing the total amount of sapwood supplying transpiration: $$z = \frac{\theta*h}{\eta_c}$$ -#Profit + +# Profit The relative forms of the $R$ and $H$ curves in relation to $\psi_l$ means that a single $psi_l$ which maximises profit emerges. Let's demonstrate this below, graphically. ```{r} -tibble(psi_stem = seq(1, 4, length.out = 100)) %>% - mutate(R = map_dbl(psi_stem, ~{ - leaf$set_leaf_states_rates_from_psi_stem_analytical(.x) - leaf$assim_colimited_} - )) %>% - mutate(C = map_dbl(psi_stem, ~leaf$hydraulic_cost_TF(.x)))-> data +f <- function(psi_stem) { + leaf$set_leaf_states_rates_from_psi_stem(psi_stem) + R = leaf$assim_colimited_ + H = leaf$hydraulic_cost_TF(psi_stem) + P = R-H + tibble(R, H, P) +} + +data <- + tibble(psi_stem = seq(1, 4, length.out = 100)) %>% + mutate(outcomes = map(psi_stem, f)) %>% + unnest(outcomes) + data %>% - mutate(P = R-C) %>% - pivot_longer(cols = c(P, R,C)) %>% + pivot_longer(cols = c(P, R, H)) %>% ggplot(aes(x = psi_stem, y = value)) + geom_line(aes(colour = name, group = name)) + theme_classic() + geom_vline(xintercept = 2.05, linetype = "dashed") ``` -That's a pretty complicated way to do it though. We can just automatically calculated these values using a given profit funciton. For example, the in-built profit funciton in `tf24w` is the `profit_psi_stem_TF`. +That's a pretty complicated way to do it though. We can just automatically calculated these values using a given profit funciton. For example, the in-built profit funciton in `TF24` is the `profit_psi_stem_TF`. ```{r} -tibble(psi_stem = seq(1, 4, length.out = 100)) %>% - mutate(outcomes = map(.x = psi_stem, ~{ - leaf$profit_psi_stem_TF(.x) - return(tibble(H = leaf$hydraulic_cost_, R = leaf$assim_colimited_, P = R-H, )) - }))-> data +f <- function(psi_stem){ + leaf$profit_psi_stem_TF(psi_stem) + tibble(H = leaf$hydraulic_cost_, R = leaf$assim_colimited_, P = R-H) + } -data %>% - unnest(outcomes) %>% +data <- + tibble(psi_stem = seq(1, 4, length.out = 100)) %>% + mutate(outcomes = map(psi_stem, f))%>% + unnest(outcomes) + +data %>% pivot_longer(cols = c(H,R,P)) %>% ggplot(aes(x = psi_stem, y = value)) + geom_line(aes(colour = name, group = name)) + theme_classic() ``` -#Optimising profit +# Optimising profit Recall that the goal of the leaf physiology sub-model is to calculate the $CO_2$ assimilation and water use of a given unit of leaf area given the presiding environmental conditions and plant state. In order to do this, then, a numerical method is required to find the $\psi_l$ which maximises $P$. This also allows $E$ to be calculated, which is used in the soil hydrology sub-model (discussed elsewhere). -The preferred method for numerical optimisation at the time of writing for `tf24` is the Golden Section Search algorthim. This algorithm finds local maxima or minima by successively narrowing the position of two initial boundary values until the distance of movement is below a defined tolerance values. As above, the x-values of the method is $\psi_l$, and the two initial boundary values in this case are $\psi_s$ and $psi_{crit}$; $psi_l$ cannot be less negative than $psi_s$ and is assumed to not surpass $psi_crit$. +The preferred method for numerical optimisation at the time of writing for `TF24` is the Golden Section Search algorthim. This algorithm finds local maxima or minima by successively narrowing the position of two initial boundary values until the distance of movement is below a defined tolerance values. As above, the x-values of the method is $\psi_l$, and the two initial boundary values in this case are $\psi_s$ and $psi_{crit}$; $psi_l$ cannot be less negative than $psi_s$ and is assumed to not surpass $psi_crit$. -A manual demonstration is shown below, and then the method implemented in `tf24w` +A manual demonstration is shown below, and then the method implemented in `TF24` ```{r} #golden ratio @@ -322,12 +344,12 @@ while (abs(bound_b - bound_a) > delta_crit) { } - opt_psi_stem = ((bound_b + bound_a) / 2); - profit = leaf$optimise_psi_stem_TF(); - transpiration = leaf$transpiration_ +(opt_psi_stem = ((bound_b + bound_a) / 2)) +(profit = leaf$profit_psi_stem_TF(opt_psi_stem)) +(transpiration = leaf$transpiration_) ``` -`tf24w` implementation. +Now compare these numbers to the `TF24` implementation, (they should be the same): ```{r} leaf$optimise_psi_stem_TF() @@ -335,6 +357,3 @@ leaf$profit_ leaf$transpiration_ ``` -ion_ -``` -