#-------------------------------------------------------------------------------
# Copyright (c) 2012 University of Illinois and Authors.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the
# University of Illinois/NCSA Open Source License
# which accompanies this distribution, and is available at
# http://opensource.ncsa.illinois.edu/license.html
#
# Citation: Kristina J. Teixeira and Evan H. Delucia 2011. The greenhouse gas value of ecosystems. Global Change Biology. 17(1):425–438 doi: 10.1111/j.1365-2486.2010.02220.x
#-------------------------------------------------------------------------------
#--------------------------------------------------------------------------------------------------#
##' Greenhouse Gas Value Calculator
##'
##' R function implementation of GHGV_calculator_web.m
##' @title GHGVC
##' @param options
##' @param ecosystem_data
##' @export
##' @return GHGVC result
##' @author Chris Schauer, David LeBauer
ghgvc <- function(options, ecosystem_data){
options <- lapply(options, get.nums)
includeANTH <- 1
includeS <- as.logical(options[['storage']])
includeF <- as.logical(options[['flux']])
includeD <- as.logical(options[['disturbance']])
if (as.logical(options[['co2']]) && as.logical(options[['ch4']]) && as.logical(options[['n2o']])) {
gf <- 1
gl <- 3
} else {
if (as.logical(options[['co2']]))
gf <- 1
else if (as.logical(options[['ch4']]))
gf <- 2
else
gf <- 3
gl <- gf
}
A <- 1.78e8
ax <- c(1.4*10^-5*10^9, 3.7*10^-4*10^9*4/3, 3.03*10^-3*10^9) #radiative efficiency of GHGs (nW/m2/ppb; IPCC 2007)
#see p_x function for description of decay kinetics (currently from IPCC 2007)
nruns <- length(grep("pft", names(ecosystem_data)))
p_matrix = matrix(0, 52, nruns)
s_names <- vector('list', nruns)
T_A <- as.numeric(options[['T_A']])
T_E <- as.numeric(options[['T_E']])
annual_discount_rate <- as.numeric(options[['r']])
GHGV_matrix = NaN * matrix(1, T_A, nruns)
GHGV_C_matrix = NaN * matrix(1, T_A, nruns)
swRFV_matrix = NaN * matrix(1, T_A, nruns)
swRFV_C_matrix = NaN * matrix(1, T_A, nruns)
RFV_matrix = NaN * matrix(1, T_A, nruns)
RFV_C_matrix = NaN * matrix(1, T_A, nruns)
GHGmatrix = NaN * matrix(1, 16, nruns)
jsonResults = matrix("", 1, nruns)
for (i in 1:nruns) {
ecosystem <- lapply(ecosystem_data[[i]], get.nums)
t_E <- seq(0, T_E, len=T_E+1)
t_A <- seq(1, T_A, len=T_A)
#Biophysical
sw_radiative_forcing <- ecosystem[['sw_radiative_forcing']]
latent_cooling <- ecosystem[['latent']]
sensible_heat <- ecosystem[['sensible']]
biophysical_net <- latent_cooling + sensible_heat
#STORAGE
aboveground_storage <- ecosystem[['OM_ag']]
root_storage <- ecosystem[['OM_root']]
wood_storage <- ecosystem[['OM_wood']]
litter_storage <- ecosystem[['OM_litter']]
peat_storage <- ecosystem[['OM_peat']]
S_SOM <- ecosystem[['OM_SOM']]
S_p <- c(aboveground_storage + wood_storage + litter_storage, root_storage, peat_storage, S_SOM)
#BURN CHARACTERISTICS
fc <- c(ecosystem[['fc_ag_wood_litter']], ecosystem[['fc_root']], ecosystem[['fc_peat']], ecosystem[['fc_SOM']])
#print(fc)
Ec <- c(ecosystem[['Ec_CO2']], ecosystem[['Ec_CH4']], ecosystem[['Ec_N2O']]) #proportional release of GHG
#DECOMPOSITION
k <- c(ecosystem[['k_ag_wood_litter']], ecosystem[['k_root']], ecosystem[['k_peat']], ecosystem[['k_SOM']])
t_peat <- 0*t_E+1
if (T_E > 50) {
t_peat[51:T_E] <- 0
}
fdecay <- matrix(c(exp(-k[1]*t_E)-exp(-k[1]*(t_E+1)), exp(-k[2]*t_E)-exp(-k[2]*(t_E+1)), k[3]*t_peat, exp(-k[4]*t_E)-exp(-k[4]*(t_E+1))), nrow=4, byrow=TRUE)
if (peat_storage > 0) {
fdecay[4,] <- (exp(-k[4]*(t_E-50))-exp(-k[4]*(t_E-50+1)))*(t_peat-1)*-1
#print(fdecay[4,])
}
termite <- ecosystem[['termite']] / 100
Ed_CO2 <- c(ecosystem[['Ed_CO2_ag_wood_litter']], ecosystem[['Ed_CO2_root']], ecosystem[['Ed_CO2_peat']], ecosystem[['Ed_CO2_litter']])
Ed_CH4 <- c(ecosystem[['Ed_CH4_ag_wood_litter']], ecosystem[['Ed_CH4_root']], ecosystem[['Ed_CH4_peat']], ecosystem[['Ed_CH4_litter']])
Ed_N2O <- c(ecosystem[['Ed_N2O_ag_wood_litter']], ecosystem[['Ed_N2O_root']], ecosystem[['Ed_N2O_peat']], ecosystem[['Ed_N2O_litter']])
Ed <- matrix(c(Ed_CO2, Ed_CH4, Ed_N2O), nrow=4)
#print(Ed)
#FLUX
if (includeANTH == 0)
F <- c(ecosystem[['F_CO2']] + ecosystem[['F_anth']], ecosystem[['F_CH4']], ecosystem[['F_N2O']])
else if (includeANTH == 1)
F <- c(ecosystem[['F_CO2']] + ecosystem[['F_anth']], ecosystem[['F_CH4']], ecosystem[['F_N2O']])
#DISTURBANCE
rD <- ecosystem[['rd']]
tR <- ecosystem[['tR']]
FR <- c(ecosystem[['FR_CO2']], ecosystem[['FR_CH4']], ecosystem[['FR_N2O']])
#Disturbance biomass pools:
S_pD <- c(aboveground_storage + wood_storage + litter_storage, root_storage, peat_storage)
fcD <- c(ecosystem[['dfc_ag_wood_litter']], ecosystem[['dfc_root']], ecosystem[['dfc_peat']])
kD <- c(ecosystem[['dk_ag_wood_litter']], ecosystem[['dk_root']], ecosystem[['dk_peat']])
fdecayD <- matrix(c(exp(-kD[1]*t_E) - exp(-kD[1]*(t_E+1)), exp(-kD[2]*t_E) - exp(-kD[2]*(t_E+1)), exp(-kD[3]*t_E) - exp(-kD[3]*(t_E+1))),nrow=3,byrow=TRUE)
#Transition from Aggrading to 'Mature':
age_transition <- ecosystem[['age_transition']]
F_new <- c(ecosystem[['new_F_CO2']], ecosystem[['new_F_CH4']], ecosystem[['new_F_N2O']])
#CALCULATE GHGV
Sx <- NaN * matrix(1, T_E + 1, 3)
Fx <- NaN * matrix(1, T_E + 1, 3)
Dx <- NaN * matrix(1, T_E + 1, 3)
SDx <- NaN * matrix(1, T_E + 1, 3)
FDx <- NaN * matrix(1, T_E + 1, 3)
Ix <- NaN * matrix(1, T_E + 1, 3)
Cx <- NaN * matrix(1, T_A, 3)
RFx <- matrix(0, T_A, 3)
RFsw <- NaN * matrix(1, T_A, 1)
p_x = t(matrix(c(.217+.259*exp(-t_A / 172.9)+.338*exp(-t_A / 18.51)+.186*exp(-t_A / 1.186), exp(-t_A / 12), exp(-t_A / 114)),nrow=3,byrow=TRUE))
for (nm in 1:4) {
for (g in gf:gl) {
#calculate S_x (eq. 5)
Sx[1,g] <- sum(S_p * fc * Ec[g])
Sx[2:(T_E+1),g] <- t((S_p * (1 - fc)) * Ed[,g]) %*% fdecay[,1:T_E]
#calculate F_x
Fx[,g] <- F[g]
Fx[1,g] <- 0
if (age_transition + 1 < T_E && age_transition > 0) {
Fx[(age_transition + 2):(T_E + 1),g] <- F_new[g]
}
#calculate D_x
tempA <- matrix(0, 1, T_E+1)
for (j in 1:T_E+1) {
FDx[j,g] <- min(j,tR) * (FR[g] - Fx[j,g])
for (jk in 1:j) {
if (jk == j)
tempA[jk] <- sum(S_pD * fcD * Ec[g])
else if (jk < j)
tempA[jk] <- t((S_pD * (1-fcD)) * Ec[g]) %*% fdecayD[,jk]
}
SDx[j,g] <- sum(tempA)
}
Dx[,g] <- rD * (SDx[,g] + FDx[,g])
Dx[1,g] <- 0
#calculate I_x (eq. 4)
if (nm == 1)
Ix[1:(T_E+1),g] <- Sx[,g] * includeS-Fx[,g] * includeF - Dx[,g] * includeD
else if (nm == 2)
Ix[1:(T_E+1),g] <- Sx[,g] * includeS
else if (nm == 3)
Ix[1:(T_E+1),g] <- -Fx[,g] * includeF
else if (nm == 4)
Ix[1:(T_E+1),g] <- -Dx[,g] * includeD
w = matrix(0, T_A, 1)
temp = matrix(0, 1, T_A)
for (j in 1:T_A) {
for (k in 1:min(T_E+1, t_A[j])) {
if (j - k == 0)
temp[k] <- Ix[k,g] / A
else
temp[k] <- Ix[k,g] / A * p_x[(j-k),g]
}
Cx[j,g] <- sum(temp)
w[j] <- 1 / (1 + annual_discount_rate)^j
}
RFx[,g] <- ax[g] * Cx[,g]
}
RFsw[1:T_E] <- biophysical_net
#calculate full radiative forcing & apply weighting
RF_GHG <- rowSums(RFx) * w
RF_SW <- rowSums(RFsw) * w
RF <- RF_GHG + RF_SW
#calculate radiative frocing from C pulse for comparison
I_Cpulse <- 1000 * 1/44 #1 Mg CO2 pulse at time 0--> units of kmol
C_Cpulse <- NaN*Cx[,1]
C_Cpulse[1] <- I_Cpulse / A
C_Cpulse[2:T_A] <- I_Cpulse / A * p_x[1:T_A-1]
RF_Cpulse <- (C_Cpulse * ax[1]) * w
#calculate GHGV--for inclusion of all components (nm=1)
if (nm == 1) {
GHGV <- NaN * RF_GHG
swRFV <- NaN * RF_SW
cRF_Cpulse <- NaN * RF_Cpulse
for (j in 1:T_A) {
GHGV[j] <- sum(RF_GHG[1:j,])
swRFV[j] <- sum(RF_SW[1:j,])
cRF_Cpulse[j] <- sum(RF_Cpulse[1:j])
}
RFV <- GHGV + swRFV
GHGV_C <- GHGV / cRF_Cpulse
swRFV_C <- swRFV / cRF_Cpulse
RFV_C <- RFV / cRF_Cpulse
GHGV_matrix[1:T_A,i] <- GHGV
GHGV_C_matrix[1:T_A,i] <- GHGV_C
swRFV_matrix[1:T_A,i] <- swRFV
swRFV_C_matrix[1:T_A,i] <- swRFV_C
RFV_matrix[1:T_A,i] <- RFV
RFV_C_matrix[1:T_A,i] <- RFV_C
}
#separate reporting for each GHG
RFx_w <- NaN * RFx
GHGVx <- NaN * RFx
GHGVx_C <- NaN * RFx
for (kk in 1:3) {
RFx_w[1:T_A,kk] <- (RFx[,kk] * t(w))
for (j in 1:T_A) {
GHGVx[j,kk] <- sum(RFx_w[1:j,kk])
}
GHGVx_C[,kk] <- t((GHGVx[,kk] / cRF_Cpulse))
}
if (nm == 1) {
GHGmatrix[13:15, i] <- GHGVx_C[T_A,]
GHGmatrix[16, i] <- sum(GHGmatrix[13:15,i])
}
else if (nm == 2) {
GHGmatrix[1:3, i] <- GHGVx_C[T_A,]
GHGmatrix[4, i] <- sum(GHGmatrix[1:3,i])
}
else if (nm == 3) {
GHGmatrix[5:7, i] <- GHGVx_C[T_A,]
GHGmatrix[8, i] <- sum(GHGmatrix[5:7,i])
}
else if (nm == 4) {
GHGmatrix[9:11, i] <- GHGVx_C[T_A,]
GHGmatrix[12, i] <- sum(GHGmatrix[9:11,i])
}
}
# determine the scale between the input and output value for sw radiative forcing
swRFV_scale_factor = swRFV_C_matrix[T_E,i] / sw_radiative_forcing
# scale latent proportional to above
instance_output_latent = swRFV_scale_factor * latent_cooling
storage_group = ( GHGmatrix[1,i] + GHGmatrix[2,i] + GHGmatrix[3,i] )
flux_group = ( GHGmatrix[5,i] + GHGmatrix[6,i] + GHGmatrix[7,i] )
# CRV= (S_CO2+S_CH4+S_N2O) + (F_CO2+F_CH4+F_N2O)-swRFV+latent
climate_regulating_value = storage_group + flux_group - swRFV_C_matrix[T_E,i] + instance_output_latent
listResult <- list( name = ecosystem[['name']],
S_CO2 = GHGmatrix[1,i], S_CH4 = GHGmatrix[2,i], S_N2O = GHGmatrix[3,i],
F_CO2 = GHGmatrix[5,i], F_CH4 = GHGmatrix[6,i], F_N2O = GHGmatrix[7,i],
D_CO2 = (GHGmatrix[1,i] + GHGmatrix[5,i]), D_CH4 = (GHGmatrix[2,i]+GHGmatrix[6,i]), D_N2O = (GHGmatrix[3,i] = GHGmatrix[7,i]),
swRFV = swRFV_C_matrix[T_E,i], latent = instance_output_latent, crv = climate_regulating_value )
jsonResults[i] <- toJSON(listResult)
}
jsonResult = "["
for (i in 1:length(jsonResults)) {
jsonResult <- paste(jsonResult,jsonResults[i],sep="")
if (i < length(jsonResults))
jsonResult <- paste(jsonResult,",",sep="")
}
jsonResult <- paste(jsonResult,"]",sep="")
print(jsonResult)
return(jsonResult)
}
##' Greenhouse Gas Value Calculator v2
##'
##' R function implementation of GHGV_calculator_web.m; works for n ecosystems
##' @title GHGVC2
##' @param config.list
##' @export
##' @return GHGVC2 result
##' @author David LeBauer
ghgvc2 <- function(config.list){
options <- config.list$options
ecosystems <- names(config.list)[-which(names(config.list)%in% "options")]
out <- list()
for (ecosystem in ecosystems){
out[[ecosystem]] <- fromJSON(ghgvc(options, config.list[[ecosystem]]))
}
return(toJSON(out))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.