---
title: "Evaluation of irigation strategies with OptirrigCORE"
output: 
  rmarkdown::html_vignette:
    css: styles/vignette.css
vignette: >
  %\VignetteIndexEntry{Evaluation of irigation strategies with OptirrigCORE}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE, file = 'styles/setup.R'}
rm(list = ls())
gc()
```

## Introduction & objectives

Irrigation management is not only about supplying water, but about deciding **when**,
**how much**, and under which **constraints** water should be applied during the crop cycle.

This vignette extends the minimal **OptirrigCORE** workflow presented in *Get Started with OptirrigCORE*.
Where the *Get Started* vignette deliberately shows the core objects and functions with a very explicit setup,
here we rely on the companion packages **OptirrigTOOLS** and **OptirrigVIEW** to simplify
scenario construction and visualization.

The objective is to focus on the **evaluation and comparison of irrigation strategies** for an irrigated maize crop
under Mediterranean conditions, while keeping the code shorter and easier to read.

Using contrasted calendar-based, rule-based, and split-period strategies, we assess how irrigation timing,
decision rules, and operational constraints affect crop growth, yield, and water-use efficiency over a single growing season.

Results are presented in terms of grain yield (**Y**, t·ha⁻¹), aboveground biomass (**B**, t·ha⁻¹),
soil water reserve (**RU**, %), irrigation inputs (**ΣI**, mm), and total seasonal water input (**ΣP + ΣI**, mm).

The objective is to identify:
- strategies that **limit hydric stress during critical phenological phases** (especially around flowering),
- strategies that offer the best **yield–water compromise** under operational constraints,
- and cases where increasing water supply leads to **diminishing returns**.

## Project setup

A simulation project is set up to represent an irrigated maize crop in 2021 at the PRESTIE site
(Lavalette, Montpellier, France). Climate data come from the Lavalette station and we use the `"CL"` soil preset
shipped with **OptirrigCORE**.

As in the *Get Started* vignette, **OptirrigCORE** remains the simulation engine.
In this vignette, however, we use:
- **OptirrigTOOLS** to build scenario tables with a compact syntax,
- **OptirrigVIEW** to produce ready-to-use multi-panel graphics.

For this soil, the following reference moisture contents are used:
- θ Field Capacity (FC) = 0.30 cm³/cm³
- θ Wilting Point (WP) = 0.17 cm³/cm³
- θ Saturation (SAT) = 0.42 cm³/cm³
- θ RFU limit = 0.21 cm³/cm³
- θ Residual water = 0.04 cm³/cm³

The example relies on bundled datasets and built-in crop and soil presets, which keeps the workflow portable and reproducible.

```{r, 01-project_setup}
library(OptirrigCORE)
library(OptirrigTOOLS)
library(OptirrigVIEW)
```

The following code loads example climate, irrigation, and observation data shipped with the package.
```{r, 01-project_setup_code}
data("MAIZE_21LAVALETTE_clim")
data("MAIZE_21LAVALETTE_irrig")
data("MAIZE_21LAVALETTE_LAI")
data("MAIZE_21LAVALETTE_B")
```

## Minimal model inputs

Each simulation scenario is defined by a minimal set of parameters describing the crop, soil,
simulation period, and climate input. The general structure of these inputs and the base
**OptirrigCORE** workflow are described in detail in the *Get Started with OptirrigCORE* vignette.
Here, instead of manually assembling a flat input list, we use **OptirrigTOOLS** helpers to
generate the scenario object more directly.

### Creation of the input dataset

We start with a baseline scenario without irrigation (rainfed), which will serve 
as a reference to evaluate the effect of irrigation strategies.

Compared with the *Get Started* vignette, the same information is provided here through
`OptirrigTOOLS::create_scenarios()`, which keeps the scenario definition concise while preserving
the exact inputs required by **OptirrigCORE**.

```{r 01-create_model_params}
input <- OptirrigTOOLS::create_scenarios(
  run = list(
    run_id = "Run_1",
    date_start = "01/04/2021",
    date_end = "06/09/2021"
  ),
  inputs = list(
    climate = MAIZE_21LAVALETTE_clim,
    irrigation = MAIZE_21LAVALETTE_irrig
  ),
  crop = list(
    crop = "maize",
    date_sowing = "20/04/2021",
    date_harvest = "06/09/2021"
  ),
  soil = list(
    soil = "CL",
    zmax = 1.2,
    ratio_R_init = 0.7,
    theta_fc = 0.30,
    theta_wp = 0.17,
    theta_sat = 0.42,
    theta_raw = 0.21,
    theta_r = 0.04
  ),
  irrigation = list(
    irrig_mod = 0
  )
)
str(input)
```

### Reference simulation (rainfed maize)

Here we simulate rainfed maize (no irrigation applied).  
For consistency across scenarios, an irrigation calendar may be provided as an input, but it is **ignored** here
because `irrig_mod = 0`.

This baseline scenario allows us to:
- test the proper functioning of the model and inputs,
- observe soil and crop dynamics under dry conditions,
- provide a reference for quantifying the gains associated with irrigated strategies.

The rainfed simulation shows that soil water reserve (**RU**) decreases rapidly during summer as rainfall declines
and crop demand increases. This induces marked water stress from around flowering onward, reducing leaf development,
biomass accumulation, and ultimately yield.

The plot below is produced with **OptirrigVIEW** and combines simulated trajectories with the
available observed **LAI** and **biomass** values for the reference experiment.

```{r, 01-ref_simulation}
outputs <- run_model(input, options = list(log = FALSE, force = TRUE))

