Manually select some sites from which we’re going to use the data for evaluation and calibration.
mysites <- c("BE-Vie", "DE-Tha", "DK-Sor", "FI-Hyy", "IT-Col", "NL-Loo", "US-MMS", "US-WCr", "US-UMB", "US-Syv", "DE-Hai", "IT-MBo", "US-GLE", "FR-Fon", "NL-Hor", "US-UMd", "AU-Dry", "DE-Obe", "IT-Tor", "US-Wi4")
Create a site meta info table that contains all the site-specific information that is used to force site-simulations (e.g. starting year, number of simulations years, elevation, etc.). For FLUXNET2015 data, required meta info is provided by the rsofun
package (data frame rsofun::metainfo_Tier1_sites_kgclimate_fluxnet2015
).
path_siteinfo <- "~/.siteinfo_example_fortran.csv"
siteinfo <- rsofun::metainfo_Tier1_sites_kgclimate_fluxnet2015 %>%
dplyr::filter(sitename %in% mysites) %>%
write_csv(path = path_siteinfo)
Now specify the simulation parameters that are identical for all site-scale simulations.
params_siml <- list(
spinup = TRUE,
spinupyears = 10,
recycle = 1,
soilmstress = FALSE,
tempstress = FALSE,
calc_aet_fapar_vpd = FALSE,
in_ppfd = TRUE,
in_netrad = FALSE,
const_clim_year = -9999,
const_lu_year = -9999,
const_co2_year = -9999,
const_ndep_year = -9999,
const_nfert_year = -9999,
outdt = 1,
ltre = FALSE,
ltne = FALSE,
ltrd = FALSE,
ltnd = FALSE,
lgr3 = TRUE,
lgn3 = FALSE,
lgr4 = FALSE
)
Run prepare_setup_sofun()
to define the simulation settings that contain all the information specified by the two steps above (meta info, and simulation parameters).
settings_sims <- prepare_setup_sofun(siteinfo = siteinfo, params_siml = params_siml)
First, let’s do it by hand (calibration of parameters is shown later).
params_modl <- list(
kphio = 0.04997714009213085,
soilm_par_a = 1.0,
soilm_par_b = 0.0,
vpdstress_par_a = 0.2,
vpdstress_par_b = 0.2,
vpdstress_par_m = 5
)
For now, this is implemented as an illustration. Should be made site-specific.
df_soiltexture <- bind_rows(
top = tibble(layer = "top", fsand = 0.4, fclay = 0.3, forg = 0.1, fgravel = 0.1),
bottom = tibble(layer = "bottom", fsand = 0.4, fclay = 0.3, forg = 0.1, fgravel = 0.1)
)
First, define input settings.
settings_input <- list(
data = NA,
temperature = "fluxnet2015",
precipitation = "fluxnet2015",
vpd = "fluxnet2015",
ppfd = "fluxnet2015",
netrad = "fluxnet2015", # c("fluxnet2015", "watch_wfdei"),
patm = "fluxnet2015",
netrad = NA,
cloudcover = "cru",
path_input = "~/sofun_inputs/example/",
path_watch_wfdei = "~/data/watch_wfdei/",
path_cru = "~/data/cru/ts_4.01/",
path_MODIS_FPAR_MCD15A3H = "~/data/fluxnet_subsets/fapar_MODIS_FPAR_MCD15A3H_gee_MCD15A3H_fluxnet2015_gee_subset/",
path_MODIS_EVI_MOD13Q1 = "~/data/fluxnet_subsets/fapar_MODIS_EVI_MOD13Q1_gee_MOD13Q1_fluxnet2015_gee_subset/",
path_co2 = "~/data/co2/cCO2_rcp85_const850-1765.csv",
path_fluxnet2015 = "~/data/FLUXNET-2015_Tier1/20191024/DD/",
path_fluxnet2015_hh = "~/data/FLUXNET-2015_Tier1/20191024/HH/",
get_from_remote = FALSE,
settings_gee = get_settings_gee(
bundle = "fpar",
python_path = "/Users/benjaminstocker/Library/Enthought/Canopy_64bit/User/bin/python",
gee_path = "~/gee_subset/gee_subset/"
),
fapar = "MODIS_FPAR_MCD15A3H",
splined_fapar = TRUE
)
Then, get the input data.
## [1] "Creating raster brick from file ~/data/cru/ts_4.01/cru_ts4.01.1901.2016.cld.dat.nc"
Run the model for all the sites specified in the first step.
df_drivers <- collect_drivers_sofun(
settings = settings_sims,
forcing = ddf_input,
df_soiltexture = df_soiltexture
)
## run for a single site
mod <- run_sofun_f_bysite(
df_drivers$sitename[1],
df_drivers$params_siml[[1]],
df_drivers$siteinfo[[1]],
df_drivers$forcing[[1]],
df_drivers$df_soiltexture[[1]],
params_modl = params_modl,
makecheck = TRUE
)
## Run for the full set of sites
ptm <- proc.time()
df_output <- runread_sofun_f(
df_drivers,
params_modl = params_modl,
makecheck = TRUE,
parallel = FALSE
)
print(ptm)
## user system elapsed
## 6.000 0.803 9.246
# microbenchmark::microbenchmark(
# runread_sofun_f(
# df_drivers,
# params_modl = params_modl,
# makecheck = TRUE,
# parallel = TRUE,
# ncores = 4
# ),
# runread_sofun_f(
# df_drivers,
# params_modl = params_modl,
# makecheck = TRUE,
# parallel = FALSE
# ),
# times = 5,
# units = 's'
# )
df_output$out_sofun[[1]] %>%
ggplot(aes(x=date, y=gpp)) +
geom_line() +
labs(title = df_output$sitename[[1]], subtitle = "SOFUN output")
Define calibration settings.
## Define calibration settings common for all setups
settings_calib <- list(
method = "gensa",
targetvars = c("gpp"),
timescale = list( gpp = "d" ),
path_fluxnet2015 = "~/data/FLUXNET-2015_Tier1/20191024/DD/",
path_fluxnet2015_hh = "~/data/FLUXNET-2015_Tier1/20191024/HH/",
threshold_GPP = 0.5,
path_gepisat = "~/data/gepisat/v3_fluxnet2015/daily_gpp/",
maxit = 5, # (5 for gensa) (30 for optimr) #
sitenames = mysites,
filter_temp_max = 35.0,
filter_drought = FALSE,
metric = "rmse",
dir_results = "./",
name = "ORG",
par = list( kphio = list( lower=0.03, upper=0.07, init=0.0496 ) ),
datasource = list( gpp = "fluxnet2015_NT" ),
filter_temp_min = NA,
filter_soilm_min = NA
)
Get calibration target data.
ddf_obs_calib <- get_obs_calib(
settings_calib = settings_calib,
dplyr::select(df_drivers, sitename, siteinfo) %>% tidyr::unnest(siteinfo),
settings_input
)
## [1] "getting obs for BE-Vie"
## [1] "Getting FLUXNET data for BE-Vie ..."
## [1] "getting obs for DE-Tha"
## [1] "Getting FLUXNET data for DE-Tha ..."
## [1] "getting obs for DK-Sor"
## [1] "Getting FLUXNET data for DK-Sor ..."
## [1] "getting obs for FI-Hyy"
## [1] "Getting FLUXNET data for FI-Hyy ..."
## [1] "getting obs for IT-Col"
## [1] "Getting FLUXNET data for IT-Col ..."
## [1] "getting obs for NL-Loo"
## [1] "Getting FLUXNET data for NL-Loo ..."
## [1] "getting obs for US-MMS"
## [1] "Getting FLUXNET data for US-MMS ..."
## [1] "getting obs for US-WCr"
## [1] "Getting FLUXNET data for US-WCr ..."
## [1] "getting obs for US-UMB"
## [1] "Getting FLUXNET data for US-UMB ..."
## [1] "getting obs for US-Syv"
## [1] "Getting FLUXNET data for US-Syv ..."
## [1] "getting obs for DE-Hai"
## [1] "Getting FLUXNET data for DE-Hai ..."
## [1] "getting obs for IT-MBo"
## [1] "Getting FLUXNET data for IT-MBo ..."
## [1] "getting obs for US-GLE"
## [1] "Getting FLUXNET data for US-GLE ..."
## [1] "getting obs for FR-Fon"
## [1] "Getting FLUXNET data for FR-Fon ..."
## [1] "getting obs for NL-Hor"
## [1] "Getting FLUXNET data for NL-Hor ..."
## [1] "getting obs for US-UMd"
## [1] "Getting FLUXNET data for US-UMd ..."
## [1] "getting obs for AU-Dry"
## [1] "Getting FLUXNET data for AU-Dry ..."
## [1] "getting obs for DE-Obe"
## [1] "Getting FLUXNET data for DE-Obe ..."
## [1] "getting obs for IT-Tor"
## [1] "Getting FLUXNET data for IT-Tor ..."
## [1] "getting obs for US-Wi4"
## [1] "Getting FLUXNET data for US-Wi4 ..."
Calibrate the model.
set.seed(1982)
settings_calib <- calib_sofun(
settings_calib,
df_drivers,
ddf_obs = ddf_obs_calib
)
## kphio
## 0.05231893
## [1] "writing output from GenSA function to .//out_gensa_ORG.Rdata"
## [1] "writing calibrated parameters to .//params_opt_ORG.csv"
The calibrated parameters are returned by calib_sofun()
as part of the list:
print(settings_calib$par_opt)
## kphio
## 0.05231893
Run the model once again with these parameters and evaluate results.
mylist <- readr::read_csv("~/eval_pmodel/myselect_fluxnet2015.csv") %>%
dplyr::filter( use==1 ) %>%
dplyr::pull( Site )
settings_eval <- list(
sitenames = settings_sims$sitename,
sitenames_siteplots = mylist,
agg = 8,
path_fluxnet2015_d = "~/data/FLUXNET-2015_Tier1/20160128/point-scale_none_1d/original/unpacked/",
path_fluxnet2015_w = "~/data/FLUXNET-2015_Tier1/20160128/point-scale_none_7d/original/unpacked/",
path_fluxnet2015_m = "~/data/FLUXNET-2015_Tier1/20160128/point-scale_none_1m/original/unpacked/",
path_fluxnet2015_y = "~/data/FLUXNET-2015_Tier1/20160128/point-scale_none_1y/original/unpacked/",
path_gepisat_d = "~/data/gepisat/v3_fluxnet2015/daily_gpp/",
benchmark = list( gpp = c("fluxnet2015_NT") ),
remove_premodis = TRUE
)
Get evaluation data (benchmarking data).
filn <- "./obs_eval.Rdata"
if (file.exists(filn)){
load(filn)
} else {
obs_eval <- get_obs_eval(
settings_eval = settings_eval,
settings_sims = settings_sims,
overwrite = TRUE,
light = TRUE,
add_forcing = FALSE
)
save(obs_eval, file = filn)
}
Now run the model with calibrated parameters.
params_modl <- list(
kphio = settings_calib$par_opt[["kphio"]],
soilm_par_a = 1.0,
soilm_par_b = 0.0,
vpdstress_par_a = 0.2,
vpdstress_par_b = 0.2,
vpdstress_par_m = 5
)
mod <- runread_sofun_f(
df_drivers,
params_modl = params_modl,
makecheck = TRUE
) %>%
rename(id = sitename) %>%
unnest(out_sofun)
And finally do the evaluation.
out_eval <- eval_sofun(
mod,
settings_eval,
settings_sims,
obs_eval = obs_eval,
overwrite = TRUE,
light = FALSE
)
## [1] "-----------------------------------"
## [1] "gpp"
## [1] "-----------------------------------"
## [1] "Aggregating model outputs..."
## [1] "Evaluate annual values..."
## [1] "Evaluate monthly values..."
## [1] "Evaluate spatial values..."
## [1] "Evaluate interannual variability..."
## [1] "Evaluate mean seasonal cycle..."
## [1] "Evaluate mean seasonal cycle by climate zones..."
## [1] "Evaluate inter-day variability..."
## [1] "Evaluate mean seasonal cycle by X-day periods..."
## [1] "Evaluate inter-X-day variability..."
## [1] "Done with eval_sofun()."
Print some results.
out_eval$gpp$fluxnet2015$metrics$xdaily_pooled
## # A tibble: 1 x 5
## rsq rmse slope bias nvals
## <dbl> <dbl> <dbl> <dbl> <int>
## 1 0.736 2.23 1.09 -0.172 9569
out_eval$gpp$fluxnet2015$data$xdf %>% rbeni::analyse_modobs2("mod", "obs", type = "heat")
## Loading required package: ggthemes
## Loading required package: RColorBrewer
## $df_metrics
## # A tibble: 10 x 3
## .metric .estimator .estimate
## <chr> <chr> <dbl>
## 1 rmse standard 2.23
## 2 rsq standard 0.736
## 3 mae standard 1.53
## 4 n standard 9569
## 5 slope standard 1.09
## 6 mean_obs standard 4.14
## 7 prmse standard 0.538
## 8 pmae standard 0.369
## 9 bias standard -0.172
## 10 pbias standard -2.89
##
## $gg
##
## $linmod
##
## Call:
## lm(formula = obs ~ mod, data = df)
##
## Coefficients:
## (Intercept) mod
## -0.1742 1.0872
##
##
## $results
## # A tibble: 1 x 6
## rsq rmse mae bias slope n
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.736 2.23 1.53 -0.172 1.09 9569
out_eval$gpp$fluxnet2015$data$ddf %>%
dplyr::filter(sitename=="BE-Vie" & year(date) < 2005) %>%
ggplot(aes(x = date)) +
geom_line(aes(y = obs), col="black") +
geom_line(aes(y = mod), col="red") +
labs(title = "BE-Vie")
out_eval$gpp$fluxnet2015$data$ddf %>%
dplyr::filter(sitename=="AU-Dry" & year(date) > 2010) %>%
ggplot(aes(x = date)) +
geom_line(aes(y = obs), col="black") +
geom_line(aes(y = mod), col="red") +
labs(title = "AU-Dry")
## Warning: Removed 33 rows containing missing values (geom_path).