15  Forest Succession and Wildfire using setupProject

Author

Eliot McIntire and Ian Eddy

Published

December 3, 2024

See Barebones R script for the code shown in this chapter

1.5 hours – estimated time for 1st time executing

6 GB RAM – estimated peak RAM for executing

We have developed an R version of LANDIS-II’s Biomass Succession Extension, comprised of 2 modules: Biomass_core and Biomass_regeneration. We can combine these with a fire model, such as scfm which is a collaborative effort lead by Steve Cumming at Laval, University (thus the name: Steve Cumming Fire Model).

As with other examples, we also include all the parameterization modules here, with Biomass_borealDataPrep for the Biomass_*** modules and scfmLandcoverInit, scfmRegime and scfmDriver for the scfm family.

This makes for a 10 module project. Using setupProject, we can readily run these from their canonical “i.e., current, up to date, open and available” versions:

Time to run this is between 1 and 2 hours.

Code
# This repository is ours and it has the latest versions of our packages
repos <- c("predictiveecology.r-universe.dev", getOption("repos"))
# Need the latest version
if (tryCatch(packageVersion("SpaDES.project") < "0.1.1", error = function(x) TRUE))
  install.packages(c("SpaDES.project", "Require"), repos = repos)
# 

out <- SpaDES.project::setupProject(
  Restart = TRUE,
  updateRprofile = FALSE,
  paths = list(projectPath = "~/SpaDES_book/Wildfire_demo"),
  modules = c("PredictiveEcology/Biomass_borealDataPrep@main",
              "PredictiveEcology/Biomass_core@main",
              "PredictiveEcology/Biomass_regeneration@main",
              file.path("PredictiveEcology/scfm@development/modules",
                        c("scfmLandcoverInit", "scfmRegime", "scfmDriver",
                          "scfmIgnition", "scfmEscape", "scfmSpread",
                          "scfmDiagnostics"))
              #note scfm is a series of modules on a single git repository
  ),
  params = list(
    .globals = list(
      dataYear = 2011, #will get kNN 2011 data, and NTEMS 2011 landcover
      sppEquivCol = "LandR",
      .plots = c("png"),
      .useCache = c(".inputObjects", "init")
    ),
    scfmDriver = list(targetN = 1000, #default is 4000 - higher targetN adds time + precision
                      # targetN would ideally be minimum 2000 - mean fire size estimates will be bad with 1000
                      .useParallelFireRegimePolys = TRUE) #assumes parallelization is an otpion
    
  ),
  options = list(#spades.allowInitDuringSimInit = TRUE,
    spades.allowSequentialCaching = TRUE,
    spades.moduleCodeChecks = FALSE,
    spades.recoveryMode = 1
  ),
  packages = c('RCurl', 'XML', 'snow', 'googledrive'),
  times = list(start = 2011, end = 2081),
  #70 years of fire should be enough to evaluate MAAB
  studyArea = {
    targetCRS <- paste("+proj=lcc +lat_1=49 +lat_2=77 +lat_0=0 +lon_0=-95 +x_0=0 +y_0=0",
                       "+datum=NAD83 +units=m +no_defs +ellps=GRS80 +towgs84=0,0,0")
    sa <- terra::vect(cbind(-1209980, 7586865), crs = targetCRS)
    sa <- LandR::randomStudyArea(center = sa, size = 10000 * 250 * 30000, seed = 1002)
    sa <- sf::st_as_sf(sa)
  },
  studyAreaLarge = {
    sf::st_buffer(studyArea, 5000)
  },
  rasterToMatchLarge = {
    rtml<- terra::rast(terra::ext(studyAreaLarge), res = c(250, 250))
    terra::crs(rtml) <- terra::crs(studyAreaLarge)
    rtml[] <- 1
    rtml <- terra::mask(rtml, studyAreaLarge)
  },
  rasterToMatch = {
    rtm <- terra::crop(rasterToMatchLarge, studyArea)
    rtm <- terra::mask(rtm, studyArea)
  },
  sppEquiv = {
    speciesInStudy <- LandR::speciesInStudyArea(studyAreaLarge)
    species <- LandR::equivalentName(speciesInStudy$speciesList, df = LandR::sppEquivalencies_CA, "LandR")
    sppEquiv <- LandR::sppEquivalencies_CA[LandR %in% species]
    sppEquiv <- sppEquiv[KNN != "" & LANDIS_traits != ""] #avoid a bug with shore pine
  } 
)

outSim <- do.call(SpaDES.core::simInitAndSpades, out)

15.1 Examining things