plot(
  outputs,
  obs = list(
    LAI = MAIZE_21LAVALETTE_LAI,
    B = MAIZE_21LAVALETTE_B
  ),
  options = list(
    plots = list(
      LAI = list(x = "Date", y = "LAI", title = "LAI", y_lab = "LAI"),
      RU = list(x = "Date", y = "RU", title = "RU", y_lab = "RU (%)"),
      B = list(x = "Date", y = "B", title = "Biomass", y_lab = "Biomass (t/ha)"),
      IRR = list(x = "Date", y = "I1", geom = "point", title = "Irrigation", y_lab = "Irrigation (mm)", filter = function(d) d$I1 > 0)
    ),
    layout = "LAI | RU / B | IRR",
    title = "Reference simulation",
    legend_position = "bottom",
    theme = OptirrigVIEW::theme_optirrig_view(base_size = 11)
  )
)
```

## Defining irrigation strategies

Ten fixed irrigation strategies (*S1–S10*) are evaluated, spanning a wide range of
**water management objectives**, from purely rainfed conditions to intensive,
highly protective irrigation regimes.

The strategies differ along four main axes:

1. **Exposure to water stress**,  
2. **Total water use** (irrigation + rainfall),  
3. **Protection of phenologically sensitive phases**,  
4. **Operational objectives embedded in the rules** (water saving, yield maximization, robustness to constraints).

### Threshold-based irrigation strategies (TBIS)

In this vignette, **TBIS** refers to *threshold-based irrigation strategies*, in which
irrigation decisions are triggered when a state variable crosses a predefined threshold,
most commonly the **soil water reserve (RU)**, but also precipitation indices (**PI**) in some cases.

Once a threshold is reached, irrigation may be applied immediately or modulated by
additional constraints such as:

- fixed or bounded irrigation doses,
- refill targets,
- irrigation turn rules,
- seasonal or window-based water quotas.

These constraints reflect different **management philosophies**:
limiting peak demand, smoothing water use, or prioritizing specific crop stages.

### Irrigation turns and operational flexibility

Some strategies include **irrigation turn management**, reflecting real-world
operational constraints.

- **Strict turns** enforce irrigation only if all conditions are met on the decision day.
- **Delay / flexible turns** allow irrigation to be postponed and applied later, which may
  partially compensate short-term restrictions but can expose the crop to transient stress.

Turn rules therefore influence **stress timing** more than total water volume.

### Multi-period strategies and phenological targeting

Several strategies explicitly modify irrigation rules across the season.
This allows water management to be aligned with **crop phenology**, especially around
**flowering**, which is known to be highly sensitive to water stress in maize.

In this vignette, multi-period strategies are defined using **calendar-based splits**:

- **S9** applies two successive RU thresholds, combined with a July constraint window.
- **S10** combines a split strategy with dose and quota constraints during a critical mid-summer period.

These strategies explicitly test whether **reallocating water in time** can outperform
uniform-season management.

The table below summarizes the different strategies tested in this vignette:

| ID      | Description                | Strat. period(s)        | Constraint period(s) | RU_thrld (%) | RU_target (%) | PI (thrld/days) | Turn mode | Turn days | dose_fix (mm) | dose_min–max (mm) | Quota max (mm) | Quota cst (mm) | Mode     |
| ------- | -------------------------- | ----------------------- | -------------------- | -----------: | ------------: | --------------- | --------- | --------: | ------------: | ----------------: | -------------: | -------------: | -------- |
| **S1**  | Rainfed                    | -                       | -                    |            - |             - | -               | -         |         - |             - |                 - |              - |              - | pluvial  |
| **S2**  | Calendar (file)            | 05/05–08/08             | -                    |            - |             - | -               | -         |         - |             - |                 - |              - |              - | calendar |
| **S3**  | Threshold                  | 05/05–08/08             | -                    |           25 |            75 | -               | -         |         - |            30 |                 - |              - |              - | tbis     |
| **S4**  | Threshold + turn           | 05/05–08/08             | -                    |           50 |            80 | -               | strict    |         7 |            30 |                 - |              - |              - | turn     |
| **S5**  | Deficit + quota            | 05/05–08/08             | -                    |           35 |            60 | -               | -         |         - |            30 |                 - |            400 |              - | tbis     |
| **S6**  | PI + fixed dose            | 05/05–08/08             | -                    |            - |             - | 30 / 15         | strict    |         7 |            20 |                 - |              - |              - | turn     |
| **S7**  | High refill + quota        | 05/05–08/08             | -                    |           75 |           100 | -               | -         |         - |            30 |                 - |            300 |              - | tbis     |
| **S8**  | High refill + turn + quota | 05/05–08/08             | -                    |           75 |           100 | -               | strict    |         7 |            30 |             15–20 |            200 |              - | turn     |
| **S9**  | Two-phase RU               | 05/05–01/07–01/07–08/08 | 01/07–20/07          |        30–70 |         30–70 | -               | delay     |         5 |            20 |                 - |              - |            100 | turn     |
| **S10** | Split strat + July window  | 05/05–10/07–10/07–08/08 | 10/07–20/07          |        35–50 |         75–65 | -               | -         |         - |            30 |             15–20 |            300 |             60 | tbis     |

### Building the input object for all strategies

To simulate all fixed strategies (*S1–S10*), we build a scenario object where each element corresponds
to a specific strategy with its associated parameters. Here again, **OptirrigTOOLS** lets us define
the whole batch compactly instead of assembling each scenario by hand.
```{r, 01-input_strategies}
inputs <- OptirrigTOOLS::create_scenarios(
  run = list(
    run_id     = c("S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10"),
    date_start = "01/04/2021",
    date_end   = "06/09/2021"
  ),
  inputs = list(
    climate = MAIZE_21LAVALETTE_clim,
    irrigation = list(NA, MAIZE_21LAVALETTE_irrig, NA, NA, NA, NA, NA, NA, NA, NA)
  ),
  crop = list(
    crop = "maize",
    date_sowing = "20/04/2021",
    date_harvest = "06/09/2021"
  ),
  soil = list(
    soil = "CL",
    zmax = 1.2,
    ratio_R_init = 80,
    theta_fc = 0.30,
    theta_wp = 0.17,
    theta_sat = 0.42,
    theta_raw = 0.21,
    theta_r = 0.04
  ),
  irrigation = list(
    irrig_mod = c(0, 0, 1, 1, 1, 1, 1, 1, 1, 1),
    irrig_strategy_start = c(
      rep(list("05/05/2021"), 8),
      list(c("05/05/2021", "01/07/2021")),
      list(c("05/05/2021", "01/07/2021"))
    ),
    irrig_strategy_end = c(
      rep(list("08/08/2021"), 8),
      list(c("01/07/2021", "08/08/2021")),
      list(c("01/07/2021", "08/08/2021"))
    ),
    irrig_constraints_start = c(NA, NA, NA, NA, NA, NA, NA, NA, "01/07/2021", "10/07/2021"),
    irrig_constraints_end = c(NA, NA, NA, NA, NA, NA, NA, NA, "20/07/2021", "20/07/2021"),
    RU_thrld = list(NA, NA, 25, 50, 35, NA, 75, 75, list(30, 70), list(35, 50)),
    RU_target = list(NA, NA, 75, 80, 60, NA, 100, 100, list(30, 70), list(75, 65)),
    PI_thrld = c(NA, NA, NA, NA, NA, 30, NA, NA, NA, NA),
    PI_ndays = c(NA, NA, NA, NA, NA, 15, NA, NA, NA, NA),
    WTurn_ndays = c(NA, NA, NA, 7, NA, 7, NA, 7, 5, NA),
    WTurn_mod = c(NA, NA, 0, 1, 0, 1, 0, 1, 2, 0),
    dose_min = c(NA, NA, NA, NA, NA, NA, NA, 15, NA, 15),
    dose_max = c(NA, NA, NA, NA, NA, NA, NA, 20, NA, 20),
    dose_fix = c(NA, NA, 30, 30, 30, 20, 30, 30, 20, 30),
    quota_max = c(NA, NA, NA, NA, 400, NA, 300, 200, NA, 300),
    quota_wind = c(NA, NA, NA, NA, NA, NA, NA, NA, 100, 60)
  ),
  options = list(grid = FALSE, fill_missing = FALSE)
)
```

### Simulation of all strategies

All strategies are simulated in a single call to `run_model()`.
Each row of the scenario object corresponds to a distinct irrigation strategy,
while sharing the same crop, soil, climate, and simulation period.

This approach ensures that observed differences in outputs are attributable
solely to irrigation management choices.

```{r, 01-run_strategies}
outputs <- run_model(
  x = inputs,
  options = list(
    plan = "multicore",
    log = FALSE
  ),
  cfg = load_config()
)
```

## Water and growth dynamics

The figures below show the temporal dynamics of soil water reserve (**RU**),
biomass (**B**), yield (**Y**), and water inputs (rainfall + irrigation).

### Soil water reserve and hydric stress

The simulated trajectories of **RU (%)** clearly separate strategies according to
their exposure to water stress and, importantly, **the timing of stress events**:

- **S1 (rainfed)** experiences prolonged and severe stress, with RU dropping close to zero
  during summer, which is consistent with the strong reduction in leaf development and growth later in the season.
- **Low- to moderate-input strategies** (S2, S3, S6) partially mitigate stress but still allow
  substantial RU depletion during the late vegetative and reproductive phases, with visible stress episodes in mid-summer.
- **High-refill strategies** (S7, S8, S10) maintain RU at higher levels for longer,
  effectively reducing exposure to severe deficits during peak demand.
- **Multi-period strategies** (S9, S10) show structured RU trajectories,
  reflecting deliberate changes in decision rules across the season rather than uniform protection.

Overall, these dynamics suggest that **short stress episodes during phenologically sensitive phases**
(e.g. around flowering) may have a disproportionate impact compared to the seasonal average RU.

### Biomass and yield dynamics

Biomass and yield dynamics broadly mirror the hydric stress patterns:

- Strategies exhibiting pronounced RU drops during mid-summer show reduced growth rates and
  earlier yield plateaus.
- **S8**, despite irrigation, underperforms relative to strategies with comparable seasonal water supply,
  which is consistent with the combined effect of operational constraints
  (turn rules + bounded doses + quota) that can limit responsiveness during peak demand.
- **S3, S4, and S9** reach comparable yields through different decision logics:
  reactive refilling, stricter protection, or temporal reallocation.
- **S10** maintains favorable water status during the most demanding period and achieves
  the highest biomass and yield among tested strategies.

```{r, 01-plot_strategies}
run_ids <- grep("^S", names(outputs), value = TRUE)

