-
Notifications
You must be signed in to change notification settings - Fork 16
/
calc_optimal_vcmax.R
267 lines (230 loc) · 9.86 KB
/
calc_optimal_vcmax.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# calculate optimal vcmax as in Smith et al. Photosynthetic capacity is optimized to the
# environment. Ecology Letters.
########################
## variable key
########################
# pathway: photosynthetic pathway, either "c3" or "c4"
# tg_c: acclimated temperature (degC)
# z: elevation (m)
# vpdo: vapor pressure deficit at sea level (kPa)
# cao: atmospheric CO2 at sea level (umol mol-1)
# oao: atmospheric O2 at sea level (ppm)
# paro: photosynthetically active radiation at sea level (µmol m-2 s-1)
# q0_resp: yes or no, use the q0 response curve calculation
# q0_int: intercept for the q0 response curve calculation
# q0: quantum efficiency of photosynthetic electron transport (mol/mol)
# theta: curvature of the light response of electron transport (unitless)
# given_chi: yes or no based on if chi is known (yes) or calculated (no)
# chi: leaf intercellular to atmospheric CO2 ratio (ci/ca) (unitless)
# f: fraction of year in growing season
# lma: leaf mass area (g m-2)
# given_lma: yes or no based on if lma is known (yes) or calculated (no)
# R: universal gas constant (J mol-1 K-1)
# patm: atmospheric pressure (Pa)
# ca: atmospheric CO2 at z (Pa)
# km: Michaelis-Menten constant for Rubisco (Pa)
# gammastar: CO2 compensation point (Pa)
# vpd: vapor pressure deficit at z (kPa)
# par: photosynthetically active radiation at z (µmol m-2 s-1)
# ci: leaf intercellular CO2 concentation (Pa)
# m: CO2 limiation of electron transport rate limited photosynthesis (Pa)
# mc: CO2 limiation of Rubisco carboxylation rate limited photosynthesis (Pa)
# c: constant describing cost of maintaining electron transport (unitless)
# omega: omega term from Smith et al.
# omega_star: omega_star term from Smith et al.
# vcmax_star: maximum rate of Rubisco carboxylation without temperature correction (µmol m-2 s-1)
# vcmax_prime: optimal maximum rate of Rubisco carboxylation at tg (µmol m-2 s-1)
# jvrat: ratio of the maximum rate of electron transport to the maximum rate of Rubisco carbocylation at tg (unitless)
# jmax_prime: optimal maximum rate of electron transport at tg (µmol m-2 s-1)
# vcmax25: optimal maximum rate of Rubisco carboxylation at a temperature of 25 C (µmol m-2 s-1)
# vpmax25: ...at a temperature of 25 C (µmol m-2 s-1)
# jmax25: optimal maximum rate of electron transport at a temperature of 25 C (µmol m-2 s-1)
# grossphoto: gross photosynthesis
# resp: respiration
# netphoto: net photosynthesis
# nrubisco: leaf N in rubisco
# nbioe: leaf N in bioenergetics
# npep: leaf N in rubisco from predicted vpmax with PEP-specific constants
# nstructure: nitrogen in structural tissue from lma
# nall: all leaf N predictions
# nphoto: leaf N used for photosynthesis
# nrubisco_frac: fraction of leaf N in rubisco out of all leaf N
# nphoto_frac: fraction of leaf N for photosynthesis out of all leaf N
# All equation numbers refer to equations presented in Smith et al., 2019
# libraries
# install.packages('R.utils')
library(R.utils)
# load necessary functions
sourceDirectory('functions', modifiedOnly = FALSE)
calc_optimal_vcmax <- function(pathway = "C3", tg_c = 25, z = 0, vpdo = 1, cao = 400, oao = 209460,
paro = 800, beta = 146, theta = 0.85, chi = NA, q0 = 0.257, q0_resp = "yes",
q0_int = -0.0805, lma = NA, f = 0.5){
# constants
R <- 8.314
c <- 0.05336251
leakiness <- 0.01
# environmental terms
patm <- calc_patm(z)
par <- calc_par(paro, z)
vpd <- calc_vpd(tg_c, z, vpdo)
ca <- cao * 1e-6 * patm
oa <- oao * 1e-6 * patm
# K and Gamma* model terms
km <- calc_km_pa(tg_c, z)
if(pathway == "C3"){
# C3
gammastar <- calc_gammastar_pa(tg_c, z)
# Coordination and least-cost hypothesis model terms
given_chi <- given_chi(chi) # returns yes or no based on presence of chi value
# calculate chi if unknown
chi <- return_chi(given_chi = given_chi, chi = chi, temp = tg_c, z = z, vpdo = vpdo, cao = cao, beta = beta)
ci <- chi * ca # Pa
mc <- ((ci - gammastar) / (ci + km))
m <- ((ci - gammastar)/(ci + (2 * gammastar)))
omega <- calc_omega(theta = theta, c = c, m = m)
omega_star <- (1 + (omega) - sqrt((1 + (omega))^2 - (4 * theta * omega)))
# calculate q0
if(q0_resp == "yes"){
# Bernacchi et al. (2003) temperature response (set to 0.257 at 25C)
q0 = q0_int + (0.022 * tg_c) - (0.00034 * tg_c * tg_c)
}else{
q0
}
# calculate vcmax and jmax
vcmax <- ((q0 * par * m) / mc) * (omega_star / (8 * theta))
jvrat <- ((8 * theta * mc * omega) / (m * omega_star))
jmax <- jvrat * vcmax
vpmax <- 0
vpmax25 <- 0
leakage <- NA
chi_bs <- NA
kp <- NA
kr <- NA
ko <- NA
cbs <- NA
chi_bs <- NA
obs <- NA
Al <- q0 * par * m * omega_star / (8 * theta)
Ap <- 0
Ac <- vcmax * mc
}else{
# C4
gammastar <- calc_gammastar_pa_c4(tg_c, z)
# Coordination and least-cost hypothesis model terms
given_chi <- given_chi(chi) # returns yes or no based on presence of chi value
# calculate chi if unknown
chi <- return_chi_c4(given_chi = given_chi, chi = chi, ca = ca, temp = tg_c, vpd = vpdo, z = z, beta = beta)
ci <- ca * chi
cm <- ci
oi <- oa * chi
m <- (ci - gammastar) / (ci + 2 * gammastar)
omega <- calc_omega(theta = theta, c = 0.01, m = m) # Eq. S4
omega_star <- (1 + (omega) - sqrt((1 + (omega))^2 - (4 * theta * omega))) # Eq. 18
# calculate q0
if(q0_resp == "yes"){
# Bernacchi et al. (2003) temperature response (set to 0.257 at 25C)
q0 = q0_int + (0.022 * tg_c) - (0.00034 * tg_c * tg_c)
}else{
q0
}
Al <- q0 * par * m * omega_star / (8 * theta) # Eqn. 2.2
jmax <- q0 * par * omega
# calc kp, kr, and ko
kp <- calc_kp_temp_pa(tg_c, z) # Eqn. 2.43
kr <- calc_kc_temp_pa(tg_c, z) # Eqn. 2.48
ko <- calc_ko_temp_pa(tg_c, z)
# calc vpmax
vpmax <- ((kp + cm)/cm) * (q0 * par * m * omega_star / (8 * theta)) # Eqn. 2.42
Ap <- vpmax * (cm / (cm + kp))
# calc cbs
leakage <- leakiness * Al
cbs <- calc_cbs(cm, leakage) # Eqn. 2.41
chi_bs <- cbs / ca
# calc obs
obs <- oi
# calc vcmax
vcmax <- (q0 * par * m * omega_star / (8 * theta)) * ((cbs + kr * (1 + obs/ko)) / (cbs - gammastar)) # Eqn. 2.47
mc <- ((cbs + kr * (1 + obs/ko)) / (cbs - gammastar))
Ac <- vcmax * ((cbs - gammastar) / (kr * (1 + obs/ko) + cbs)) # Eqn. 2.4
# calculate vpmax at temperature = 25 C
vpmax25 <- vpmax / calc_tresp_mult(tg_c, tg_c, 25) # using vcmax parameters - find better solution
}
# calculate vcmax and jmax at temperature = 25 C
vcmax25 <- vcmax / calc_tresp_mult(tg_c, tg_c, 25)
jmax25 <- jmax / calc_jmax_tresp_mult(tg_c, tg_c, 25)
# LMA
given_lma <- ifelse(!is.na(lma), "yes", "no") # returns yes or no based on presence of LMA value
# calculate LMA if unknown
lma <- return_lma(given_lma, lma, f = f, par = paro, temperature = tg_c, vpd_kpa = vpdo, z = z, co2 = cao)
# calculate leaf N in rubisco from predicted vcmax
nrubisco <- fvcmax25_nrubisco(vcmax25)
# calculate leaf N in bioenergetics from predicted jmax
nbioe <- fjmax25_nbioe(jmax25)
# calculate leaf N in rubisco from predicted vpmax with PEP-specific constants
npep <- fvpmax25_npep(vpmax25)
# calculate nitrogen in structural tissue from lma
nstructure <- flma_nstructure(lma)
# sum all leaf N predictions
nall <- nrubisco + nbioe + nstructure + npep
# calculate leaf N used for photosynthesis
nphoto <- nrubisco + nbioe + npep
# calculate the fraction of leaf N in rubisco out of all leaf N
nrubisco_frac <- nrubisco / nall
# calculate the fraction of leaf N for photosynthesis out of all leaf N
nphoto_frac <- nphoto / nall
# output
results <- data.frame("pathway" = pathway,
"tg_c" = tg_c,
"z" = z,
"vpdo" = vpdo,
"cao" = cao,
"oao" = oao,
"paro" = paro,
"q0_response" = q0_resp,
"q0_intercept" = q0_int,
"q0" = q0,
"beta" = beta,
"theta" = theta,
"lma" = lma,
"given_lma" = given_lma,
"f" = f,
"patm" = patm,
"par" = par,
"vpd" = vpd,
"ca" = ca,
"oa" = oa,
"km" = km,
"gammastar" = gammastar,
"chi" = chi,
"given_chi" = given_chi,
"ci" = ci,
"mc" = mc,
"m" = m,
"omega" = omega,
"omega_star" = omega_star,
"Al" = Al,
"kp" = kp,
"kr" = kr,
"ko" = ko,
"Ap" = Ap,
"leakage" = leakage,
"cbs" = cbs,
"chi_bs" = chi_bs,
"obs" = obs,
"Ac" = Ac,
"jmax" = jmax,
"vpmax" = vpmax,
"vcmax" = vcmax,
"jmax25" = jmax25,
"vpmax25" = vpmax25,
"vcmax25" = vcmax25,
"nrubisco" = nrubisco,
"nbioe" = nbioe,
"npep" = npep,
"nstructure" = nstructure,
"nall" = nall,
"nphoto" = nphoto,
"nrubisco_frac" = nrubisco_frac,
"nphoto_frac" = nphoto_frac)
return(results)
}