We can do all sorts of things. We will start with a few simple “accessors”, i.e., “access something from the simList”. completed shows the events that were run. elapsedTime shows how much time each event took.

Code
completed(outSim)
elapsedTime(outSim, units = "mins")

The module metadata can be accessed from the sim or can be read from the module source files or it is usually built into the Rmd file that comes with the module.

Code
mm <- moduleMetadata(outSim)

# a list of all the module metadata
mm$Biomass_borealDataPrep$

15.2 Changing things

Setting .plots = "png" will turn on all known plotting (that uses the Plots function) and save them all as png files in the figures subfolder.

Code
out$params$.globals$.plots <- "png"
outSim <- simInitAndSpades2(out)

Then we can look in the outputs/figures folder to see all the figures that the modules created.

15.3 Barebones R script

Code
# This repository is ours and it has the latest versions of our packages
repos <- c("predictiveecology.r-universe.dev", getOption("repos"))
# Need the latest version
if (tryCatch(packageVersion("SpaDES.project") < "0.1.1", error = function(x) TRUE))
  install.packages(c("SpaDES.project", "Require"), repos = repos)
# 

out <- SpaDES.project::setupProject(
  Restart = TRUE,
  updateRprofile = FALSE,
  paths = list(projectPath = "~/SpaDES_book/Wildfire_demo"),
  modules = c("PredictiveEcology/Biomass_borealDataPrep@main",
              "PredictiveEcology/Biomass_core@main",
              "PredictiveEcology/Biomass_regeneration@main",
              file.path("PredictiveEcology/scfm@development/modules",
                        c("scfmLandcoverInit", "scfmRegime", "scfmDriver",
                          "scfmIgnition", "scfmEscape", "scfmSpread",
                          "scfmDiagnostics"))
              #note scfm is a series of modules on a single git repository
  ),
  params = list(
    .globals = list(
      dataYear = 2011, #will get kNN 2011 data, and NTEMS 2011 landcover
      sppEquivCol = "LandR",
      .plots = c("png"),
      .useCache = c(".inputObjects", "init")
    ),
    scfmDriver = list(targetN = 1000, #default is 4000 - higher targetN adds time + precision
                      # targetN would ideally be minimum 2000 - mean fire size estimates will be bad with 1000
                      .useParallelFireRegimePolys = TRUE) #assumes parallelization is an otpion
    
  ),
  options = list(#spades.allowInitDuringSimInit = TRUE,
    spades.allowSequentialCaching = TRUE,
    spades.moduleCodeChecks = FALSE,
    spades.recoveryMode = 1
  ),
  packages = c('RCurl', 'XML', 'snow', 'googledrive'),
  times = list(start = 2011, end = 2081),
  #70 years of fire should be enough to evaluate MAAB
  studyArea = {
    targetCRS <- paste("+proj=lcc +lat_1=49 +lat_2=77 +lat_0=0 +lon_0=-95 +x_0=0 +y_0=0",
                       "+datum=NAD83 +units=m +no_defs +ellps=GRS80 +towgs84=0,0,0")
    sa <- terra::vect(cbind(-1209980, 7586865), crs = targetCRS)
    sa <- LandR::randomStudyArea(center = sa, size = 10000 * 250 * 30000, seed = 1002)
    sa <- sf::st_as_sf(sa)
  },
  studyAreaLarge = {
    sf::st_buffer(studyArea, 5000)
  },
  rasterToMatchLarge = {
    rtml<- terra::rast(terra::ext(studyAreaLarge), res = c(250, 250))
    terra::crs(rtml) <- terra::crs(studyAreaLarge)
    rtml[] <- 1
    rtml <- terra::mask(rtml, studyAreaLarge)
  },
  rasterToMatch = {
    rtm <- terra::crop(rasterToMatchLarge, studyArea)
    rtm <- terra::mask(rtm, studyArea)
  },
  sppEquiv = {
    speciesInStudy <- LandR::speciesInStudyArea(studyAreaLarge)
    species <- LandR::equivalentName(speciesInStudy$speciesList, df = LandR::sppEquivalencies_CA, "LandR")
    sppEquiv <- LandR::sppEquivalencies_CA[LandR %in% species]
    sppEquiv <- sppEquiv[KNN != "" & LANDIS_traits != ""] #avoid a bug with shore pine
  } 
)

outSim <- do.call(SpaDES.core::simInitAndSpades, out)


completed(outSim)
elapsedTime(outSim, units = "mins")

mm <- moduleMetadata(outSim)

# a list of all the module metadata
mm$Biomass_borealDataPrep$

out$params$.globals$.plots <- "png"
outSim <- simInitAndSpades2(out)