[ref doc] what is done when converting a crop sequence file (& refyear+kc_pairs per crop files) into an integrated kc pairs VLE parameter for ASCROM model
In the ASCROM model the part responsible for the kcb dynamic (eg. basal crop coefficient) is managed by an instance of the vle.discrete-time.generic/Interpolate
atomic model.
vle.discrete-time.generic/Interpolate
atomic model is a generic interpolation function based on time and value pairs given as parameters at the start of the simulation.
<port name="kcb_params">
<map>
<key name="t0">
<integer>1</integer>
</key>
<key name="pairs">
<set>
<map>
<key name="kcb">
<double>0</double>
</key>
<key name="date">
<integer>0</integer>
</key>
</map>
<map>
<key name="kcb">
<double>0.3</double>
</key>
<key name="date">
<integer>1</integer>
</key>
</map>
</set>
</key>
</map>
</port>
XML representation of an example of the vle.discrete-time.generic/Interpolate parameters (see atomic model reference documentation in VLE package for more details)
As a consequence, for configuring the models using ASCROM, one need to provide a set of date/value pairs corresponding to all the crops to be simulated on a given plot during the simulation.
For practical reasons, in the Shiny applications MFX_X available in this rASCROM R package, we added several intermediate csv data files that allow the user to choose a crop sequence from a set of predefined ones (see data files reference documentation vignette in rASCROM R package). Then the Shiny applications use the information in those files along with a reference year and a set of per crop kc pairs files to generate an integrated sequence of date/value pairs corresponding to all the crops to be simulated.
sequence | padding | startdate | enddate |
---|---|---|---|
F_onion | 0 | 15/4/+0 | 20/7/+0 |
F_beetroot | 0 | 1/8/+0 | 31/10/+0 |
F_tomato | 0 | 15/11/+0 | 31/03/+1 |
F_onion | 0 | 15/4/+1 | 20/7/+1 |
F_beetroot | 0 | 1/8/+1 | 31/10/+1 |
F_tomato | 0 | 15/11/+1 | 31/03/+2 |
date | kc |
---|---|
0 | 0 |
1 | 0.15 |
113 | 0.15 |
196 | 1.05 |
310 | 1.05 |
363 | 0.9 |
364 | 0 |
First step is to use a user defined reference year (in the following example we use: 2015, Nota: 2016 is a leap year) to fully define the sequence dates
sequence | padding | startdate | enddate |
---|---|---|---|
F_onion | 0 | 15/4/2015 | 20/7/2015 |
F_beetroot | 0 | 1/8/2015 | 31/10/2015 |
F_tomato | 0 | 15/11/2015 | 31/03/2016 |
F_onion | 0 | 15/4/2016 | 20/7/2016 |
F_beetroot | 0 | 1/8/2016 | 31/10/2016 |
F_tomato | 0 | 15/11/2016 | 31/03/2017 |
Then the sequence column is used to get all crops involved. Each crop identifier correspond to a reference kc pairs file that is loaded for latter use.
date | kc |
---|---|
0 | 0 |
1 | 0.15 |
18 | 0.15 |
62 | 0.95 |
80 | 0.95 |
89 | 0.65 |
90 | 0 |
date | kc |
---|---|
0 | 0 |
1 | 0.15 |
18 | 0.15 |
39 | 0.95 |
57 | 0.95 |
64 | 0.85 |
65 | 0 |
date | kc |
---|---|
0 | 0 |
1 | 0.15 |
20 | 0.15 |
46 | 1.2 |
73 | 1.2 |
89 | 0.7 |
90 | 0 |
Two separate checking steps are then done to ensure :
Then for each element of the sequence we first compute a padding duration corresponding to the number of days since the previous crop (or the start of simulation for the first crop of the sequence, in the following example we use: 2015-1-1).
We then sequentially integrate these paddings with the pairs duration of the previous crop and the difference between the current crop dates and pairs duration.
sequence | padding | startdate | enddate | dates_duration | pairs_duration | integrated_padding |
---|---|---|---|---|---|---|
F_onion | 104 | 15/4/2015 | 20/7/2015 | 96 | 90 | 104 |
F_beetroot | 12 | 1/8/2015 | 31/10/2015 | 91 | 65 | 212 |
F_tomato | 15 | 15/11/2015 | 31/03/2016 | 137 | 90 | 318 |
F_onion | 15 | 15/4/2016 | 20/7/2016 | 96 | 90 | 470 |
F_beetroot | 12 | 1/8/2016 | 31/10/2016 | 91 | 65 | 578 |
F_tomato | 15 | 15/11/2016 | 31/03/2017 | 136 | 90 | 684 |
Finally these integrated padding are used to shift all the dates when concatenating the individual crop reference kc pairs.
date | kcb | calendar_dates |
---|---|---|
104 | 0 | 15/04/2015 |
105 | 0.15 | |
122 | 0.15 | |
166 | 0.95 | |
184 | 0.95 | |
193 | 0.65 | |
194 | 0 | |
212 | 0 | 01/08/2015 |
213 | 0.15 | |
230 | 0.15 | |
251 | 0.95 | |
269 | 0.95 | |
276 | 0.85 | |
277 | 0 | |
318 | 0 | 15/11/2015 |
319 | 0.15 | |
338 | 0.15 | |
364 | 1.2 | |
391 | 1.2 | |
407 | 0.7 | |
408 | 0 | |
470 | 0 | 15/04/2016 |
471 | 0.15 | |
488 | 0.15 | |
532 | 0.95 | |
550 | 0.95 | |
559 | 0.65 | |
560 | 0 | |
578 | 0 | 01/08/2016 |
579 | 0.15 | |
596 | 0.15 | |
617 | 0.95 | |
635 | 0.95 | |
642 | 0.85 | |
643 | 0 | |
684 | 0 | 15/11/2016 |
685 | 0.15 | |
704 | 0.15 | |
730 | 1.2 | |
757 | 1.2 | |
773 | 0.7 | |
774 | 0 |
.generateKcPairs
#> function (RvleObj, condPortName, T0, crop_seq, kc_list, debut_sim,
#> clim_corr = FALSE, clim_filepath = "", h = 0, dbgLog = FALSE)
#> {
#> error_kc <- FALSE
#> kc_params <- .getSamplePair(RvleObj, condPortName, T0)
#> sample_kc_pair <- kc_params$pairs[[1]]
#> kc_pair_index <- 1
#> padding <- 0
#> dureeDates <- dureePaires <- vector(mode = "numeric", length = nrow(crop_seq))
#> for (idseq_index in 1:nrow(crop_seq)) {
#> if (idseq_index == 1) {
#> crop_seq$padding[idseq_index] <- as.integer(chron(crop_seq$startdate[idseq_index],
#> format = c(dates = "d/m/Y")) - chron(debut_sim,
#> format = c(dates = "Y-m-d")))
#> }
#> else {
#> crop_seq$padding[idseq_index] <- as.integer(chron(crop_seq$startdate[idseq_index],
#> format = c(dates = "d/m/Y")) - chron(crop_seq$enddate[idseq_index -
#> 1], format = c(dates = "d/m/Y")))
#> }
#> {
#> if (crop_seq$padding[idseq_index] < 1) {
#> if (idseq_index == 1) {
#> cat(file = stderr(), "Attention date de debut de la sequence avant le debut de simulation\n")
#> cat(file = stderr(), as.character(chron(debut_sim,
#> format = c(dates = "Y-m-d"), out.format = c(dates = "d/m/Y"))),
#> " < ", as.character(chron(crop_seq$startdate[idseq_index],
#> format = c(dates = "d/m/Y"))), "\n")
#> }
#> else {
#> cat(file = stderr(), "Attention date de debut avant date de fin du precedent\n")
#> cat(file = stderr(), as.character(chron(crop_seq$startdate[idseq_index],
#> format = c(dates = "d/m/Y"))), " < ", as.character(chron(crop_seq$enddate[idseq_index -
#> 1], format = c(dates = "d/m/Y"))), "\n",
#> idseq_index, " vs ", idseq_index - 1, " (element de la sequence)\n")
#> }
#> error_kc <- TRUE
#> }
#> dureeDates[idseq_index] <- as.integer(chron(crop_seq$enddate[idseq_index],
#> format = c(dates = "d/m/Y")) - chron(crop_seq$startdate[idseq_index],
#> format = c(dates = "d/m/Y")))
#> dureePaires[idseq_index] <- max(kc_list[[crop_seq$sequence[idseq_index]]]$date)
#> if (dureeDates[idseq_index] < dureePaires[idseq_index]) {
#> cat(file = stderr(), "Attention durees plus courte entre les dates du fichier sequence et la duree de cycle du fichier de kc\n")
#> cat(file = stderr(), idseq_index, "eme element de la sequence, ID:",
#> crop_seq$sequence[idseq_index], "\n")
#> cat(file = stderr(), dureeDates[idseq_index],
#> "(dates sequence) != ", dureePaires[idseq_index],
#> "(duree paires)\n")
#> error_kc <- TRUE
#> }
#> }
#> extra_seq_pairs_delay <- ifelse(idseq_index == 1, 0,
#> dureeDates[idseq_index - 1] - dureePaires[idseq_index -
#> 1])
#> padding <- padding + crop_seq$padding[idseq_index] +
#> extra_seq_pairs_delay
#> for (idpair_index in 1:nrow(kc_list[[crop_seq$sequence[idseq_index]]])) {
#> kc_params$pairs[[kc_pair_index]] <- sample_kc_pair
#> kc_params$pairs[[kc_pair_index]]$kcb <- kc_list[[crop_seq$sequence[idseq_index]]][idpair_index,
#> ]$kc
#> kc_params$pairs[[kc_pair_index]]$date <- as.integer(kc_list[[crop_seq$sequence[idseq_index]]][idpair_index,
#> ]$date + padding)
#> kc_pair_index <- kc_pair_index + 1
#> }
#> padding <- padding + max(kc_list[[crop_seq$sequence[idseq_index]]]$date)
#> }
#> if (clim_corr & file.exists(clim_filepath)) {
#> if (dbgLog)
#> cat(file = stderr(), "Calcul de correction climatique sur les valeurs de kc\n")
#> weatherdata <- read_delim(clim_filepath, delim = " ",
#> col_types = cols_only(annee = col_integer(), mois = col_integer(),
#> jour = col_integer(), RHmin = col_double(), u2 = col_double()))
#> kc_params <- .kc_climate_correction(kc_params, weatherdata,
#> debut_sim, h, dbgLog)
#> }
#> else {
#> cat(file = stderr(), "Pas de correction climatique sur les valeurs de kc\n")
#> }
#> return(list(KC_PARAMS = kc_params, KC_SEQ = crop_seq, ERROR_KC = error_kc))
#> }
#> <bytecode: 0x560da5e1b2d0>