vignettes/run_pmodel_points.Rmd
run_pmodel_points.Rmd
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
Often, we want to compare the P-model’s predicted leaf-level photosynthetic (and related) traits with values measured in the field. Field data is typically provided as data for a single point in time and accompanied by information about the geographic location of the observation. This vignette describes a workflow for simulations of P-model quantities based on growing season average conditions and using climate forcing data from a high-resolution product, here WorldClim, provided as monthly climatologies of a set of climate variables at ~800 m resolution globally. The high resolution of the climate forcing data is essential here since we want to account for small-scale climate variations mediated by topographic gradients (which are not captured when using, e.g., 0.5 deg data as provided in commonly used global climate data products).
Since we’re interested in point simulations with no temporal dimension (to be compared to point observations), we can use the simple P-model implementation from the rpmodel R package.
The workflow below outlines the steps needed to collect the climate
forcing data from WorldClim, reformat it and convert units so that it
can be used as forcing for a call to the rpmodel::rpmodel()
function. Use ?rpmodel
for a documentation of the variables
and their units provided as function arguments.
The only information required for running point simulations with the
P-model is the geographic position of the sites and their elevation. A
site name is required as an ID for the output. The site meta information
has to be provided as a data frame containing the following columns:
sitename, lon, lat, elv
.
Let’s use the FLUXNET2015 site info data frame from ingestr as an example here.
ingestr makes it easy to collect WorldClim data from files available
locally (in directory ~/data/worldclim
). Here, we use the
monthly climatologies of daily minimum and maximum temperatures, vapour
pressure, and solar radiation. See here for details about
WorldClim variables and their units.
This is done here for three example sites from the FLUXNET2015
network. The site meta info data frame defined is used here for the
ingest()
function call.
Next, we aggregate the monthly WorldClim climatology to means across
the thermal growing season, i.e., over months where the growth
temperature is above 0 deg C. Before aggregation, we also convert
WorldClim variables to the units required for rpmodel
. See
?rpmodel
for information about the arguments.
get_growingseasonmean <- function(df){
df |>
filter(tgrowth > 0) |>
ungroup() |>
summarise(across(c(tgrowth, vpd, ppfd), mean))
}
kfFEC <- 2.04
df_wc <- df_wc |>
unnest(data) |>
## add latitude
left_join(df_sites, by = "sitename") |>
## vapour pressure kPa -> Pa
mutate(vapr = vapr * 1e3) |>
## PPFD from solar radiation: kJ m-2 day-1 -> mol m−2 s−1 PAR
mutate(ppfd = 1e3 * srad * kfFEC * 1.0e-6 / (60 * 60 * 24)) |>
## calculate VPD (Pa) based on tmin and tmax
rowwise() |>
mutate(vpd = calc_vpd(eact = vapr, tmin = tmin, tmax = tmax)) |>
## calculate growth temperature (average daytime temperature), taking the 15 in each month
mutate(doy = lubridate::yday(lubridate::ymd("2001-01-15") + months(month - 1))) |>
mutate(tgrowth = ingestr::calc_tgrowth(tmin, tmax, lat, doy)) |>
## average over growing season (where Tgrowth > 0 deg C)
group_by(sitename) |>
nest() |>
mutate(data_growingseason = purrr::map(data, ~get_growingseasonmean(.))) |>
unnest(data_growingseason) |>
select(-data) |>
## since we don't know the year of measurement (often), we assume a "generic" concentration (ppm)
mutate(co2 = 380) |>
## we're interested not in ecosystem fluxes, but in leaf-level quantities
## therefore, apply a "dummy" fAPAR = 1
mutate(fapar = 1.0) |>
## add elevation (elv)
left_join(df_sites, by = "sitename")
Now, we convert units of variables, derive the growth temperature, and average variables over the (thermal) growing season, i.e., over months where the growth temperature is above 0 deg C.
df_wc <- df_wc |>
## apply the P-model on each site (corresponding to each row)
group_by(sitename) |>
nest() |>
mutate(out = purrr::map(data,
~rpmodel::rpmodel(
tc = .x$tgrowth,
vpd = .x$vpd,
co2 = .x$co2,
fapar = .x$fapar,
ppfd = .x$ppfd,
elv = .x$elv,
kphio = 0.049977,
beta = 146,
c4 = FALSE,
method_jmaxlim = "wang17",
do_ftemp_kphio = FALSE,
do_soilmstress = FALSE,
verbose = TRUE
))) |>
mutate(out = purrr::map(out, ~as_tibble(.))) %>%
unnest(c(data, out))
The returned object contains all forcing data in P-model units and aggregated over the thermal growing season, and all P-model outputs.
knitr::kable(df_wc)