The rsofun
package and framework includes two main
models. The pmodel
and biomee
(which in part
relies on pmodel component). Here we give a short example on how to run
the biomee
model on the included demo datasets to
familiarize yourself with both the data structure and the outputs.
The package includes two demo datasets to run. These files can be directly loaded into your workspace by typing:
These are real data from the Swiss CH-Lae fluxnet site. We can use
these data to run the model, together with observations of GPP we can
also parameterize biomee
parameters.
BiomeE is a cohort-based vegetation model which simulates vegetation dynamics and biogeochemical processes (Weng et al., 2015). The model is able to link photosynthesis standard models (Farquhar et al., 1980) with tree allometry. In our formulation we retain the original model structure with the standard photosynthesis formulation (i.e. “gs_leuning”) as well as an alternative “p-model” approach. Both model structures operate at different time scales, where the original input has an hourly time step our alternative p-model approach uses a daily time step. Hence, we have two different datasets as driver data (with the BiomeE p-model input being an aggregate of the high resolution hourly data).
With all data prepared we can run the model using
runread_biomee_f()
. This function takes the nested data
structure and runs the model site by site, returning nested model output
results matching the input drivers. In our case only one site will be
evaluated.
# print parameter settings
biomee_gs_leuning_drivers$params_siml
#> [[1]]
#> # A tibble: 1 × 14
#> spinup spinupyears recycle firstyeartrend nyeartrend outputhourly outputdaily
#> <lgl> <dbl> <dbl> <dbl> <dbl> <lgl> <lgl>
#> 1 TRUE 250 1 2009 1 TRUE TRUE
#> # ℹ 7 more variables: do_U_shaped_mortality <lgl>, update_annualLAImax <lgl>,
#> # do_closedN_run <lgl>, do_reset_veg <lgl>, dist_frequency <dbl>,
#> # method_photosynth <chr>, method_mortality <chr>
# print forcing
head(biomee_gs_leuning_drivers$forcing)
#> [[1]]
#> # A tibble: 8,760 × 19
#> date year doy hour temp temp_soil prec snow vpd rh
#> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <lgl> <lgl> <dbl>
#> 1 2009-01-01 2009 1 0 0.728 3.16 0.0000184 NA NA 91.6
#> 2 2009-01-01 2009 1 1 0.780 3.20 0.0000116 NA NA 91.5
#> 3 2009-01-01 2009 1 2 0.519 3.23 0.0000116 NA NA 93.2
#> 4 2009-01-01 2009 1 3 0.476 3.28 0.0000116 NA NA 92.5
#> 5 2009-01-01 2009 1 4 0.336 3.30 0.0000140 NA NA 92.9
#> 6 2009-01-01 2009 1 5 0.278 3.30 0.0000140 NA NA 93.8
#> 7 2009-01-01 2009 1 6 0.0966 3.28 0.0000140 NA NA 95.4
#> 8 2009-01-01 2009 1 7 0.172 3.30 0.0000211 NA NA 95.4
#> 9 2009-01-01 2009 1 8 0.236 3.33 0.0000211 NA NA 95.2
#> 10 2009-01-01 2009 1 9 0.152 3.41 0.0000211 NA NA 96.1
#> # ℹ 8,750 more rows
#> # ℹ 9 more variables: ppfd <dbl>, par <dbl>, patm <dbl>, wind <dbl>,
#> # ccov_int <lgl>, ccov <lgl>, co2 <dbl>, swc <dbl>,
#> # `lubridate::hour(datehour)` <int>
set.seed(2023)
# run the model
biomee_gs_leuning_output <- runread_biomee_f(
biomee_gs_leuning_drivers,
makecheck = TRUE,
parallel = FALSE
)
# split out the annual data
biomee_gs_leuning_output <- biomee_gs_leuning_output$data[[1]]$output_annual_tile
We can now visualize the model output.
# we only have one site so we'll unnest
# the main model output
biomee_gs_leuning_output |>
ggplot() +
geom_line(aes(x = year, y = GPP)) +
theme_classic()+labs(x = "Year", y = "GPP")
biomee_gs_leuning_output |>
ggplot() +
geom_line(aes(x = year, y = plantC)) +
theme_classic()+labs(x = "Year", y = "plantC")
Running the fast P-model implementation.
# print parameter settings
biomee_p_model_drivers$params_siml
#> [[1]]
#> # A tibble: 1 × 14
#> spinup spinupyears recycle firstyeartrend nyeartrend outputhourly outputdaily
#> <lgl> <dbl> <dbl> <dbl> <dbl> <lgl> <lgl>
#> 1 TRUE 250 1 2009 1 TRUE TRUE
#> # ℹ 7 more variables: do_U_shaped_mortality <lgl>, update_annualLAImax <lgl>,
#> # do_closedN_run <lgl>, do_reset_veg <lgl>, dist_frequency <dbl>,
#> # method_photosynth <chr>, method_mortality <chr>
# print forcing for P-model
head(biomee_p_model_drivers$forcing)
#> [[1]]
#> # A tibble: 365 × 18
#> date year doy hour temp temp_soil prec snow vpd rh
#> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <lgl> <lgl> <dbl>
#> 1 2009-01-01 2009 1 11.5 0.384 3.39 0.0000166 NA NA 93.7
#> 2 2009-01-02 2009 2 11.5 -1.64 2.55 0.0000232 NA NA 92.5
#> 3 2009-01-03 2009 3 11.5 -2.51 1.95 0.00000371 NA NA 85.1
#> 4 2009-01-04 2009 4 11.5 -1.82 2.20 0.0000130 NA NA 83.5
#> 5 2009-01-05 2009 5 11.5 -1.34 2.23 0.0000223 NA NA 87.8
#> 6 2009-01-06 2009 6 11.5 -0.450 2.75 0.0000219 NA NA 90.9
#> 7 2009-01-07 2009 7 11.5 0.266 3.50 0.0000136 NA NA 89.7
#> 8 2009-01-08 2009 8 11.5 0.504 3.52 0.0000113 NA NA 86.1
#> 9 2009-01-09 2009 9 11.5 0.0869 3.49 0.0000186 NA NA 90.3
#> 10 2009-01-10 2009 10 11.5 -0.404 3.44 0.0000125 NA NA 90.1
#> # ℹ 355 more rows
#> # ℹ 8 more variables: ppfd <dbl>, par <dbl>, patm <dbl>, wind <dbl>,
#> # ccov_int <lgl>, ccov <lgl>, co2 <dbl>, swc <dbl>
# run the model
biomee_p_model_output <- runread_biomee_f(
biomee_p_model_drivers,
makecheck = TRUE,
parallel = FALSE
)
# split out the annual data for visuals
biomee_p_model_output <- biomee_p_model_output$data[[1]]$output_annual_tile
To optimize new parameters based upon driver data and a validation
dataset we must first specify an optimization strategy and settings, as
well as parameter ranges. In this example, we use as cost the root mean
squared error (RMSE) between simulated and observed targets (GPP, LAI,
Density and Biomass) and we minimize it using the GenSA
optimizer.
# Mortality as DBH
settings <- list(
method = "GenSA",
metric = cost_rmse_biomee,
control = list(
maxit = 10
),
par = list(
phiRL = list(lower=0.5, upper=5, init=3.5),
LAI_light = list(lower=2, upper=5, init=3.5),
tf_base = list(lower=0.5, upper=1.5, init=1),
par_mort = list(lower=0.1, upper=2, init=1))
)
pars <- calib_sofun(
drivers = biomee_gs_leuning_drivers,
obs = biomee_validation,
settings = settings
)
Using the calibrated parameter values, we can run again the BiomeE simulations.
# replace parameter values by calibration output
drivers <- biomee_p_model_drivers
drivers$params_species[[1]]$phiRL[] <- pars$par[1]
drivers$params_species[[1]]$LAI_light[] <- pars$par[2]
drivers$params_tile[[1]]$tf_base <- pars$par[3]
drivers$params_tile[[1]]$par_mort <- pars$par[4]
# run the model with new parameter values
biomee_p_model_output_calib <- runread_biomee_f(
drivers,
makecheck = TRUE,
parallel = FALSE
)
# split out the annual data
biomee_p_model_output_calib <- biomee_p_model_output_calib$data[[1]]$output_annual_tile
Finally, we can visually compare the two model runs. We plot the original model run in black and the run using the calibrated parameters in grey. The dashed line represents the validation data, i.e. the observed GPP and Biomass.