plot(
  outputs,
  options = list(
    values = run_ids,
    plots = list(
      LAI = list(x = "Date", y = "LAI", title = "LAI", y_lab = "LAI"),
      RU = list(x = "Date", y = "RU", title = "RU", y_lab = "RU (%)"),
      B = list(x = "Date", y = "B", title = "Biomass", y_lab = "Biomass (t/ha)"),
      IRR = list(
        x = "Date", y = "I1", geom = "point", title = "Irrigation",
        y_lab = "Irrigation (mm)", filter = function(d) d$I1 > 0
      )
    ),
    layout = "LAI | RU / B | IRR",
    title = "Irrigation strategies",
    legend_position = "bottom",
    theme = OptirrigVIEW::theme_optirrig_view(base_size = 11)
  )
)
```

In the previus plots, the separation among strategies is most visible during mid-summer, when evaporative demand peaks and irrigation decisions drive RU trajectories.

## Total Water – Yield relationship

The relationship between total seasonal water input (ΣP + ΣI) and yield (**Y**) highlights
the combined effect of rainfall and irrigation.

> **Note:**  
> The x-axis represents **total water** (rainfall + irrigation).  
> It is therefore normal for total water to exceed irrigation quotas.

### Main patterns

- **S1 (rainfed)** exhibits the lowest yield, confirming the strong impact of water deficit.
- **S6** improves yield with moderate water inputs but does not reach the production plateau.
- **S3, S4, and S9** cluster around similar total water volumes (~540–550 mm) and yields (~12–13 t·ha⁻¹),
  illustrating that **different strategies can converge toward similar outcomes**.
- **S8** consumes comparable water but delivers lower yield, highlighting the potential cost of
  restrictive operational rules when they prevent timely protection during peak demand.
- **S5** achieves high yield with moderate total water, representing a strong **yield–water compromise**
  (high marginal productivity of additional water within this set of strategies).
- **S10** reaches the highest yield, but also among the highest total water inputs.
- **S7**, despite very high water availability, shows limited advantage compared to S10,
  illustrating **diminishing marginal returns** at high water supply.

```{r, 01-water_yield}
library(ggplot2)
df <- do.call(rbind, lapply(names(outputs), function(nm) {
  d <- outputs[[nm]]
  data.frame(
    Scenario = nm,
    Water_mm = sum(pmax(0, d$P), na.rm = TRUE) + sum(pmax(0, d$I1), na.rm = TRUE),
    Y = tail(na.omit(d$Y), 1)
  )
}))

