-
Notifications
You must be signed in to change notification settings - Fork 2
/
RIAcarbonGlobalEnvResL_Appendix1.Rmd
250 lines (184 loc) · 24.1 KB
/
RIAcarbonGlobalEnvResL_Appendix1.Rmd
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
---
title: "Appendix 1"
output: pdf_document
---
# Overview
Our study links three existing simulation models to explore their capacity to support forest carbon (C) management decisions using the current metrics of sustainable forest management practices (levels of m^3^/ha). Here, we describe the scripts used in our simulations. These scripts are R-based and are repeatable and transparent. The central model of our simulations is the Carbon Budget Model of the Canadian Forest Sector (CBM - Kurz et al., 2009). We implemented faithfully the logic, pools structure, equations, and default assumptions of the CBM into the meta R-package, `SpaDES` (Spatial Discrete Event Simulation - McIntire et al., 2019). This resulted in a spatialized version of the CBM used in simulations in conjunction with landscape modifications from a harvesting scheduler ws3 (Appendix 2) and a fire model (Appendix 3). The yearly processing of the entire landscape permits the link to our harvesting scheduling and fire model, which are also in `SpaDES`, via yearly landscape modifications.
Linking these three models permits the assessment of carbon implication of harvesting and fire disturbances on our study area (see Figure 1). All scripts are R-based, providing a parameter and data handling platform, and a clear understanding of the model structure and parameters to any moderately R-proficient scientist.
The four modules or `SpaDES`-deck can be called by a global script (available below). In this project, four modules are run: `CBM_defaults`, `CBM_dataPrep_RIA_scenario`, `CBM_vol2biomass_RIA`, and `CBM_core`. The code environment is on a public repository. The interactions with other models in our simulations are all via the `CBM_dataPrep_scenario` modules. We simulate four scenarios and therefore have four `CBM_dataPrep_scenario` modules described in this appendix.
# Background
This adaptation of the CBM was developed as a R&D tool for improving the science-basis for the CBM and applied carbon modelling in general. This `SpaDES`-deck was developed on the `SpaDES` platform (a package in R; <https://cran.r-project.org/package=SpaDES>) to make it transparent, spatial explicit, and able to link to other modules/models in `SpaDES`, striving towards a PERFICT approach. This `SpaDES`-deck enables the inclusion of carbon modelling with CBM in cumulative effects evaluation, and provides an environment in which science improvements can be explored and tested. `SpaDES` functions as a scheduler through space and time. Note that modules or models do not have to be written in R, but callable from R. More information on `SpaDES` and other openly available `SpaDES` modules can be found here <http://spades.predictiveecology.org/>.
# Four-module `SpaDES`-deck
By definition, a `SpaDES` environment is spatially explicit. In addition to that modification, this `SpaDES`-deck differs slightly from the CBM: the C transactions are calculated via matrix multiplications as opposed to the non-matrix multiplications used in the CBM. These multiplications are completed via a C++ script compiled in `CBM_core`. Knowledge of the `SpaDES` structure would help an R-knowledgeable user to manipulate simulations but is not necessary to run the current simulations. Prior knowledge of CBM-CFS3 would also help users understand the structure of these modules, the default parameters used, but is not necessary to run simulations. The simulations on which we base our research can be performed with the code block presented below once all the `SpaDES` modules have been cloned and access to all inputs confirmed. We describe all four modules necessary for simulations performed in our study with parameters described in Kurz et al. (2009) and in Stinson et al. (2011). Growth curves as the main change-agent (m^3^/ha) for the study area are available via URL in the `CBM_vol2biomass_RIA` module described below.
## `CBM_defaults`
This module loads all the CBM-CFS3 default parameters (Canadian defaults that is akin to the Archive Index access database in CBM-CFS3). These parameters are then stored in an S4 object `RIAscenarioRuns$cbmData` and accessed throughout the simulations. This object has the following slot names: turnoverRates, rootParameters, decayParameters, spinupParameters, classifierValues, climate, spatialUnitIds, slowAGtoBGTransferRate, biomassToCarbonRate, ecoIndicess, puIndices, stumpParameters, overmatureDeclineParameters, disturbanceMatrix.
Default parameters are stored in an SQLite database in this RStudio project associated with the current simulations (`spadesCBM_RIA.Rproj` - *~spadesCBM_RIA/data/modules/CBM_defaults/data/cbm_defaults*). All parameters used in these simulations are the general Canadian defaults, and can be accessed with common R functionality. In the `SpaDES` environment, modules have events that are scheduled for the simulation. This module has one event (`init`) and does not schedule anything else. It requires the R-object `dbPath` and `sqlDir` to run, both are specified in the global script below.
## `CBM_dataPrep_studyArea_specifyScenario`
This module reads in user-provided information similarly to CBM-CFS3. User provided/expected input include:
- the ages of the stands/pixels (in our case a raster),
- study location information (in our case a raster)
- disturbance information the user wants applied in the simulations (coma separated value (.csv) file)
• the growth curves (.csv) and where they should be applied (which pixels - raster) on the land base,
- growth curve meta data which includes at a minimum growth curve identification and leading species from which a six column table will be built in this module, OR the user can provide the six-column meta data directly as we have done for these simulations (.csv).
The `.inputObjects` section of this module provides links to all input data for the simulations used in our study.
The user-provided study area is used to make a `RIAscenarioRuns$masterRaster` (see `.inputObjects` section of this module) on which all maps and other calculations are based. The spatial unit raster as well as an ecozone raster are created using the `RIAscenarioRuns$masterRaster`. Spatial units (SPUs) are an overlay of administrative boundaries (provinces and territories) and ecozones. SPUs are the link back to the default ecological parameters assembled for CBM-CFS3 simulations in Canada. These parameters are necessary to be able to perform a simulation; you either use the defaults or have to provide alternative values for all the parameters. The location information provided by SPU is used to narrow the parameter options from `CBM_default` to the ones that are specific to this study area. The `CBM_default` modules needs to have been run before `CBM_dataPrep_studyArea_scenario`. Information and data provided are also used to create a table of similar pixels to increase processing speeds (`pixelGroup`). A `data.table` listing the `pixelGoup` in the initial landscape is saved in the `simList` as `RIAscenarioRuns$level3DT`. All necessary vectors for annual processes (main part of the simulations that happen in the `CBM_core` module) are created in this module. These vectors need to be in a specific format for the C++ functions processing. A table stored in the `simList` (`RIAscenarioRuns$mySpuDmid`) links the user-provided disturbance information to the disturbance matrix identification numbers in `CBM_defaults`. The `.inputObjects` function at the end of this module provides quasi-automatic read-in of all the necessary rasters and tables for our simulations. This module is the most specific to a study area. Users should expect this module to contain all idiosyncratic data manipulations specific to the study area and to each simulated scenario. Each scenario requires its own data preparation modules. These are names as follows: `CBM_dataPrep_RIAfri` for the fire-only simulations (years 2020-2540), `CBM_dataPrep_RIApresentDay` representing the current state of the landscape (years 1985-2015), `CBM_dataPrep_RIAharvest1`, and ` CBM_dataPrep_RIAharvest2`, each representing a level of resource extraction (years 2020-2099).
## `CBM_vol2biomass_studyArea`
This module is a translation module. It takes in the growth curves (cumulative m^3^/ha) and returns the biomass increments that drive the simulations. It is an implementation of the stand-level biomass conversion parameters published in Boudewyn et al. (2007). Similarly to the `CBM_dataPrep_myStudyArea_scenario` module, this module is specific to our study area.
Following the CBM-CFS3 approach, the growth curves are cumulative m^3^/ha. Each curves needs to have an identification number permitting the linking to its spatial application; it needs the range of ages from 0 to the oldest ages represented on the landscape; it needs the volume associated with that age vector; and a leading species for that curve. Metadata for each curve was already provided in the data preparation module (`CBM_dataPrep_studyArea_specifyScenario`). All m^3^/ha curves provided are plotted for visual inspection in the `simList` object named `RIAscenarioRuns$volCurves`. The unaltered three above ground carbon pools directly out of the application of the Boudewyn et al. (2007) parameters and caps, resulted in our study as in most cases, in some non-smooth curves, curves with odd shapes, or curves that do not go through a 0 intercept. For these reason, this script incorporates a smoothing procedure that uses a Chapman-Richards function to correct for non-plausible shapes and wiggles in the curves resulting from the translation process. Note that the purpose of the present `SpaDES`-deck is to emulate the CBM-CFS3 approach faithfully. This module saves figures for users to evaluate in *~spadesCBM_RIA/data/modules/CBM_vol2biomass_RIA/figures*. The `CBM_dataPrep_yourStudyArea_specifyScenario` need to be run prior to running this module. This module, however, could be run independently for translation of single-species stand-level m^3^/ha into three increment columns for the above ground live biomass pools with minimal adjustments.
## `CBM_core`
This module uses all the information from the three previously described `SpaDES` modules to compute carbon dynamics in the landcsape. The `CBM_default`, `CBM_vol2biomass_studyArea` and `CBM_dataPrep_studyArea_specifyScenario` modules need to be run prior to this module. This module has six `SpaDES`-events that can be scheduled: `spinup`, `postSpinup`, `saveSpinup`, `annual`, `plot`, and `savePools`. We do not schedule the `saveSpinup` event for our simulations. The `spinup` event is the `init` event run by default in all `SpaDES` modules. This event calls a C++ spinup function. This emulated the traditional initialization procedure of the CBM where each stand (`pixelGroup` in our case) is disturbed using the disturbance specified in `RIAscenarioRuns$historicDMIDs` (usually wildfire for the ecozone) and re-grown using the provided above ground biomass pools, repeatedly, until the dead organic matter (DOM) pools values stabilize or the maximum number of iteration is reached `RIAscenarioRuns$maxRotations`. In this `spinup` event, carbon increment estimates from the biomass estimate of Boudewyn et al. (2007)’s translation of the m^3^/ha curves from the `CBM_vol2biomass_RIA` module are used for each of the above ground live pools. The bark, branches, biomass nonmerch (equation 2 in Boudewyn) pools, and biomass sap (equation 3 in Boudewyn) are grouped under “other” in the CBM. Biomass in coarse and fine roots are derived from above ground biomass estimates using increments and default parameters, one set for softwood and one set for hardwood (see `root_parameter` table in the SQLite default database). To estimate carbon in all other pools, the burn-grow cycle is repeated as described above. In all spatial units in Canada, the historical disturbance is set to fire. The `CBM_default` module has fire return intervals for each ecozone in Canada that can be match with the ecozone of the study area via the ecozone raster, which is what we did for our simulations. Once the `spinup` is complete, the last cycle grows the pixelGroup (still using the same growth curve) to the user-provided age in the age raster. In the `postSpinup` event, matrices are set up for the processes that will happen in the `annual` event. In order, the processes in the `annual` event are: disturbance, one half of growth, dead organic matter (DOM) turnover, biomass turnover, over mature decline calculations, second half of growth, DOM decay, slow decay, and slow soil mixing of dead pools’. Each process is a set of carbon-transactions between pools. The `annual` event is where all the processes are applied. Most carbon transactions are calculated by C++ functions compiled via Rcpp in this module.
The current global script produces a series of default plots via the `plot` event. The `plot` event uses three parameters: the initial plot time (`.plotInitialTime`), the interval to plot (`.plotInterval`), and the carbon pools to plot (`poolsToPlot`). The parameter `poolsToPlot` accepts a character vector consisting of any individual pools in the object `RIAscenarioRuns$cbmPools` as well as `totalCarbon` for the sum of below ground and above ground carbon. The event `savePools` is scheduled last. It creates a `.csv` file (`cPoolsPixelYear.csv`) that contains the carbon pool values for each `pixelGroup` at the end of each simulation year, for all simulation years. The event `spinupDebug` is currently a place holder to explore spinup results, it is set to FALSE in our simulations.
# Current Simulations
The global script in this document will run by default, simulations for 53.4 Mha of managed forests in the northeastern corner of the province of British Colombia, Canada, running the following script, with all the defaults parameters, for four scenarios. The first scenario provides an estimate of the carbon carrying capacity (Liang et al., 2017) of the study area by simulating the landscape using the CBM and the fire model (Armstrong & Cumming, 2003 - Appendix 3) from the year 2020 to 2540 (FRI for Fire Return Interval). The second represents the present day landscape, where disturbances from 1985-2015 as presented in Hermosilla et al. (2016) were applied annually and resulting carbon dynamics simulated with the CBM. The final two scenarios simulate two levels in resource removal as simulated by ws3 (Paradis et al., 2018 - Appendix 2) , on representing a sustainable resource management extraction scenario (base harvest) and the other a lesser amount of resources removed (less harvest). Note that all scenarios use the same `CBM_vol2biomass_RIA` module, and that both the `CBM_default` and `CBM_core` modules are non-changing between scenario. Meta data for each scenario are created in the script below and this script runs four separate simulations.
```{r, module_usage, eval=FALSE, echo=TRUE}
library(Require)
Require("magrittr") # this is needed to use "%>%" below
Require("SpaDES.core")
install_github("PredictiveEcology/CBMutils@development")
#load_all("~/GitHub/PredictiveEcology/CBMutils")
Require("PredictiveEcology/CBMutils (>= 0.0.6)")
options("reproducible.useRequire" = TRUE)
cacheDir <- reproducible::checkPath("cache", create = TRUE)
moduleDir <- reproducible::checkPath("modules")
inputDir <- reproducible::checkPath("inputs", create = TRUE)
outputDir <- reproducible::checkPath("outputs", create = TRUE)
scratchDir <- file.path(tempdir(), "scratch", "CBM") %>% reproducible::checkPath(create = TRUE)
## TODO fix this so we can run all the times with the appropriate sims below
timesFRI <- list(start = 2020.00, end = 2540.00)
timesPresentDay <- list(start = 1985.00, end = 2015.00)
timesHarvest1 <- list(start = 2020.00, end = 2099.00)
parameters <- list(
CBM_defaults = list(
.useCache = TRUE
),
CBM_vol2biomass_RIA = list(
.useCache = TRUE
)
)
#Fire Return Interval
parametersFRI <- parameters
parametersFRI$CBM_dataPrep_RIAfri <- list(
.useCache = TRUE
)
parametersFRI$CBM_core <- list(
.useCache = FALSE, #"init", #c(".inputObjects", "init")
# .plotInterval = 5,
.plotInitialTime = timesFRI$start,
poolsToPlot = c("totalCarbon"),
spinupDebug = FALSE ## TODO: temporary
)
#Present Day 1985-2015
parametersPresentDay <- parameters
parametersPresentDay$CBM_dataPrep_RIApresentDay <- list(
.useCache = TRUE
)
parametersPresentDay$CBM_core <- list(
.useCache = FALSE, #"init", #c(".inputObjects", "init")
# .plotInterval = 5,
.plotInitialTime = timesPresentDay$start,
poolsToPlot = c("totalCarbon"),
spinupDebug = FALSE ## TODO: temporary
)
# harvest1 is the base case
parametersHarvest1 <- parameters
parametersHarvest1$CBM_dataPrep_RIAharvest1 <- list(
.useCache = TRUE
)
parametersHarvest1$CBM_core <- list(
#.useCache = TRUE, #"init", #c(".inputObjects", "init")
# .plotInterval = 5,
.plotInitialTime = timesHarvest1$start,
poolsToPlot = c("totalCarbon"),
spinupDebug = FALSE) ## TODO: temporary
modulesFRI <- list("CBM_defaults", "CBM_dataPrep_RIAfri", "CBM_vol2biomass_RIA", "CBM_core")
modulesPresentDay <- list("CBM_defaults", "CBM_dataPrep_RIApresentDay", "CBM_vol2biomass_RIA", "CBM_core")
modulesHarvest1 <- list("CBM_defaults", "CBM_dataPrep_RIAharvest1", "CBM_vol2biomass_RIA", "CBM_core")
#harvest2 is the less-than-base case
modulesHarvest2 <- list("CBM_defaults", "CBM_dataPrep_RIAharvest2", "CBM_vol2biomass_RIA", "CBM_core")
objects <- list(
dbPath = file.path(inputDir, "cbm_defaults", "cbm_defaults.db"),
sqlDir = file.path(inputDir, "cbm_defaults")
)
paths <- list(
cachePath = cacheDir,
modulePath = moduleDir,
inputPath = inputDir,
rasterPath = scratchDir
)
pathsFRI <- paths
pathsFRI$outputPath <- file.path(outputDir,"FRI")
pathsPresentDay <- paths
pathsPresentDay$outputPath <- file.path(outputDir,"presentDay")
pathsHarvest1 <- paths
pathsHarvest1$outputPath <- file.path(outputDir,"harvest1")
pathsHarvest2 <- paths
pathsHarvest2$outputPath <- file.path(outputDir,"harvest2")
quickPlot::dev.useRSGD(FALSE)
dev()
clearPlot()
options(spades.moduleCodeChecks = FALSE,
reproducible.useMemoise = FALSE,
spades.recoveryMode = FALSE)
#reproducible.useNewDigestAlgorithm = 2)
# this is the whens for the 540 years of fire runs
whensFRI <- sort(c(timesFRI$start, timesFRI$start + 1:4 * 100, timesFRI$end - 2:0))
# this is for the presentDay runs
whensPresentDay <- sort(c(timesPresentDay$start, timesPresentDay$start + c(5, 10, 15, 20, 25),
timesPresentDay$end - 2:0))
# this is for the harvest runs
whensHarvest1 <- sort(c(timesHarvest1$start, timesHarvest1$start + c(10, 30, 50, 60),
timesHarvest1$end - 1:0))
outputsFRI <- as.data.frame(expand.grid(objectName = c("cbmPools", "NPP"), saveTime = whensFRI))
outputsPresentDay <- as.data.frame(expand.grid(objectName = c("cbmPools", "NPP"), saveTime = whensPresentDay))
outputsHarvest1 <- as.data.frame(expand.grid(objectName = c("cbmPools", "NPP"), saveTime = whensHarvest1))
## All simulation parameters are set-up above this line.
## All simulations are set-up (simInit) and performed (spades) below this line
RIApresentDayRuns <- simInitAndSpades(times = timesPresentDay,
params = parametersPresentDay,
modules = modulesPresentDay,
objects = objects,
paths = pathsPresentDay,
outputs = outputsPresentDay,
loadOrder = unlist(modulesPresentDay),
debug = TRUE)
RIAfriRuns <- simInitAndSpades(times = timesFRI,
params = parametersFRI,
modules = modulesFRI,
objects = objects,
paths = pathsFRI,
outputs = outputsFRI,
loadOrder = unlist(modulesFRI),
debug = TRUE)
RIAharvest1Runs <- simInitAndSpades(times = timesHarvest1,
params = parametersHarvest1,
modules = modulesHarvest1,
objects = objects,
paths = pathsHarvest1,
outputs = outputsHarvest1,
loadOrder = unlist(modulesHarvest1),
debug = TRUE)
RIAharvest2Runs <- simInitAndSpades(times = timesHarvest1,
params = parametersHarvest1,
modules = modulesHarvest2,
objects = objects,
paths = pathsHarvest2,
outputs = outputsHarvest1,
loadOrder = unlist(modulesHarvest2),
debug = TRUE)
```
# `CBMutils`
In the spirit of PERFICT (see McIntire et al 2021), we developed a series of utility functions, to support simulations using this `SpaDES`-deck. This are in the package `CBMutils` and are available on a public github repository.
# References
Armstrong, G. W., & Cumming, S. G. (2003). Estimating the Cost of Land Base Changes Due to Wildfire Using Shadow Prices. Forest Science, 49(5), 719–730. https://doi.org/10.1093/forestscience/49.5.719
Boudewyn, P., Song, X., Magnussen, S., & Gillis, M. D. (2007). Model-based, volume-to-biomass conversion for forested and vegetated land in Canada (P. F. C. Canadian Forest Service, Trans.; ISSN 0830-0453 ISBN 978-0-662-46513-3; Information Report BC-X-411). Natural Resources Canada.
Hermosilla, T., Wulder, M. A., White, J. C., Coops, N. C., Hobart, G. W., & Campbell, L. B. (2016). Mass data processing of time series Landsat imagery: Pixels to data products for forest monitoring. International Journal of Digital Earth, 1–20. https://doi.org/10.1080/17538947.2016.1187673
Kurz, W. A., Dymond, C. C., White, T. M., Stinson, G., Shaw, C. H., Rampley, G. J., Smyth, C., Simpson, B. N., Neilson, E. T., Trofymow, J. A., Metsaranta, J., & Apps, M. J. (2009). CBM-CFS3: A model of carbon-dynamics in forestry and land-use change implementing IPCC standards. Ecological Modelling, 220(4), 480–504.
Liang, S., Hurteau, M. D., & Westerling, A. L. (2017). Potential decline in carbon carrying capacity under projected climate-wildfire interactions in the Sierra Nevada. Scientific Reports, 7(1), 2420. https://doi.org/10.1038/s41598-017-02686-0
McIntire, E. J. B., Chubaty, A., Cumming, S. G., Andison, D. W., Barros, C., Boisvenue, C., Hache, S., Luo, Y., Micheletti, T., & Stewart, F. (2021). Predictive Ecology: A Re-imagined Foundation and Toolkit for Ecological Models. Authorea (Submitted to Ecology Letters). https://doi.org/DOI: 10.22541/au.161709444.40008325/v1
McIntire, E. J. B., Chubaty, A., Luo, Y., & Cumming, S. G. (2019). Develop and Run Spatially Explicit Discrete Event Simulation Models (2.07) [R language]. https://spades.predictiveecology.org, https://github.com/PredictiveEcology/SpaDES
Paradis, G., Bouchard, M., LeBel, L., & D’Amours, S. (2018). A bi-level model formulation for the distributed wood supply planning problem. Canadian Journal of Forest Research, 48(2), 160–171. https://doi.org/10.1139/cjfr-2017-0240
Stinson, G., Kurz, W. A., Smyth, C. E., Neilson, E. T., Dymond, C. C., Metsaranta, J. M., Boisvenue, C., Rampley, G. J., Li, Q., White, T. M., & Blain, D. (2011). An inventory-based analysis of Canada’s managed forest carbon dynamics, 1990 to 2008. Global Change Biology, 17(6), 2227–2244. https://doi.org/10.1111/j.1365-2486.2010.02369.x
<!--
reference list is automatically generated with 'references.bib';
see https://rmarkdown.rstudio.com/authoring_bibliographies_and_citations.html
-->