ggplot(df, aes(x = Water_mm, y = Y)) +
  geom_point(size = 3, color = optirrig_view_palette[1], alpha = 0.85) +
  geom_text(aes(label = Scenario), hjust = -0.15, vjust = 0.4, size = 3.5) +
  scale_x_continuous(
    limits = range(df$Water_mm, na.rm = TRUE),
    expand = expansion(mult = c(0.02, 0.05))
  ) +
  labs(
    x = "Total seasonal water (mm) = ΣP + ΣI",
    y = "Yield (t/ha)",
    title = "Yield response to total seasonal water"
  ) +
  theme_optirrig_view(base_size = 13)
```

This plot is useful to distinguish **water amount effects** from **timing / rule effects**, 
since strategies with similar ΣP + ΣI can still achieve different yields.

## Strategy objectives and interpretation

Viewed through the combined lenses of stress exposure, timing, and water use,
the strategies can be grouped by their dominant objectives:

- **Stress acceptance / baseline**: S1  
- **Operational simplicity**: S2  
- **Reactive stress correction**: S3, S6  
- **Stress avoidance at any cost**: S4, S7  
- **Water-use efficiency**: S5  
- **Operationally constrained protection**: S8  
- **Phenology-aware reallocation**: S9  
- **Yield maximization**: S10  

### Interpreting the water–yield relationship as a production function

The relationship between total seasonal water input (ΣP + ΣI) and final yield can be interpreted
as an empirical realization of a **water–yield production function**.

In this representation, each irrigation strategy corresponds to a discrete point on the production surface,
since strategies differ not only in total water supplied but also in the **temporal allocation of water**
and in the operational rules governing irrigation decisions.

As a result, the vertical dispersion observed among strategies with similar total water inputs
(e.g. S5, S8, S9) reflects differences in **water productivity** and proximity to the efficient frontier,
rather than stochastic noise alone.

The concave envelope formed by the upper-performing strategies is consistent with diminishing marginal
returns to additional water once severe stress is largely avoided, while lower-performing strategies
illustrate sub-optimal allocation under comparable seasonal water availability.

```{r, 01-water_yield_schem, echo=FALSE, out.width="80%", fig.align="center"}
knitr::include_graphics("img/FPG.png")
```

## Discussion and conclusions

These simulations reproduce expected soil water dynamics and yield responses to both the amount and timing of irrigation.
In this case study (Mediterranean season, maize, CL soil preset), differences among strategies are primarily governed by
**the timing and severity of hydric stress** relative to **high-demand phases**, rather than total seasonal water alone.

Key takeaways are:

- Yield increases strongly when irrigation prevents severe stress during peak demand, but responses show
  **diminishing returns** once stress is already largely avoided.
- Operational constraints (turn rules, bounded doses, quotas) may reduce performance when they limit the ability
  to respond rapidly during peak demand, even when total seasonal water is comparable (e.g. S8 vs. higher-performing strategies).
- Because total seasonal water includes rainfall (**ΣP + ΣI**), total water can exceed irrigation quotas without contradiction.

Overall, within the tested strategies:
- **S5** typically offers the best yield–water compromise,
- **S10** maximizes yield but requires higher total water inputs,
- strategies like **S8** illustrate how restrictive constraints can penalize yield despite non-negligible seasonal water supply.

In summary, irrigation strategy design here is fundamentally about **managing stress in time**, not simply adding water.
