diff --git a/DESCRIPTION b/DESCRIPTION
index a3f44ba4304c2df39e5b26a1f950bb3aa509daae..dc992881e5161950faf7456c729df520a7a232de 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -19,7 +19,7 @@ URL: https://airgriwrm.g-eau.fr/,
 BugReports: https://github.com/inrae/airGRiwrm/issues
 Depends:
     airGR (>= 1.7.0),
-    R (>= 2.10)
+    R (>= 3.5)
 Imports:
     DiagrammeR,
     dplyr,
diff --git a/NAMESPACE b/NAMESPACE
index 2117129665dfac85f6d3978cda702541e67292c5..a6e3b9618b3e40ac965d2462cf710b9d5b24c35a 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -38,9 +38,12 @@ export(RunModel)
 export(getNoSD_Ids)
 export(getSD_Ids)
 export(isNodeDownstream)
+export(plot.Qm3s)
 import(airGR)
 importFrom(grDevices,rainbow)
 importFrom(graphics,matplot)
 importFrom(graphics,par)
 importFrom(graphics,plot)
 importFrom(graphics,title)
+importFrom(utils,read.table)
+importFrom(utils,tail)
diff --git a/R/Calibration.GRiwrmInputsModel.R b/R/Calibration.GRiwrmInputsModel.R
index 1924a775093a78c6d98b945ffc2c2af30f0ce171..f4671e11d5bcc9e480eb6d6501a5334bed607d36 100644
--- a/R/Calibration.GRiwrmInputsModel.R
+++ b/R/Calibration.GRiwrmInputsModel.R
@@ -36,7 +36,7 @@ Calibration.GRiwrmInputsModel <- function(InputsModel,
 
   for(id in gaugedIds) {
     IM <- InputsModel[[id]]
-    message("Calibration.GRiwrmInputsModel: Treating sub-basin ", id, "...")
+    message("Calibration.GRiwrmInputsModel: Processing sub-basin ", id, "...")
 
     if (inherits(InputsCrit[[id]], "InputsCritLavenneFunction")) {
       IC <- getInputsCrit_Lavenne(id, OutputsModel, InputsCrit)
@@ -54,7 +54,7 @@ Calibration.GRiwrmInputsModel <- function(InputsModel,
       IM$FUN_MOD <- "RunModel_Ungauged"
       attr(RunOptions[[id]], "GRiwrmRunOptions") <- l$RunOptions
     } else {
-      if (useUpstreamQsim && any(IM$UpstreamIsRunoff)) {
+      if (useUpstreamQsim && any(IM$UpstreamIsModeled)) {
         # Update InputsModel$Qupstream with simulated upstream flows
         IM <- UpdateQsimUpstream(IM, RunOptions[[id]], OutputsModel)
       }
@@ -188,13 +188,13 @@ updateParameters4Ungauged <- function(GaugedId,
   g2 <- griwrm[griwrm$donor == GaugedId,]
   upIds2 <- g2$id[!g2$id %in% g2$down]
   for (id in upIds2) {
-    if(useUpstreamQsim && any(InputsModel[[id]]$UpstreamIsRunoff)) {
+    if(useUpstreamQsim && any(InputsModel[[id]]$UpstreamIsModeled)) {
       # Update InputsModel$Qupstream with simulated upstream flows
       InputsModel[[id]] <- UpdateQsimUpstream(InputsModel[[id]],
                                               RunOptions[[id]],
                                               OutputsModel)
-      InputsModel[[id]]$UpstreamIsRunoff <-
-        rep(FALSE, length(InputsModel[[id]]$UpstreamIsRunoff))
+      InputsModel[[id]]$UpstreamIsModeled <-
+        rep(FALSE, length(InputsModel[[id]]$UpstreamIsModeled))
     }
   }
 
diff --git a/R/CreateController.R b/R/CreateController.R
index c1fe654023c6eb57a2ca05916b9c1a0f5ee0a0ff..4079240e35f642e580f9cdc11e2d7f1a743b17d3 100644
--- a/R/CreateController.R
+++ b/R/CreateController.R
@@ -26,40 +26,20 @@
 #' - `FUN` [function]: controller logic which calculates `U` from `Y`
 #' @export
 #'
-#' @examples
-#' # First create a Supervisor from a model
-#' data(Severn)
-#' nodes <- Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")]
-#' nodes$model <- "RunModel_GR4J"
-#' griwrm <- CreateGRiwrm(nodes,
-#'                  list(id = "gauge_id",
-#'                       down = "downstream_id",
-#'                       length = "distance_downstream"))
-#' BasinsObs <- Severn$BasinsObs
-#' DatesR <- BasinsObs[[1]]$DatesR
-#' PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
-#' PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
-#' Qobs <- cbind(sapply(BasinsObs, function(x) {x$discharge_spec}))
-#' Precip <- ConvertMeteoSD(griwrm, PrecipTot)
-#' PotEvap <- ConvertMeteoSD(griwrm, PotEvapTot)
-#' InputsModel <- CreateInputsModel(griwrm, DatesR, Precip, PotEvap, Qobs)
-#' sv <- CreateSupervisor(InputsModel)
-#'
-#' # A controller which usually releases 0.1 m3/s and provides
-#' # extra release if the downstream flow is below 0.5 m3/s
-#' logicDamRelease <- function(Y) max(0.5 - Y[1], 0.1)
-#' CreateController(sv, "DamRelease", Y = c("54001"), U = c("54095"), FUN = logicDamRelease)
+#' @example man-examples/RunModel.Supervisor.R
 CreateController <- function(supervisor, ctrl.id, Y, U, FUN){
 
-  if(!is.character(ctrl.id)) stop("Parameter `ctrl.id` should be character")
+  if (!is.character(ctrl.id)) stop("Parameter `ctrl.id` should be character")
+  if (length(ctrl.id) != 1) stop("Parameter `ctrl.id` should be of length 1")
+  stopifnot(is.Supervisor(supervisor))
 
   FUN <- match.fun(FUN)
 
   ctrlr <- list(
     id = ctrl.id,
-    U = CreateControl(U),
+    U = CreateControl(U, supervisor, TRUE),
     Unames = U,
-    Y = CreateControl(Y),
+    Y = CreateControl(Y, supervisor, FALSE),
     Ynames = Y,
     FUN = FUN
   )
@@ -87,9 +67,19 @@ CreateController <- function(supervisor, ctrl.id, Y, U, FUN){
 #' @examples
 #' # For pointing the discharge at the oulet of basins "54095" and "54002"
 #' CreateControl(c("54095", "54002"))
-CreateControl <- function(locations) {
-  if(!is.character(locations)) {
-    stop("Parameter `locations` should be character")
+CreateControl <- function(locations, sv, isU) {
+  if (!is.character(locations)) {
+    stop("Parameters `Y` and `U` should be character")
+  }
+  if (isU) {
+    if (!all(locations %in% sv$griwrm4U$id)) {
+      stop("Ids defined in `U` must be chosen from DirectInjection and Diversion nodes: ",
+           paste(sv$griwrm4U$id, collapse = ", "))
+    }
+  } else {
+    if (!all(locations %in% sv$griwrm$id)) {
+      stop("Ids defined in `Y` must be chosen from available Ids in the GRiwrm object")
+    }
   }
   m <- matrix(NA, ncol = length(locations), nrow = 0)
   return(m)
diff --git a/R/CreateGRiwrm.R b/R/CreateGRiwrm.R
index 83cf2672d10e128e72558c0440d090f24ea0db4d..2c46b0ef1f5a829609038ca96cdb78198c106022 100644
--- a/R/CreateGRiwrm.R
+++ b/R/CreateGRiwrm.R
@@ -17,11 +17,16 @@
 #'
 #' * One of the hydrological models available in the *airGR* package defined by its
 #' `RunModel` function (i.e.: `RunModel_GR4J`, `RunModel_GR5HCemaneige`...)
-#' * `NA` for injecting (or abstracting) a flow time series at the location of the node
-#' (direct flow injection)
 #' * `Ungauged` for an ungauged node. The sub-basin inherits hydrological model and
 #' parameters from a "donor" sub-basin. By default the donor is the first gauged
 #' node at downstream
+#' * `NA` for injecting (or abstracting) a flow time series at the location of the node
+#' (direct flow injection)
+#' * `Diversion` for abstracting a flow time series from an existing node transfer it
+#' to another node. As a `Diversion` is attached to an existing node, this node is
+#' then described with 2 lines: one for the hydrological model and another one for the
+#' diversion
+#'
 #'
 #' @param db [data.frame] description of the network (See details)
 #' @param cols [list] or [vector] columns of `db`. By default, mandatory column
@@ -131,7 +136,7 @@ getNodeRanking <- function(griwrm) {
     stop("getNodeRanking: griwrm argument should be of class GRiwrm")
   }
   # Remove upstream nodes without model (direct flow connections)
-  griwrm <- griwrm[!is.na(griwrm$model),]
+  griwrm <- griwrm[!is.na(griwrm$model), ]
   # Rank 1
   rank <- setdiff(griwrm$id, griwrm$down)
   ranking <- rank
@@ -149,19 +154,69 @@ getNodeRanking <- function(griwrm) {
 
 
 checkNetworkConsistency <- function(db) {
-  if(sum(is.na(db$down)) != 1 | sum(is.na(db$length)) != 1) {
-    stop("One and only one node must have 'NA' in columns 'down' and 'length")
+  db2 <- db[getDiversionRows(db, TRUE), ]
+  if (any(duplicated(db2$id))) {
+    stop("Duplicated nodes detected: ",
+         paste(db2$id[duplicated(db2$id)], collapse = "\n"),
+         "\nNodes `id` must be unique (except for `Diversion` nodes)")
   }
-  if(which(is.na(db$down)) != which(is.na(db$length))) {
-    stop("The node with 'down = NA' must be the same as the one with 'length = NA'")
+  if (sum(is.na(db$down)) == 0) {
+    stop("At least one node must be a network downstream node",
+      " specified by 'down = NA'")
   }
   sapply(db$down[!is.na(db$down)], function(x) {
-    if(!(x %in% db$id)) {
+    if (!(x %in% db$id)) {
       stop("The 'down' id ", x, " is not found in the 'id' column")
     }
   })
+  db3 <- db2[!is.na(db2$model), ]
+  sapply(db$id[getDiversionRows(db)], function(x) {
+    i <- which(db$id == x & db$model == "Diversion")[1]
+    if (length(which(db3$id == x)) != 1) {
+      nodeError(db[i, ],
+                "A Diversion node must have the same `id` of one (and only one) node with a model")
+    }
+    if (length(unique(db$down[db$id == x])) != 2) {
+      nodeError(db[i, ], paste(
+        "The downstream node of a Diversion node must be different",
+        "than the downstream node of the node is attached to"))
+    }
+  })
+  apply(db, 1, checkNode, simplify = FALSE)
 }
 
+checkNode <- function(node) {
+  node <- as.list(node)
+  if (!is.na(node$model)) {
+    if (node$model == "Diversion") {
+      if (!is.na(node$area)) {
+        nodeError(node, "A Diversion node must have its area equal to `NA`")
+      }
+    } else if (length(grep("RunModel_GR", node$model)) > 0 & is.na(node$area)) {
+      # TODO This test should be extended to airGRplus models
+      nodeError(node, "A node using an hydrological model must have a numeric area")
+    }
+  }
+  if (is.na(node$down) & !is.na(node$length)) {
+    nodeError(node, "A downstream end node defined by `down=NA` must have `length=NA`")
+  }
+  if (is.na(node$length) & !is.na(node$down)) {
+    nodeError(node, "A node with a defined downstream node must have a numeric `length`")
+  }
+}
+
+displayNodeDetails <- function(node) {
+  s <- sapply(names(node), function(x) {
+    sprintf("%s: %s", x, node[x])
+  })
+  paste("Error on the node:",
+        paste(s, collapse = "\n"),
+        sep = "\n")
+}
+
+nodeError <- function(node, s) {
+  stop(displayNodeDetails(node), "\n", s)
+}
 
 #' Get the Id of the nearest gauged model at downstream
 #'
@@ -172,12 +227,44 @@ checkNetworkConsistency <- function(db) {
 #'
 #' @noRd
 getGaugedId <- function(id, griwrm) {
-  if(!is.na(griwrm$model[griwrm$id == id]) & griwrm$model[griwrm$id == id] != "Ungauged") {
+  griwrm <- griwrm[getDiversionRows(griwrm, TRUE), ]
+  if (!is.na(griwrm$model[griwrm$id == id]) &
+    griwrm$model[griwrm$id == id] != "Ungauged") {
     return(id)
-  } else if(!is.na(griwrm$down[griwrm$id == id])){
+  } else if (!is.na(griwrm$down[griwrm$id == id])) {
     return(getGaugedId(griwrm$down[griwrm$id == id], griwrm))
   } else {
-    stop("The model of the downstream node of a network cannot be `NA` or \"Ungauged\"")
+    stop("The model of the downstream node of a network",
+      " cannot be `NA` or \"Ungauged\"")
   }
 }
 
+getDiversionRows <- function(griwrm, inverse = FALSE) {
+
+  rows <- which(!is.na(griwrm$model) & griwrm$model == "Diversion")
+  if (inverse) {
+    if(length(rows) == 0) {
+      rows <- seq.int(nrow(griwrm))
+    } else {
+      rows <- setdiff(seq.int(nrow(griwrm)), rows)
+    }
+  }
+  return(rows)
+}
+
+getNodeProperties <- function(id, griwrm) {
+  upstreamIds <- griwrm$id[!griwrm$id %in% griwrm$down]
+  gaugedIds <- griwrm$id[!is.na(griwrm$model) & griwrm$model != "Ungauged"]
+  divertedIds <- griwrm$id[!is.na(griwrm$model) & griwrm$model == "Diversion"]
+  p <- list(
+    position = ifelse(id %in% upstreamIds, "Upstream", "Intermediate"),
+    hydrology = ifelse(id %in% gaugedIds, "Gauged",
+                       ifelse(is.na(griwrm$model[griwrm$id == id]),
+                              "DirectInjection",
+                              "Ungauged"))
+  )
+  p$Upstream <- p$position == "Upstream"
+  p$DirectInjection = p$hydrology == "DirectInjection"
+  p$Diversion = id %in% divertedIds
+  return(p)
+}
diff --git a/R/CreateInputsCrit.GRiwrmInputsModel.R b/R/CreateInputsCrit.GRiwrmInputsModel.R
index 55394a1e20449f443256372a1746cf1456918cd9..b0eff5ba007792f48a33da26e5fd67e67cae16bd 100644
--- a/R/CreateInputsCrit.GRiwrmInputsModel.R
+++ b/R/CreateInputsCrit.GRiwrmInputsModel.R
@@ -1,5 +1,6 @@
 #' @rdname CreateInputsCrit
 #' @import airGR
+#' @importFrom utils tail read.table
 #' @export
 CreateInputsCrit.GRiwrmInputsModel <- function(InputsModel,
                                                FUN_CRIT = ErrorCrit_NSE,
diff --git a/R/CreateInputsModel.GRiwrm.R b/R/CreateInputsModel.GRiwrm.R
index db34acbbe7c3464f0eaec69fd20cddcf6f8ec031..557ae31009ebe931e61a1c94609bc9bb413625ec 100644
--- a/R/CreateInputsModel.GRiwrm.R
+++ b/R/CreateInputsModel.GRiwrm.R
@@ -2,37 +2,78 @@
 #'
 #' @param x \[GRiwrm object\] diagram of the semi-distributed model (See [CreateGRiwrm])
 #' @param DatesR [POSIXt] vector of dates
-#' @param Precip (optional) [matrix] or [data.frame] frame of numeric containing precipitation in \[mm per time step\]. Column names correspond to node IDs
-#' @param PotEvap (optional) [matrix] or [data.frame] frame of numeric containing potential evaporation \[mm per time step\]. Column names correspond to node IDs
-#' @param Qobs (optional) [matrix] or [data.frame] frame of numeric containing observed flows in \[mm per time step\]. Column names correspond to node IDs
-#' @param PrecipScale (optional) named [vector] of [logical] indicating if the mean of the precipitation interpolated on the elevation layers must be kept or not, required to create CemaNeige module inputs, default `TRUE` (the mean of the precipitation is kept to the original value)
-#' @param TempMean (optional) [matrix] or [data.frame] of time series of mean air temperature \[°C\], required to create the CemaNeige module inputs
-#' @param TempMin (optional) [matrix] or [data.frame] of time series of minimum air temperature \[°C\], possibly used to create the CemaNeige module inputs
-#' @param TempMax (optional) [matrix] or [data.frame] of time series of maximum air temperature \[°C\], possibly used to create the CemaNeige module inputs
-#' @param ZInputs  (optional) named [vector] of [numeric] giving the mean elevation of the Precip and Temp series (before extrapolation) \[m\], possibly used to create the CemaNeige module input
-#' @param HypsoData	(optional) [matrix] or [data.frame] containing 101 [numeric] rows: min, q01 to q99 and max of catchment elevation distribution \[m\], if not defined a single elevation is used for CemaNeige
-#' @param NLayers (optional) named [vector] of [numeric] integer giving the number of elevation layers requested [-], required to create CemaNeige module inputs, default=5
+#' @param Precip (optional) [matrix] or [data.frame] of [numeric] containing
+#'        precipitation in \[mm per time step\]. Column names correspond to node IDs
+#' @param PotEvap (optional) [matrix] or [data.frame] of [numeric] containing
+#'        potential evaporation \[mm per time step\]. Column names correspond to node IDs
+#' @param Qobs (optional) [matrix] or [data.frame] of [numeric] containing
+#'        observed flows. It must be provided only for nodes of type "Direct
+#'        injection" and "Diversion". See [CreateGRiwrm] for
+#'        details about these node types. Unit is \[mm per time step\] for nodes
+#'        with an area, and \[m3 per time step\] for nodes with `area=NA`.
+#'        Column names correspond to node IDs. Negative flows are abstracted from
+#'        the model and positive flows are injected to the model
+#' @param Qmin (optional) [matrix] or [data.frame] of [numeric] containing
+#'        minimum flows to let downstream of a node with a Diversion \[m3 per
+#'        time step\]. Default is zero. Column names correspond to node IDs
+#' @param PrecipScale (optional) named [vector] of [logical] indicating if the
+#'        mean of the precipitation interpolated on the elevation layers must be
+#'        kept or not, required to create CemaNeige module inputs, default `TRUE`
+#'        (the mean of the precipitation is kept to the original value)
+#' @param TempMean (optional) [matrix] or [data.frame] of time series of mean
+#'        air temperature \[°C\], required to create the CemaNeige module inputs
+#' @param TempMin (optional) [matrix] or [data.frame] of time series of minimum
+#'        air temperature \[°C\], possibly used to create the CemaNeige module inputs
+#' @param TempMax (optional) [matrix] or [data.frame] of time series of maximum
+#'        air temperature \[°C\], possibly used to create the CemaNeige module inputs
+#' @param ZInputs  (optional) named [vector] of [numeric] giving the mean
+#'        elevation of the Precip and Temp series (before extrapolation) \[m\],
+#'        possibly used to create the CemaNeige module input
+#' @param HypsoData	(optional) [matrix] or [data.frame] containing 101 [numeric]
+#'        rows: min, q01 to q99 and max of catchment elevation distribution \[m\],
+#'        if not defined a single elevation is used for CemaNeige
+#' @param NLayers (optional) named [vector] of [numeric] integer giving the number
+#'        of elevation layers requested [-], required to create CemaNeige module
+#'        inputs, default=5
 #' @param ... used for compatibility with S3 methods
 #'
-#' @details Meteorological data are needed for the nodes of the network that represent a catchment simulated by a rainfall-runoff model. Instead of [airGR::CreateInputsModel] that has [numeric] [vector] as time series inputs, this function uses [matrix] or [data.frame] with the id of the sub-catchment as column names. For single values (`ZInputs` or `NLayers`), the function requires named [vector] with the id of the sub-catchment as name item. If an argument is optional, only the column or the named item has to be provided.
+#' @details Meteorological data are needed for the nodes of the network that
+#' represent a catchment simulated by a rainfall-runoff model. Instead of
+#' [airGR::CreateInputsModel] that has [numeric] [vector] as time series inputs,
+#' this function uses [matrix] or [data.frame] with the id of the sub-catchment
+#' as column names. For single values (`ZInputs` or `NLayers`), the function
+#' requires named [vector] with the id of the sub-catchment as name item. If an
+#' argument is optional, only the column or the named item has to be provided.
 #'
 #' See [airGR::CreateInputsModel] documentation for details concerning each input.
 #'
-#' @return A \emph{GRiwrmInputsModel} object which is a list of \emph{InputsModel} objects created by [airGR::CreateInputsModel] with one item per modeled sub-catchment.
+#' Number of rows of `Precip`, `PotEvap`, `Qobs`, `Qmin`, `TempMean`, `TempMin`,
+#' `TempMax` must be the same of the length of `DatesR` (each row corresponds to
+#' a time step defined in `DatesR`).
+#'
+#' For example of use of Direct Injection nodes, see vignettes
+#' "V03_Open-loop_influenced_flow" and "V04_Closed-loop_regulated_withdrawal".
+#'
+#' For example of use of Diversion nodes, see example below and vignette
+#' "V06_Modelling_regulated_diversion".
+#'
+#' @return A \emph{GRiwrmInputsModel} object which is a list of \emph{InputsModel}
+#' objects created by [airGR::CreateInputsModel] with one item per modeled sub-catchment.
 #' @export
-#' @inherit RunModel.GRiwrmInputsModel return examples
+#' @example man-examples/RunModel.GRiwrmInputsModel.R
 #'
 CreateInputsModel.GRiwrm <- function(x, DatesR,
                                      Precip = NULL,
                                      PotEvap = NULL,
                                      Qobs = NULL,
+                                     Qmin = NULL,
                                      PrecipScale = TRUE,
                                      TempMean = NULL, TempMin = NULL,
                                      TempMax = NULL, ZInputs = NULL,
                                      HypsoData = NULL, NLayers = 5, ...) {
 
   # Check and format inputs
-  varNames <- c("Precip", "PotEvap", "TempMean", "Qobs",
+  varNames <- c("Precip", "PotEvap", "TempMean", "Qobs", "Qmin",
                 "TempMin", "TempMax", "ZInputs", "HypsoData", "NLayers")
   names(varNames) <- varNames
   lapply(varNames, function(varName) {
@@ -51,17 +92,32 @@ CreateInputsModel.GRiwrm <- function(x, DatesR,
           ))
         }
         if (!varName %in% c("ZInputs", "NLayers", "HypsoData") && nrow(v) != length(DatesR)) {
-          stop("'%s' number of rows and the length of 'DatesR' must be equal",
-               varName)
+          stop(sprintf(
+            "'%s' number of rows and the length of 'DatesR' must be equal",
+             varName
+          ))
+        }
+        if (varName %in% c("Precip", "PotEvap", "Qmin")) {
+          if (any(is.na(v))) {
+            stop(sprintf(
+              "`NA` values detected in '%s'. Missing values are not allowed in InputsModel",
+              varName
+            ))
+          }
+          if (any(v < 0)) {
+            stop(sprintf(
+              "'%s' values must be positive or nul. Missing values are not allowed in InputsModel",
+              varName
+            ))
+          }
         }
-
       } else if (!varName %in% c("ZInputs", "NLayers")) {
         stop(sprintf("'%s' must be a matrix or a data.frame", varName))
       }
     }
   })
 
-  directFlowIds <- x$id[is.na(x$model)]
+  directFlowIds <- x$id[is.na(x$model) | x$model == "Diversion"]
   if (length(directFlowIds) > 0) {
     err <- FALSE
     if (is.null(Qobs)) {
@@ -69,17 +125,63 @@ CreateInputsModel.GRiwrm <- function(x, DatesR,
     } else {
       Qobs <- as.matrix(Qobs)
       if (is.null(colnames(Qobs))) {
-      err <- TRUE
+        err <- TRUE
       } else if (!all(directFlowIds %in% colnames(Qobs))) {
-      err <- TRUE
+        err <- TRUE
       }
     }
     if (err) stop(sprintf("'Qobs' column names must at least contain %s", paste(directFlowIds, collapse = ", ")))
   }
+  if (!all(colnames(Qobs) %in% directFlowIds)) {
+    stop("The following columns in 'Qobs' don't match with ",
+         "Direction Injection or Diversion nodes: ",
+         paste(setdiff(colnames(Qobs), directFlowIds), collapse = ", "))
+    Qobs <- Qobs[directFlowIds, ]
+  }
+  diversionRows <- getDiversionRows(x)
+  if (length(diversionRows) > 0) {
+    warn <- FALSE
+    if (is.null(Qmin)) {
+      warn <- TRUE
+    } else {
+      Qmin <- as.matrix(Qmin)
+      if (!all(colnames(Qmin) %in% x$id[diversionRows])) {
+        stop(paste(
+          "'Qmin' contains columns that does not match with IDs of Diversion nodes:\n",
+          setdiff(colnames(Qmin), x$id[diversionRows])
+        ))
+      }
+      if (is.null(colnames(Qmin))) {
+        warn <- TRUE
+      } else if (!all(x$id[diversionRows] %in% colnames(Qmin))) {
+        warn <- TRUE
+      }
+      if (any(is.na(Qmin))) {
+        stop("`NA` values are note allowed in 'Qmin'")
+      }
+    }
+    if (warn) {
+      warning(
+        sprintf(
+          "'Qmin' would include the following columns %s.\n Zero values are applied by default.",
+          paste(directFlowIds, collapse = ", ")
+        )
+      )
+    }
+    # Qmin completion for Diversion nodes with default zero values
+    Qmin0 <- matrix(0, nrow = length(DatesR), ncol = length(diversionRows))
+    colnames(Qmin0) <- x$id[diversionRows]
+    if (is.null(Qmin)) {
+      Qmin <- Qmin0
+    } else {
+      Qmin0[, colnames(Qmin)] <- Qmin
+      Qmin <- Qmin0
+    }
+  }
 
   InputsModel <- CreateEmptyGRiwrmInputsModel(x)
 
-  # Qobs completion
+  # Qobs completion for at least filling Qupstream of all nodes by zeros
   Qobs0 <- matrix(0, nrow = length(DatesR), ncol = nrow(x))
   colnames(Qobs0) <- x$id
   if (is.null(Qobs)) {
@@ -90,11 +192,7 @@ CreateInputsModel.GRiwrm <- function(x, DatesR,
   }
 
   for(id in getNodeRanking(x)) {
-    message("CreateInputsModel.GRiwrm: Treating sub-basin ", id, "...")
-    if (x$area[x$id == id] > 0 && any(Qobs[, id] < 0, na.rm = TRUE)) {
-      stop(sprintf("Negative flow found in 'Qobs[, \"%s\"]'. ", id),
-           "Catchment flow can't be negative, use `NA` for flow data gaps.")
-    }
+    message("CreateInputsModel.GRiwrm: Processing sub-basin ", id, "...")
 
     InputsModel[[id]] <-
       CreateOneGRiwrmInputsModel(id = id,
@@ -109,7 +207,8 @@ CreateInputsModel.GRiwrm <- function(x, DatesR,
                                  ZInputs = getInputBV(ZInputs, id),
                                  HypsoData = getInputBV(HypsoData, id),
                                  NLayers = getInputBV(NLayers, id, 5),
-                                 Qobs = Qobs
+                                 Qobs = Qobs,
+                                 Qmin = getInputBV(Qmin, id)
                                  )
   }
   attr(InputsModel, "TimeStep") <- getModelTimeStep(InputsModel)
@@ -145,24 +244,39 @@ CreateEmptyGRiwrmInputsModel <- function(griwrm) {
 #'
 #' @return \emph{InputsModel} object for one.
 #' @noRd
-CreateOneGRiwrmInputsModel <- function(id, griwrm, ..., Qobs) {
+CreateOneGRiwrmInputsModel <- function(id, griwrm, ..., Qobs, Qmin) {
+  hasDiversion <- getNodeProperties(id, griwrm)$Diversion
+  if (hasDiversion) {
+    rowDiv <- which(griwrm$id == id & griwrm$model == "Diversion")
+    diversionOutlet <- griwrm$down[rowDiv]
+    griwrm <- griwrm[-rowDiv, ]
+  }
   node <- griwrm[griwrm$id == id,]
   FUN_MOD <- griwrm$model[griwrm$id == griwrm$donor[griwrm$id == id]]
 
   # Set hydraulic parameters
-  UpstreamNodes <- griwrm$id[griwrm$down == id & !is.na(griwrm$down)]
+  UpstreamNodeRows <- which(griwrm$down == id & !is.na(griwrm$down))
   Qupstream <- NULL
   LengthHydro <- NULL
   BasinAreas <- NULL
 
-  if(length(UpstreamNodes) > 0) {
+  if(length(UpstreamNodeRows) > 0) {
     # Sub-basin with hydraulic routing
-    Qupstream <- as.matrix(Qobs[ , UpstreamNodes, drop=FALSE])
-    LengthHydro <- griwrm$length[griwrm$id %in% UpstreamNodes]
-    names(LengthHydro) <- UpstreamNodes
+    Qupstream <- as.matrix(Qobs[ , griwrm$id[UpstreamNodeRows], drop=FALSE])
+    upstreamDiversion <- which(
+      sapply(griwrm$id[UpstreamNodeRows],
+             function(id) {
+               getNodeProperties(id, griwrm)$Diversion
+             })
+    )
+    if (length(upstreamDiversion) > 0) {
+      Qupstream[, upstreamDiversion] <- - Qupstream[, upstreamDiversion]
+    }
+    LengthHydro <- griwrm$length[UpstreamNodeRows]
+    names(LengthHydro) <- griwrm$id[UpstreamNodeRows]
     BasinAreas <- c(
-        griwrm$area[griwrm$id %in% UpstreamNodes],
-        node$area - sum(griwrm$area[griwrm$id %in% UpstreamNodes], na.rm = TRUE)
+        griwrm$area[UpstreamNodeRows],
+        node$area - sum(griwrm$area[UpstreamNodeRows], na.rm = TRUE)
     )
     if (BasinAreas[length(BasinAreas)] < 0) {
       stop(sprintf(
@@ -170,7 +284,7 @@ CreateOneGRiwrmInputsModel <- function(id, griwrm, ..., Qobs) {
         id
       ))
     }
-    names(BasinAreas) <- c(UpstreamNodes, id)
+    names(BasinAreas) <- c(griwrm$id[UpstreamNodeRows], id)
   }
 
   # Set model inputs with the **airGR** function
@@ -185,9 +299,13 @@ CreateOneGRiwrmInputsModel <- function(id, griwrm, ..., Qobs) {
   # Add Identifiers of connected nodes in order to be able to update them with simulated flows
   InputsModel$id <- id
   InputsModel$down <- node$down
-  if(length(UpstreamNodes) > 0) {
-    InputsModel$UpstreamNodes <- UpstreamNodes
-    InputsModel$UpstreamIsRunoff <- !is.na(griwrm$model[match(UpstreamNodes, griwrm$id)])
+  if(length(UpstreamNodeRows) > 0) {
+    InputsModel$UpstreamNodes <- griwrm$id[UpstreamNodeRows]
+    InputsModel$UpstreamIsModeled <- !is.na(griwrm$model[UpstreamNodeRows])
+    InputsModel$UpstreamVarQ <- ifelse(!is.na(griwrm$model[UpstreamNodeRows]) &
+                                    griwrm$model[UpstreamNodeRows] == "Diversion",
+                                    "Qdiv_m3",
+                                    "Qsim_m3")
   } else {
     InputsModel$BasinAreas <- node$area
   }
@@ -201,6 +319,12 @@ CreateOneGRiwrmInputsModel <- function(id, griwrm, ..., Qobs) {
   InputsModel$model <- list(indexParamUngauged = ifelse(inherits(InputsModel, "SD"), 0, 1) + seq.int(featModel$NbParam),
                             hasX4 = grepl("RunModel_GR[456][HJ]", FUN_MOD),
                             iX4 = ifelse(inherits(InputsModel, "SD"), 5, 4))
+  InputsModel$hasDiversion <- hasDiversion
+  if (hasDiversion) {
+    InputsModel$diversionOutlet <- diversionOutlet
+    InputsModel$Qdiv <- -Qobs[, id]
+    InputsModel$Qmin <- Qmin
+  }
   return(InputsModel)
 }
 
@@ -288,6 +412,7 @@ hasUngaugedNodes <- function(id, griwrm) {
 
 
 #' function to extract model features partially copied from airGR:::.GetFeatModel
+#' @importFrom utils tail
 #' @noRd
 .GetFeatModel <- function(InputsModel) {
   path <- system.file("modelsFeatures/FeatModelsGR.csv", package = "airGR")
diff --git a/R/CreateRunOptions.R b/R/CreateRunOptions.R
index 390aab4b82119585f071f477404597b4949cd640..48dfeca159a60f37504a9142d6577f60f1a61add 100644
--- a/R/CreateRunOptions.R
+++ b/R/CreateRunOptions.R
@@ -17,7 +17,7 @@
 #'
 #' @rdname CreateRunOptions
 #' @export
-#' @inherit RunModel.GRiwrmInputsModel return examples
+#' @example man-examples/RunModel.GRiwrmInputsModel.R
 CreateRunOptions <- function(x, ...) {
   UseMethod("CreateRunOptions", x)
 }
diff --git a/R/CreateSupervisor.R b/R/CreateSupervisor.R
index 5aec3fbeff0a48e79782d0dc6a93dee82718ccab..93b7fe29fabdba949f71e1b6eea648f319669707 100644
--- a/R/CreateSupervisor.R
+++ b/R/CreateSupervisor.R
@@ -11,28 +11,13 @@
 #' - some internal state variables updated during simulation (`ts.index`, `ts.previous`, `ts.date`, `ts.index0`, `controller.id`)
 #' @export
 #'
-#' @examples
-#' data(Severn)
-#' nodes <- Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")]
-#' nodes$model <- "RunModel_GR4J"
-#' griwrm <- CreateGRiwrm(nodes,
-#'                  list(id = "gauge_id",
-#'                       down = "downstream_id",
-#'                       length = "distance_downstream"))
-#' BasinsObs <- Severn$BasinsObs
-#' DatesR <- BasinsObs[[1]]$DatesR
-#' PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
-#' PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
-#' Qobs <- cbind(sapply(BasinsObs, function(x) {x$discharge_spec}))
-#' Precip <- ConvertMeteoSD(griwrm, PrecipTot)
-#' PotEvap <- ConvertMeteoSD(griwrm, PotEvapTot)
-#' InputsModel <- CreateInputsModel(griwrm, DatesR, Precip, PotEvap, Qobs)
-#' sv <- CreateSupervisor(InputsModel)
+#' @example man-examples/RunModel.Supervisor.R
 CreateSupervisor <- function(InputsModel, TimeStep = 1L) {
   if(!inherits(InputsModel, "GRiwrmInputsModel")) {
     stop("`InputsModel` parameter must of class 'GRiwrmInputsModel' (See ?CreateInputsModel.GRiwrm)")
   }
-  if(!is.integer(TimeStep)) stop("`TimeStep` parameter must be an integer")
+  if (!is.integer(TimeStep)) stop("`TimeStep` parameter must be an integer")
+  if (TimeStep < 1) stop("`TimeStep` parameter must be strictly positive")
 
   # Create Supervisor environment from the parent of GlobalEnv
   e <- new.env(parent = parent.env(globalenv()))
@@ -48,6 +33,12 @@ CreateSupervisor <- function(InputsModel, TimeStep = 1L) {
   e$DatesR <- InputsModel[[1]]$DatesR
   e$InputsModel <- InputsModel
   e$griwrm <- attr(InputsModel, "GRiwrm")
+  # Commands U are only applied on DirectInjection and Diversion
+  e$griwrm4U <- e$griwrm[is.na(e$griwrm$model) | e$griwrm$model == "Diversion", ]
+  e$nodeProperties <- lapply(e$griwrm$id[getDiversionRows(e$griwrm, TRUE)],
+                             getNodeProperties,
+                             griwrm = e$griwrm)
+  names(e$nodeProperties) <- e$griwrm$id[getDiversionRows(e$griwrm, TRUE)]
   e$OutputsModel <- list()
   e$.TimeStep <- TimeStep
 
@@ -74,3 +65,8 @@ CreateSupervisor <- function(InputsModel, TimeStep = 1L) {
 
   return(e)
 }
+
+
+is.Supervisor <- function(x) {
+  return(inherits(x, "Supervisor") && x$.isSupervisor == "3FJKmDcJ4snDbVBg")
+}
diff --git a/R/RunModel.GRiwrmInputsModel.R b/R/RunModel.GRiwrmInputsModel.R
index 439d6f2d40e0d4c5d2b9d2e29687b78bce1ed7ca..bd0f9833c69ca0be68aa9ad51006aa498ea41487 100644
--- a/R/RunModel.GRiwrmInputsModel.R
+++ b/R/RunModel.GRiwrmInputsModel.R
@@ -7,90 +7,7 @@
 #'
 #' @return An object of class \emph{GRiwrmOutputsModel}. This object is a [list] of *OutputsModel* objects produced by [RunModel.InputsModel] for each node of the semi-distributed model.
 #' @export
-#' @examples
-#' ###################################################################
-#' # Run the `airGR::RunModel_Lag` example in the GRiwrm fashion way #
-#' # Simulation of a reservoir with a purpose of low-flow mitigation #
-#' ###################################################################
-#'
-#' ## ---- preparation of the InputsModel object
-#'
-#' ## loading package and catchment data
-#' library(airGRiwrm)
-#' data(L0123001)
-#'
-#' ## ---- specifications of the reservoir
-#'
-#' ## the reservoir withdraws 1 m3/s when it's possible considering the flow observed in the basin
-#' Qupstream <- matrix(-sapply(BasinObs$Qls / 1000 - 1, function(x) {
-#'   min(1, max(0, x, na.rm = TRUE))
-#' }), ncol = 1)
-#'
-#' ## except between July and September when the reservoir releases 3 m3/s for low-flow mitigation
-#' month <- as.numeric(format(BasinObs$DatesR, "%m"))
-#' Qupstream[month >= 7 & month <= 9] <- 3
-#' Qupstream <- Qupstream * 86400 ## Conversion in m3/day
-#'
-#' ## the reservoir is not an upstream subcachment: its areas is NA
-#' BasinAreas <- c(NA, BasinInfo$BasinArea)
-#'
-#' ## delay time between the reservoir and the catchment outlet is 2 days and the distance is 150 km
-#' LengthHydro <- 150
-#' ## with a delay of 2 days for 150 km, the flow velocity is 75 km per day
-#' Velocity <- (LengthHydro * 1e3 / 2) / (24 * 60 * 60) ## Conversion km/day -> m/s
-#'
-#' # This example is a network of 2 nodes which can be describe like this:
-#' db <- data.frame(id = c("Reservoir", "GaugingDown"),
-#'                  length = c(LengthHydro, NA),
-#'                  down = c("GaugingDown", NA),
-#'                  area = c(NA, BasinInfo$BasinArea),
-#'                  model = c(NA, "RunModel_GR4J"),
-#'                  stringsAsFactors = FALSE)
-#'
-#' # Create GRiwrm object from the data.frame
-#' griwrm <- CreateGRiwrm(db)
-#' str(griwrm)
-#'
-#' # Formatting observations for the hydrological models
-#' # Each input data should be a matrix or a data.frame with the good id in the name of the column
-#' Precip <- matrix(BasinObs$P, ncol = 1)
-#' colnames(Precip) <- "GaugingDown"
-#' PotEvap <- matrix(BasinObs$E, ncol = 1)
-#' colnames(PotEvap) <- "GaugingDown"
-#'
-#' # Observed flows contain flows that are directly injected in the model
-#' Qobs = matrix(Qupstream, ncol = 1)
-#' colnames(Qobs) <- "Reservoir"
-#'
-#' # Creation of the GRiwrmInputsModel object (= a named list of InputsModel objects)
-#' InputsModels <- CreateInputsModel(griwrm,
-#'                             DatesR = BasinObs$DatesR,
-#'                             Precip = Precip,
-#'                             PotEvap = PotEvap,
-#'                             Qobs = Qobs)
-#' str(InputsModels)
-#'
-#' ## run period selection
-#' Ind_Run <- seq(which(format(BasinObs$DatesR, format = "%Y-%m-%d")=="1990-01-01"),
-#'                which(format(BasinObs$DatesR, format = "%Y-%m-%d")=="1999-12-31"))
-#'
-#' # Creation of the GriwmRunOptions object
-#' RunOptions <- CreateRunOptions(InputsModels,
-#'                                 IndPeriod_Run = Ind_Run)
-#' str(RunOptions)
-#'
-#' # Parameters of the SD models should be encapsulated in a named list
-#' ParamGR4J <- c(X1 = 257.238, X2 = 1.012, X3 = 88.235, X4 = 2.208)
-#' Param <- list(`GaugingDown` = c(Velocity, ParamGR4J))
-#'
-#' # RunModel for the whole network
-#' OutputsModels <- RunModel(InputsModels,
-#'                           RunOptions = RunOptions,
-#'                           Param = Param)
-#' str(OutputsModels)
-#'
-#' # Compare Simulation with reservoir and observation of natural flow
-#' plot(OutputsModels, data.frame(GaugingDown = BasinObs$Qmm[Ind_Run]))
+#' @example man-examples/RunModel.GRiwrmInputsModel.R
 RunModel.GRiwrmInputsModel <- function(x, RunOptions, Param, ...) {
 
   checkRunModelParameters(x, RunOptions, Param)
@@ -99,10 +16,10 @@ RunModel.GRiwrmInputsModel <- function(x, RunOptions, Param, ...) {
   class(OutputsModel) <- c("GRiwrmOutputsModel", class(OutputsModel))
 
   for(id in names(x)) {
-    message("RunModel.GRiwrmInputsModel: Treating sub-basin ", x[[id]]$id, "...")
+    message("RunModel.GRiwrmInputsModel: Processing sub-basin ", x[[id]]$id, "...")
 
     # Update x[[id]]$Qupstream with simulated upstream flows
-    if(any(x[[id]]$UpstreamIsRunoff)) {
+    if(any(x[[id]]$UpstreamIsModeled)) {
       x[[id]] <- UpdateQsimUpstream(x[[id]], RunOptions[[id]], OutputsModel)
     }
     # Run the model for the sub-basin
diff --git a/R/RunModel.InputsModel.R b/R/RunModel.InputsModel.R
index d64876a9886cc1fbbf754ac2c87f9ea1fa89c508..12727eb4adc6c6aa5dd404e4b654ca97368c970c 100644
--- a/R/RunModel.InputsModel.R
+++ b/R/RunModel.InputsModel.R
@@ -18,10 +18,76 @@ RunModel.InputsModel <- function(x, RunOptions, Param, FUN_MOD = NULL, ...) {
   OutputsModel <- airGR::RunModel(x, RunOptions, Param, FUN_MOD)
   if (is.null(OutputsModel$Qsim_m3)) {
     # Add Qsim_m3 in m3/timestep
-    OutputsModel$Qsim_m3 <- OutputsModel$Qsim * sum(x$BasinAreas) * 1e3
+    OutputsModel$Qsim_m3 <-
+      OutputsModel$Qsim * sum(x$BasinAreas, na.rm = TRUE) * 1e3
   }
   if ("WarmUpQsim" %in% RunOptions$Outputs_Sim) {
-    OutputsModel$RunOptions$WarmUpQsim_m3 <- OutputsModel$RunOptions$WarmUpQsim * sum(x$BasinAreas) * 1e3
+    OutputsModel$RunOptions$WarmUpQsim_m3 <-
+      OutputsModel$RunOptions$WarmUpQsim * sum(x$BasinAreas, na.rm = TRUE) * 1e3
+  }
+  if (x$hasDiversion) {
+    OutputsModel <- RunModel_Diversion(x, RunOptions, OutputsModel)
+  }
+  return(OutputsModel)
+}
+
+
+#' Model the diversion of a flow from an existing modeled node
+#'
+#' On a Diversion node, this function is called after `airGR::RunModel` to
+#' divert a part of the flow to another node than the original downstream one.
+#'
+#' @param InputsModel \[object of class \emph{InputsModel}\] see
+#'        [airGR::CreateInputsModel] for details
+#' @param RunOptions Same parameter as in [RunModel.GRiwrmInputsModel]
+#' @param OutputsModel Output of [airGR::RunModel]
+#' @param updateQsim [logical] for updating Qsim after diversion in the output
+#'
+#' @return Updated `OutputsModel` object after diversion
+#' @noRd
+#'
+RunModel_Diversion <- function(InputsModel,
+                               RunOptions,
+                               OutputsModel,
+                               updateQsim = TRUE) {
+  OutputsModel$Qnat <- OutputsModel$Qsim
+  lQ <- calc_Qdiv(OutputsModel$Qsim_m3,
+                  InputsModel$Qdiv[RunOptions$IndPeriod_Run],
+                  InputsModel$Qmin[RunOptions$IndPeriod_Run])
+  #message(paste(InputsModel$Qdiv[RunOptions$IndPeriod_Run], lQ$Qdiv, lQ$Qsim, InputsModel$Qmin[RunOptions$IndPeriod_Run], sep = ", "))
+  OutputsModel$Qdiv_m3 <- lQ$Qdiv
+  OutputsModel$Qsim_m3 <- lQ$Qsim
+  if (updateQsim) {
+    OutputsModel$Qsim <-
+      OutputsModel$Qsim_m3 / sum(InputsModel$BasinAreas, na.rm = TRUE) / 1e3
+  }
+  if ("WarmUpQsim" %in% RunOptions$Outputs_Sim) {
+    lQ <- calc_Qdiv(OutputsModel$RunOptions$WarmUpQsim_m3,
+                    InputsModel$Qdiv[RunOptions$IndPeriod_WarmUp],
+                    InputsModel$Qmin[RunOptions$IndPeriod_WarmUp])
+    OutputsModel$RunOptions$WarmUpQdiv_m3 <- lQ$Qdiv
+    OutputsModel$RunOptions$WarmUpQsim_m3 <- lQ$Qsim
   }
   return(OutputsModel)
 }
+
+
+#' Compute diverted and simulated flow at a diversion
+#'
+#' @param Qnat [numeric] time series of flow before diversion (m3/time step)
+#' @param Qdiv [numeric] time series of planned diverted flow (m3/time step)
+#' @param Qmin [numeric] time series of minimum flow after diversion (m3/time step)
+#'
+#' @return A [list] with items:
+#' - Qdiv, the diverted flow after limitation of minimum flow
+#' - Qsim, the simulated flow after diversion and limitation
+#' @noRd
+calc_Qdiv<- function(Qnat, Qdiv, Qmin) {
+  Qsim <- Qnat - Qdiv
+  indexQmin <- which(Qsim < Qmin & Qdiv > 0)
+  if (any(indexQmin)) {
+    #Qsim[indexQmin] <- sapply(indexQmin, function(i) min(Qnat[i], Qmin[i]))
+    Qsim[indexQmin] <- pmin(Qnat[indexQmin], Qmin[indexQmin])
+  }
+  return(list(Qsim = Qsim, Qdiv = Qnat - Qsim))
+}
diff --git a/R/RunModel.SD.R b/R/RunModel.SD.R
index 6d141d421caee7ba321f18cae3d28fca2e9f8c41..5498bcfa30a510832ac21f4f79d7d56673931668 100644
--- a/R/RunModel.SD.R
+++ b/R/RunModel.SD.R
@@ -8,5 +8,9 @@
 #' @export
 #'
 RunModel.SD <- function(x, RunOptions, Param, QcontribDown, ...) {
-  airGR::RunModel_Lag(x, RunOptions = RunOptions, Param = Param[1], QcontribDown = QcontribDown)
+  OutputsModel <- airGR::RunModel_Lag(x,
+                                      RunOptions = RunOptions,
+                                      Param = Param[1],
+                                      QcontribDown = QcontribDown)
+  return(OutputsModel)
 }
diff --git a/R/RunModel.Supervisor.R b/R/RunModel.Supervisor.R
index 937dc40ea1f76bb9173aeea48ac04d8f43ea5501..3c9518fd7b6ac8a661c2235a5cab01fe9ca5fa29 100644
--- a/R/RunModel.Supervisor.R
+++ b/R/RunModel.Supervisor.R
@@ -7,8 +7,13 @@
 #'
 #' @return \emph{GRiwrmOutputsModel} object which is a list of \emph{OutputsModel} objects (See [airGR::RunModel]) for each node of the semi-distributed model
 #' @export
+#'
+#' @example man-examples/RunModel.Supervisor.R
 RunModel.Supervisor <- function(x, RunOptions, Param, ...) {
 
+  stopifnot(is.Supervisor(x),
+            inherits(RunOptions, "GRiwrmRunOptions"))
+
   # Save InputsModel for restoration at the end (Supervisor is an environment...)
   InputsModelBackup <- x$InputsModel
 
@@ -28,32 +33,35 @@ RunModel.Supervisor <- function(x, RunOptions, Param, ...) {
 
   # Run runoff model for each sub-basin
   x$OutputsModel <- lapply(X = x$InputsModel, FUN = function(IM) {
-    RunModel.GR(IM,
-                RunOptions = RunOptions[[IM$id]],
-                Param = Param[[IM$id]])
+    OM_GR <- RunModel.GR(IM,
+                         RunOptions = RunOptions[[IM$id]],
+                         Param = Param[[IM$id]])
+    if (IM$hasDiversion) OM_GR$Qnat <- OM_GR$Qsim
+    return(OM_GR)
   })
-  class(x$OutputsModel) <- append(class(x$OutputsModel), "GRiwrmOutputsModel")
-  # Copy simulated pure runoff flows (no SD nodes) to Qupstream in downstream SD nodes
-  for(id in getNoSD_Ids(x$InputsModel)) {
-    downId <- x$InputsModel[[id]]$down
-    if(!is.null(x$InputsModel[[downId]])) {
-      x$InputsModel[[downId]]$Qupstream[RunOptions[[downId]]$IndPeriod_Run, id] <-
-        x$OutputsModel[[id]]$Qsim_m3
-    }
+  class(x$OutputsModel) <- c("GRiwrmOutputsModel", class(x$OutputsModel))
+
+  # Copy simulated pure runoff flows (no SD nor Diversion nodes) to Qupstream
+  for(id in getNoSD_Ids(x$InputsModel, include_diversion = FALSE)) {
+    updateQupstream.Supervisor(x, id, IndPeriod_Run)
   }
 
-  # Save Qsim for step by step simulation
+  # Save OutputsModel for step by step simulation
   QcontribDown <- do.call(
     cbind,
     lapply(x$OutputsModel, "[[", "Qsim")
   )
-
   Qsim_m3 <- do.call(
     cbind,
     lapply(x$OutputsModel, "[[", "Qsim_m3")
   )
+  if (length(getDiversionRows(x$griwrm)) > 0) {
+    # Outputs of Diversion nodes
+    Qdiv_m3 <- Qsim_m3[, x$griwrm$id[getDiversionRows(x$griwrm)], drop = FALSE] * NA
+    Qnat <- Qdiv_m3
+  }
 
-  # Initialisation of model states by running the model with no supervision on warm-up period
+  # Initialization of model states by running the model with no supervision on warm-up period
   RunOptionsWarmUp <- RunOptions
   for(id in names(x$InputsModel)) {
     RunOptionsWarmUp[[id]]$IndPeriod_Run <- RunOptionsWarmUp[[id]]$IndPeriod_WarmUp
@@ -73,8 +81,16 @@ RunModel.Supervisor <- function(x, RunOptions, Param, ...) {
     x$OutputsModel[[id]]$StateEnd <- serializeIniStates(OM_WarmUp[[id]]$StateEnd)
   }
 
+  message("Processing: 0%", appendLF = FALSE)
+  iProgressSteps <- round(length(lSuperTS) * seq(0.1, 0.9, 0.1))
+
   # Loop over time steps with a step equal to the supervision time step
-  for(iTS in lSuperTS) {
+  for(i in seq_along(lSuperTS)) {
+    iProgressMessage <- which(i == iProgressSteps)
+    if (length(iProgressMessage) == 1) {
+      message(" ", 10 * iProgressMessage, "%", appendLF = FALSE)
+    }
+    iTS <- lSuperTS[[i]]
     # Run regulation on the whole basin for the current time step
     x$ts.index <- iTS - x$ts.index0
     x$ts.date <- x$InputsModel[[1]]$DatesR[iTS]
@@ -82,32 +98,49 @@ RunModel.Supervisor <- function(x, RunOptions, Param, ...) {
     if(iTS[1] > ts.start) {
       doSupervision(x)
     }
-
     # Loop over sub-basin using SD model
-    for(id in getSD_Ids(x$InputsModel)) {
-      # Run the SD model for the sub-basin and one time step
-      RunOptions[[id]]$IndPeriod_Run <- iTS
+    for(id in getSD_Ids(x$InputsModel, add_diversion = TRUE)) {
+      # Run model for the sub-basin and one time step
       RunOptions[[id]]$IniStates <- serializeIniStates(x$OutputsModel[[id]]$StateEnd)
-      x$OutputsModel[[id]] <- RunModel.SD(
-        x$InputsModel[[id]],
-        RunOptions = RunOptions[[id]],
-        Param = Param[[id]],
-        QcontribDown = QcontribDown[x$ts.index, id]
-      )
-      # Storing Qsim in the data.frame Qsim
+      RunOptions[[id]]$IndPeriod_Run <- iTS
+      if (RunOptions[[id]]$FeatFUN_MOD$IsSD) {
+        # Route upstream flows for SD nodes
+        x$OutputsModel[[id]] <- RunModel.SD(
+          x$InputsModel[[id]],
+          RunOptions = RunOptions[[id]],
+          Param = Param[[id]],
+          QcontribDown = QcontribDown[x$ts.index, id]
+        )
+      } else {
+        x$OutputsModel[[id]]$Qsim_m3 <- Qsim_m3[x$ts.index, id]
+      }
+      if (x$InputsModel[[id]]$hasDiversion) {
+        # Compute diverted and simulated flows on Diversion nodes
+        x$OutputsModel[[id]] <-
+          RunModel_Diversion(x$InputsModel[[id]],
+                             RunOptions = RunOptions[[id]],
+                             OutputsModel = x$OutputsModel[[id]])
+      }
+      # Storing Qsim_m3 and Qdiv_m3 data.frames
       Qsim_m3[x$ts.index, id] <- x$OutputsModel[[id]]$Qsim_m3
-      # Routing Qsim to Qupstream of downstream nodes
-      if(!is.na(x$InputsModel[[id]]$down)) {
-        x$InputsModel[[x$InputsModel[[id]]$down]]$Qupstream[iTS, id] <-
-          x$OutputsModel[[id]]$Qsim_m3
+      if (x$InputsModel[[id]]$hasDiversion) {
+        Qdiv_m3[x$ts.index, id] <- x$OutputsModel[[id]]$Qdiv_m3
       }
+      # Routing Qsim_m3 and Qdiv_m3 to Qupstream of downstream nodes
+      updateQupstream.Supervisor(x, id, iTS)
     }
     x$ts.previous <- x$ts.index
   }
+
+  message(" 100%")
+
   for(id in getSD_Ids(x$InputsModel)) {
     x$OutputsModel[[id]]$Qsim_m3 <- Qsim_m3[, id]
     x$OutputsModel[[id]]$Qsim <-
       Qsim_m3[, id] / sum(x$InputsModel[[id]]$BasinAreas, na.rm = TRUE) / 1e3
+    if (x$InputsModel[[id]]$hasDiversion) {
+      x$OutputsModel[[id]]$Qdiv_m3 <- Qdiv_m3[, id]
+    }
   }
   attr(x$OutputsModel, "Qm3s") <- OutputsModelQsim(x$InputsModel, x$OutputsModel, IndPeriod_Run)
 
@@ -116,3 +149,18 @@ RunModel.Supervisor <- function(x, RunOptions, Param, ...) {
 
   return(x$OutputsModel)
 }
+
+updateQupstream.Supervisor <- function(x, id, iTS) {
+  downId <- x$InputsModel[[id]]$down
+  if(!is.null(x$InputsModel[[downId]])) {
+    x$InputsModel[[downId]]$Qupstream[iTS, id] <-
+      x$OutputsModel[[id]]$Qsim_m3
+  }
+  if (x$InputsModel[[id]]$hasDiversion) {
+    divOutId <- x$InputsModel[[id]]$diversionOutlet
+    if (!is.na(divOutId)) {
+      x$InputsModel[[divOutId]]$Qupstream[iTS, id] <-
+        x$OutputsModel[[id]]$Qdiv_m3
+    }
+  }
+}
diff --git a/R/UpdateQsimUpstream.R b/R/UpdateQsimUpstream.R
index 3afa52d8c94c02ddb7b716077973866eb1d404a6..9d0a012a2b4af6697babb3ddb838b9b2eb3eabd9 100644
--- a/R/UpdateQsimUpstream.R
+++ b/R/UpdateQsimUpstream.R
@@ -11,12 +11,13 @@
 #' @noRd
 #'
 UpdateQsimUpstream <- function(InputsModel, Runoptions, OutputsModel) {
-  iQ <- which(InputsModel$UpstreamIsRunoff)
+  iQ <- which(InputsModel$UpstreamIsModeled)
   for(i in iQ) {
-      InputsModel$Qupstream[Runoptions$IndPeriod_Run, i] <- OutputsModel[[InputsModel$UpstreamNodes[i]]]$Qsim_m3
-      if (!is.null(OutputsModel[[InputsModel$UpstreamNodes[i]]]$RunOptions$WarmUpQsim_m3)) {
-        InputsModel$Qupstream[Runoptions$IndPeriod_WarmUp, i] <- OutputsModel[[InputsModel$UpstreamNodes[i]]]$RunOptions$WarmUpQsim_m3
-      }
+    InputsModel$Qupstream[Runoptions$IndPeriod_Run, i] <- OutputsModel[[InputsModel$UpstreamNodes[i]]][[InputsModel$UpstreamVarQ[i]]]
+    varWarmupQ_m3 <- paste0("WarmUp", InputsModel$UpstreamVarQ[i])
+    if (!is.null(OutputsModel[[InputsModel$UpstreamNodes[i]]]$RunOptions[[varWarmupQ_m3]])) {
+      InputsModel$Qupstream[Runoptions$IndPeriod_WarmUp, i] <- OutputsModel[[InputsModel$UpstreamNodes[i]]]$RunOptions[[varWarmupQ_m3]]
+    }
   }
   return(InputsModel)
 }
diff --git a/R/plot.GRiwrm.R b/R/plot.GRiwrm.R
index 1698a13cd3d740783e063e7c8ed1baa354c38109..aa2ee083e7ff226b9230768e7e37cd4172d7b554 100644
--- a/R/plot.GRiwrm.R
+++ b/R/plot.GRiwrm.R
@@ -24,8 +24,8 @@ plot.GRiwrm <- function(x,
                         height = "100%",
                         box_colors = c(UpstreamUngauged = "#eef",
                                        UpstreamGauged = "#aaf",
-                                       IntermUngauged = "#efe",
-                                       IntermGauged = "#afa",
+                                       IntermediateUngauged = "#efe",
+                                       IntermediateGauged = "#afa",
                                        DirectInjection = "#faa"),
                         ...) {
 
@@ -40,31 +40,53 @@ plot.GRiwrm <- function(x,
             length(height) == 1,
             is.character(box_colors),
             length(setdiff(names(box_colors), c("UpstreamUngauged", "UpstreamGauged",
-                                                "IntermUngauged",   "IntermGauged",
+                                                "IntermediateUngauged",   "IntermediateGauged",
                                                 "DirectInjection"))) == 0)
+  nodes <- sprintf("id_%1$s[%1$s]", x$id)
   g2 <- x[!is.na(x$down),]
-  nodes <- paste(
-    sprintf("id_%1$s[%1$s]", g2$id),
+  links <- paste(
+    sprintf("id_%1$s", g2$id),
     "-->|",
     round(g2$length, digits = 0),
     "km|",
-    sprintf("id_%1$s[%1$s]", g2$down)
+    sprintf("id_%1$s", g2$down)
   )
-  node_class <- list(
-    UpstreamUngauged = x$id[!x$id %in% x$down & x$model == "Ungauged"],
-    UpstreamGauged = x$id[!x$id %in% x$down & x$model != "Ungauged" & !is.na(x$model)],
-    IntermUngauged = x$id[x$id %in% x$down & x$model == "Ungauged"],
-    IntermGauged = x$id[x$id %in% x$down & x$model != "Ungauged" & !is.na(x$model)],
-    DirectInjection = x$id[is.na(x$model)]
-  )
-  node_class <- lapply(node_class, function(x) if(length(x) > 0) paste0("id_", x))
-  node_class[sapply(node_class, is.null)] <- NULL
+  x$nodeclass <- sapply(x$id, getNodeClass, griwrm = x)
+  node_class <- lapply(unique(x$nodeclass), function(nc) {
+    x$id[x$nodeclass == nc]
+  })
+  names(node_class) <- unique(x$nodeclass)
+  node_class <- lapply(node_class, function(id) if(length(id) > 0) paste0("id_", id))
   node_class <- paste("class", sapply(node_class, paste, collapse = ","), names(node_class))
-  css <- paste("classDef", names(box_colors), paste0("fill:", box_colors))
-  diagram <- paste(c(paste("graph", orientation), nodes, node_class, css), collapse = "\n\n")
+  css <- c(
+    paste("classDef", names(box_colors), paste0("fill:", box_colors)),
+    paste("classDef",
+          paste0(names(box_colors), "Diversion"),
+          sprintf("fill:%s, stroke:%s, stroke-width:3px", box_colors, box_colors["DirectInjection"]))
+  )
+  if (length(getDiversionRows(g2)) > 0) {
+    css <- c(css,
+             paste("linkStyle",
+                   getDiversionRows(g2) - 1,
+                   sprintf("stroke:%s, stroke-width:2px,stroke-dasharray: 5 5;",
+                           box_colors["DirectInjection"])))
+  }
+  diagram <- paste(c(paste("graph", orientation), nodes, links, node_class, css),
+                   collapse = "\n\n")
   if (display) {
     DiagrammeR::mermaid(diagram = diagram, width, height, ...)
   } else {
     return(diagram)
   }
 }
+
+getNodeClass <- function(id, griwrm) {
+  props <- getNodeProperties(id, griwrm)
+  if (props$DirectInjection) {
+    nc <- "DirectInjection"
+  }  else {
+    nc <- paste0(props["position"], props["hydrology"])
+  }
+  if (props$Diversion) nc <- paste0(nc, "Diversion")
+  return(nc)
+}
diff --git a/R/plot.GRiwrmOutputsModel.R b/R/plot.GRiwrmOutputsModel.R
index 01d12f402d12bd0e91210b0dddc7821aeb0792ce..05081e5215e0e40acfa08bd9b144ddf44cdc57d9 100644
--- a/R/plot.GRiwrmOutputsModel.R
+++ b/R/plot.GRiwrmOutputsModel.R
@@ -11,7 +11,7 @@
 #' @importFrom graphics plot par title
 #' @export
 #'
-#' @inherit RunModel.GRiwrmInputsModel return examples
+#' @example man-examples/RunModel.GRiwrmInputsModel.R
 #'
 plot.GRiwrmOutputsModel <- function(x, Qobs = NULL, ...) {
 
diff --git a/R/plot.Qm3s.R b/R/plot.Qm3s.R
index 65202859f2aefb4b4eb1ff9b1ab2ea450b3d095c..0b378cacdbfde6546b236de4378ddff7c77cc1d1 100644
--- a/R/plot.Qm3s.R
+++ b/R/plot.Qm3s.R
@@ -1,12 +1,18 @@
 #' Plot of a `Qm3s` object (time series of simulated flows)
 #'
-#' @param x [data.frame] with a first column with [POSIXt] dates and followings columns with flows at each node of the network
+#' This function plot time series of flow rate in m3/s. It's a method for object
+#' of class "Qm3s" which can be directly called by `plot`. It can also be called
+#' as a function `plot.Qm3s` if the first parameter has the good format.
+#'
+#' @param x [data.frame] with a first column with [POSIXt] dates and followings
+#'        columns with flows at each node of the network
 #' @param type [character] plot type (See [plot.default]), default "l"
 #' @param xlab [character] label for the x axis, default to "Date"
 #' @param ylab [character] label for the y axis, default to "Flow (m3/s)"
 #' @param main [character] main title for the plot, default to "Simulated flows"
 #' @param col [character] plotting color (See [par]), default to rainbow colors
-#' @param legend [character] see parameter `legend` of [legend]. Set to [NULL] if display of the legend is not wanted
+#' @param legend [character] see parameter `legend` of [legend]. Set it to [NULL]
+#'        to hide the legend
 #' @param legend.cex [character] `cex` parameter for the text of the legend (See [par])
 #' @param legend.x,legend.y Legend position, see `x` and `y` parameters in [graphics::legend]
 #' @param lty [character] or [numeric] The line type (See [par])
@@ -14,14 +20,17 @@
 #'
 #' @return Screen plot window.
 #'
+#' @example man-examples/RunModel.GRiwrmInputsModel.R
+#'
 #' @importFrom grDevices rainbow
 #' @importFrom graphics matplot
+#' @export plot.Qm3s
 #' @export
 #'
 plot.Qm3s <- function(x,
                       type = "l",
                       xlab = "Date",
-                      ylab = expression("Flow (m"^"3"*"/s)"),
+                      ylab = expression("Flow rate (m"^"3"*"/s)"),
                       main = "Simulated flows",
                       col = rainbow(ncol(x) - 1),
                       legend = colnames(x)[-1],
@@ -30,8 +39,12 @@ plot.Qm3s <- function(x,
                       legend.y = NULL,
                       lty = 1,
                       ...) {
+
+  stopifnot(is.data.frame(x),
+            inherits(x[, 1], "POSIXct"))
+
   matplot(
-    x$DatesR,
+    x[, 1],
     x[, -1],
     type = type,
     lty = lty,
diff --git a/R/utils.R b/R/utils.R
index 2d641f622c78ae5bbbce745b72533829f863647b..a36aa1b1e22737806998118047014c3e9bc6ab33 100644
--- a/R/utils.R
+++ b/R/utils.R
@@ -1,15 +1,16 @@
 #' Function to obtain the ID of sub-basins using SD model
 #'
 #' @param InputsModel \[`GRiwrmInputsModel` object\]
+#' @param add_diversion [logical] for adding upstream nodes with diversion
 #'
 #' @return [character] IDs of the sub-basins using SD model
 #' @export
-getSD_Ids <- function(InputsModel) {
+getSD_Ids <- function(InputsModel, add_diversion = FALSE) {
   if (!inherits(InputsModel, "GRiwrmInputsModel")) {
     stop("Argument `InputsModel` should be of class GRiwrmInputsModel")
   }
   bSDs <- sapply(InputsModel, function (IM) {
-    inherits(IM, "SD")
+    inherits(IM, "SD") | IM$hasDiversion
   })
   names(InputsModel)[bSDs]
 }
@@ -17,15 +18,16 @@ getSD_Ids <- function(InputsModel) {
 #' Function to obtain the ID of sub-basins not using SD model
 #'
 #' @param InputsModel \[`GRiwrmInputsModel` object\]
+#' @param include_diversion [logical] for including diversion nodes
 #'
 #' @return [character] IDs of the sub-basins not using the SD model
 #' @export
-getNoSD_Ids <- function(InputsModel) {
+getNoSD_Ids <- function(InputsModel, include_diversion = TRUE) {
   if (!inherits(InputsModel, "GRiwrmInputsModel")) {
     stop("Argument `InputsModel` should be of class GRiwrmInputsModel")
   }
   bSDs <- sapply(InputsModel, function (IM) {
-    !inherits(IM, "SD")
+    !inherits(IM, "SD") & (include_diversion | !IM$hasDiversion)
   })
   names(InputsModel)[bSDs]
 }
@@ -44,11 +46,14 @@ getDataFromLocation <- function(loc, sv) {
   if (length(grep("\\[[0-9]+\\]$", loc)) > 0) {
     stop("Reaching output of other controller is not implemented yet")
   } else {
-    node <- sv$griwrm$down[sv$griwrm$id == loc]
-    if(is.na(node)) {
-      # Downstream node: simulated flow at last supervision time step (bug #40)
-      sv$OutputsModel[[loc]]$Qsim_m3
+    if(sv$nodeProperties[[loc]]["hydrology"] != "DirectInjection") {
+      if (sv$nodeProperties[[loc]]$Upstream) {
+        sv$OutputsModel[[loc]]$Qsim_m3[sv$ts.previous]
+      } else {
+        sv$OutputsModel[[loc]]$Qsim_m3
+      }
     } else {
+      node <- sv$griwrm$down[sv$griwrm$id == loc]
       sv$InputsModel[[node]]$Qupstream[sv$ts.index0 + sv$ts.previous, loc]
     }
   }
@@ -64,13 +69,22 @@ getDataFromLocation <- function(loc, sv) {
 #' @noRd
 setDataToLocation <- function(ctrlr, sv) {
   l <- lapply(seq(length(ctrlr$Unames)), function(i) {
-    node <- sv$griwrm$down[sv$griwrm$id == ctrlr$Unames[i]]
     # limit U size to the number of simulation time steps of the current supervision time step
     U <- ctrlr$U[seq.int(length(sv$ts.index)),i]
-    # ! Qupstream contains warm up period and run period => the index is shifted
-    if(!is.null(sv$InputsModel[[node]])) {
-      sv$InputsModel[[node]]$Qupstream[sv$ts.index0 + sv$ts.index,
-                                       ctrlr$Unames[i]] <- U
+
+    locU <- ctrlr$Unames[i]
+    if (sv$nodeProperties[[locU]]$DirectInjection) {
+      # Direct injection node => update Qusptream of downstream node
+      node <- sv$griwrm4U$down[sv$griwrm4U$id == locU]
+      # ! Qupstream contains warm up period and run period => the index is shifted
+      if(!is.null(sv$InputsModel[[node]])) {
+        sv$InputsModel[[node]]$Qupstream[sv$ts.index0 + sv$ts.index, locU] <- U
+      }
+    } else if (sv$nodeProperties[[locU]]$Diversion){
+      # Diversion node => update Qdiv with -U
+      sv$InputsModel[[locU]]$Qdiv[sv$ts.index0 + sv$ts.index] <- -U
+    } else {
+      stop("Node ", locU, " must be a Direct Injection or a Diversion node")
     }
   })
 }
@@ -94,6 +108,21 @@ doSupervision <- function(supervisor) {
     if(is.vector(supervisor$controllers[[id]]$U)) {
       supervisor$controllers[[id]]$U <- matrix(supervisor$controllers[[id]]$U, nrow = 1)
     }
+    # Check U output
+    if (
+      ncol(supervisor$controllers[[id]]$U) != length(supervisor$controllers[[id]]$Unames) |
+      (!nrow(supervisor$controllers[[id]]$U) %in% c(supervisor$.TimeStep, length(supervisor$ts.index)))
+      ) {
+      stop("The logic function of the controller ",
+           supervisor$controllers[[id]]$name,
+          " should return a matrix of dimension ",
+          supervisor$.TimeStep, ", ", length(supervisor$controllers[[id]]$Unames))
+    }
+    # For the last supervisor time step which can be truncated
+    if (length(supervisor$ts.index) < supervisor$.TimeStep) {
+      supervisor$controllers[[id]]$U <-
+        supervisor$controllers[[id]]$U[seq(length(supervisor$ts.index)), ]
+    }
     # Write U to locations in the model
     setDataToLocation(supervisor$controllers[[id]], sv = supervisor)
   }
@@ -133,23 +162,22 @@ checkRunModelParameters <- function(InputsModel, RunOptions, Param) {
 OutputsModelQsim <- function(InputsModel, OutputsModel, IndPeriod_Run) {
   griwrm <- attr(InputsModel, "GRiwrm")
   # Get simulated flow for each node
-  # Flow for each node is available in InputsModel$Qupstream except for the downstream node
-  upperNodes <- griwrm$id[!is.na(griwrm$down)]
+  # Flow for each node is available in OutputsModel except for Direct Injection
+  # nodes where it is stored in InputsModel$Qupstream of the downstream node
+  QsimRows <- getDiversionRows(griwrm, TRUE)
   lQsim <- lapply(
-    upperNodes,
-    function(x, griwrm, IndPeriod_Run) {
-      node <- griwrm$down[griwrm$id == x]
-      InputsModel[[node]]$Qupstream[IndPeriod_Run, x]
-    },
-    griwrm = griwrm, IndPeriod_Run = IndPeriod_Run
+    QsimRows,
+    function(i) {
+      x <- griwrm[i, ]
+      if (is.na(x$model)) {
+        InputsModel[[x$down]]$Qupstream[IndPeriod_Run, x$id]
+      } else {
+        OutputsModel[[x$id]]$Qsim_m3
+      }
+    }
   )
-  names(lQsim) <- upperNodes
-  # Flow of the downstream node is only available in OutputsModel[[node]]$Qsim
-  downNode <- names(InputsModel)[length(InputsModel)]
-  lQsim[[downNode]] <- OutputsModel[[downNode]]$Qsim_m3
-
-  names(lQsim) <- c(upperNodes, downNode)
-  dfQsim <- cbind(data.frame(DatesR = as.POSIXct(InputsModel[[1]]$DatesR[IndPeriod_Run])),
+  names(lQsim) <- griwrm$id[QsimRows]
+  dfQsim <- cbind(data.frame(DatesR = InputsModel[[1]]$DatesR[IndPeriod_Run]),
                   do.call(cbind,lQsim) / attr(InputsModel, "TimeStep"))
   class(dfQsim) <- c("Qm3s", class(dfQsim)) # For S3 methods
   return(dfQsim)
diff --git a/data-raw/Severn.R b/data-raw/Severn.R
index 5535ff91fc05663950a9fc17249e574eb632bdab..db720be1031c9481c2b04cb91611cba091d76c42 100644
--- a/data-raw/Severn.R
+++ b/data-raw/Severn.R
@@ -21,7 +21,7 @@ read_CAMELS_ts <- function(file, cut) {
   df <- read.csv(file)
   iCut <- which(df$date == cut)
   df <- df[iCut:nrow(df),]
-  df$DatesR <- as.POSIXct(df$date)
+  df$DatesR <- as.POSIXct(df$date, tz = "UTC")
 
   return(df[,c("DatesR", "precipitation", "peti", "discharge_spec")])
 }
diff --git a/data/Severn.rda b/data/Severn.rda
index 1d26cfd47d14b9716071c14f9346a4c05d61fbf5..1a6827656f3f7eeb2c655f4e5cc3cd5fdcab0aeb 100644
Binary files a/data/Severn.rda and b/data/Severn.rda differ
diff --git a/dev/pkgdown_build_site.R b/dev/pkgdown_build_site.R
new file mode 100644
index 0000000000000000000000000000000000000000..fdb3c170ad3ad204c84ecb3d5b8560dcca1bf99f
--- /dev/null
+++ b/dev/pkgdown_build_site.R
@@ -0,0 +1,2 @@
+remotes::install_gitlab("in-wop/seinebasin", host = "gitlab.irstea.fr")
+pkgdown::build_site("..")
diff --git a/man-examples/CreateGRiwrm.R b/man-examples/CreateGRiwrm.R
index 9ef97c074a3acb9b22aba2e8b03e361548e7b3a4..718deb6b1366893691883b1aa3635b43e3ccdc97 100644
--- a/man-examples/CreateGRiwrm.R
+++ b/man-examples/CreateGRiwrm.R
@@ -1,4 +1,6 @@
-# Network of 2 nodes distant of 150 km:
+#########################################
+# Network of 2 nodes distant of 150 km: #
+#########################################
 # - an upstream reservoir modelled as a direct flow injection (no model)
 # - a gauging station downstream a catchment of 360 km² modelled with GR4J
 db <- data.frame(id = c("Reservoir", "GaugingDown"),
@@ -12,7 +14,9 @@ griwrm_basic
 # Network diagram with direct flow node in red, intermediate sub-basin in green
 plot(griwrm_basic)
 
-# GR4J semi-distributed model of the Severn River
+###################################################
+# GR4J semi-distributed model of the Severn River #
+###################################################
 data(Severn)
 nodes <- Severn$BasinsInfo
 nodes$model <- "RunModel_GR4J"
@@ -26,7 +30,9 @@ griwrm_severn
 # Network diagram with upstream basin nodes in blue, intermediate sub-basin in green
 plot(griwrm_severn)
 
-# Same model with an ungauged station at nodes 54029 and 54001
+####################################################################
+# Severn network with an ungauged station at nodes 54029 and 54001 #
+####################################################################
 # By default the first gauged node at downstream is used for parameter calibration (54032)
 nodes_ungauged <- nodes
 nodes_ungauged$model[nodes_ungauged$gauge_id %in% c("54029", "54001")] <- "Ungauged"
@@ -35,3 +41,17 @@ griwrm_ungauged <- CreateGRiwrm(nodes_ungauged, rename_columns)
 griwrm_ungauged
 # Network diagram with gauged nodes of vivid color, and ungauged nodes of dull color
 plot(griwrm_ungauged)
+
+#######################################################
+# Severn network with a Diversion on the node "54029" #
+# which transfer flows to the node "54001"            #
+#######################################################
+nodes_div <- nodes[, c("gauge_id", "downstream_id", "distance_downstream", "model", "area")]
+nodes_div <- rbind(nodes_div, data.frame(gauge_id = "54029",
+                                         downstream_id = "54001",
+                                         distance_downstream = 20,
+                                         model = "Diversion",
+                                         area = NA))
+griwrm_div <- CreateGRiwrm(nodes_div, rename_columns)
+# Network diagram figures Diversion node by a red frame and a red arrow
+plot(griwrm_div)
diff --git a/man-examples/RunModel.GRiwrmInputsModel.R b/man-examples/RunModel.GRiwrmInputsModel.R
new file mode 100644
index 0000000000000000000000000000000000000000..c84a96a8048755b34dc6a9e936fef0184114e70b
--- /dev/null
+++ b/man-examples/RunModel.GRiwrmInputsModel.R
@@ -0,0 +1,210 @@
+###################################################################
+# Run the `airGR::RunModel_Lag` example in the GRiwrm fashion way #
+# Simulation of a reservoir with a purpose of low-flow mitigation #
+###################################################################
+
+## ---- preparation of the InputsModel object
+
+## loading package and catchment data
+library(airGRiwrm)
+data(L0123001)
+
+## ---- specifications of the reservoir
+
+## the reservoir withdraws 1 m3/s when it's possible considering the flow observed in the basin
+Qupstream <- matrix(-sapply(BasinObs$Qls / 1000 - 1, function(x) {
+  min(1, max(0, x, na.rm = TRUE))
+}), ncol = 1)
+
+## except between July and September when the reservoir releases 3 m3/s for low-flow mitigation
+month <- as.numeric(format(BasinObs$DatesR, "%m"))
+Qupstream[month >= 7 & month <= 9] <- 3
+Qupstream <- Qupstream * 86400 ## Conversion in m3/day
+
+## the reservoir is not an upstream subcachment: its areas is NA
+BasinAreas <- c(NA, BasinInfo$BasinArea)
+
+## delay time between the reservoir and the catchment outlet is 2 days and the distance is 150 km
+LengthHydro <- 150
+## with a delay of 2 days for 150 km, the flow velocity is 75 km per day
+Velocity <- (LengthHydro * 1e3 / 2) / (24 * 60 * 60) ## Conversion km/day -> m/s
+
+# This example is a network of 2 nodes which can be describe like this:
+db <- data.frame(id = c("Reservoir", "GaugingDown"),
+                 length = c(LengthHydro, NA),
+                 down = c("GaugingDown", NA),
+                 area = c(NA, BasinInfo$BasinArea),
+                 model = c(NA, "RunModel_GR4J"),
+                 stringsAsFactors = FALSE)
+
+# Create GRiwrm object from the data.frame
+griwrm <- CreateGRiwrm(db)
+str(griwrm)
+
+# Formatting observations for the hydrological models
+# Each input data should be a matrix or a data.frame with the good id in the name of the column
+Precip <- matrix(BasinObs$P, ncol = 1)
+colnames(Precip) <- "GaugingDown"
+PotEvap <- matrix(BasinObs$E, ncol = 1)
+colnames(PotEvap) <- "GaugingDown"
+
+# Observed flows contain flows that are directly injected in the model
+Qobs = matrix(Qupstream, ncol = 1)
+colnames(Qobs) <- "Reservoir"
+
+# Creation of the GRiwrmInputsModel object (= a named list of InputsModel objects)
+InputsModels <- CreateInputsModel(griwrm,
+                            DatesR = BasinObs$DatesR,
+                            Precip = Precip,
+                            PotEvap = PotEvap,
+                            Qobs = Qobs)
+str(InputsModels)
+
+## run period selection
+Ind_Run <- seq(which(format(BasinObs$DatesR, format = "%Y-%m-%d")=="1990-01-01"),
+               which(format(BasinObs$DatesR, format = "%Y-%m-%d")=="1999-12-31"))
+
+# Creation of the GRiwmRunOptions object
+RunOptions <- CreateRunOptions(InputsModels,
+                                IndPeriod_Run = Ind_Run)
+str(RunOptions)
+
+# Parameters of the SD models should be encapsulated in a named list
+ParamGR4J <- c(X1 = 257.238, X2 = 1.012, X3 = 88.235, X4 = 2.208)
+Param <- list(`GaugingDown` = c(Velocity, ParamGR4J))
+
+# RunModel for the whole network
+OutputsModels <- RunModel(InputsModels,
+                          RunOptions = RunOptions,
+                          Param = Param)
+str(OutputsModels)
+
+# Compare regimes of the simulation with reservoir and observation of natural flow
+plot(OutputsModels,
+     data.frame(GaugingDown = BasinObs$Qmm[Ind_Run]),
+     which = "Regime")
+
+# Plot together simulated flows (m3/s) of the reservoir and the gauging station
+plot(attr(OutputsModels, "Qm3s"))
+
+
+########################################################
+# Run the Severn example provided with this package    #
+# A natural catchment composed with 6 gauging stations #
+########################################################
+
+data(Severn)
+nodes <- Severn$BasinsInfo
+nodes$model <- "RunModel_GR4J"
+# Mismatch column names are renamed to stick with GRiwrm requirements
+rename_columns <- list(id = "gauge_id",
+                       down = "downstream_id",
+                       length = "distance_downstream")
+g_severn <- CreateGRiwrm(nodes, rename_columns)
+
+# Network diagram with upstream basin nodes in blue, intermediate sub-basin in green
+plot(g_severn)
+
+# Format CAMEL-GB meteorological dataset for airGRiwrm inputs
+BasinsObs <- Severn$BasinsObs
+DatesR <- BasinsObs[[1]]$DatesR
+PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
+PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
+
+# Precipitation and Potential Evaporation are related to the whole catchment
+# at each gauging station. We need to compute them for intermediate catchments
+# for use in a semi-distributed model
+Precip <- ConvertMeteoSD(g_severn, PrecipTot)
+PotEvap <- ConvertMeteoSD(g_severn, PotEvapTot)
+
+# CreateInputsModel object
+IM_severn <- CreateInputsModel(g_severn, DatesR, Precip, PotEvap)
+
+# GRiwrmRunOptions object
+# Run period is set aside the one-year warm-up period
+IndPeriod_Run <- seq(
+  which(IM_severn[[1]]$DatesR == (IM_severn[[1]]$DatesR[1] + 365*24*60*60)),
+  length(IM_severn[[1]]$DatesR) # Until the end of the time series
+)
+IndPeriod_WarmUp <- seq(1, IndPeriod_Run[1] - 1)
+
+RO_severn <- CreateRunOptions(
+  IM_severn,
+  IndPeriod_WarmUp = IndPeriod_WarmUp,
+  IndPeriod_Run = IndPeriod_Run
+)
+
+# Load parameters of the model from Calibration in vignette V02
+P_severn <- readRDS(system.file("vignettes", "ParamV02.RDS", package = "airGRiwrm"))
+
+# Run the simulation
+OM_severn <- RunModel(IM_severn,
+                          RunOptions = RO_severn,
+                          Param = P_severn)
+
+# Plot results of simulated flows in m3/s
+Qm3s <- attr(OM_severn, "Qm3s")
+plot(Qm3s[1:150, ])
+
+
+##################################################################
+# An example of water withdrawal for irrigation with restriction #
+# modeled with a Diversion node on the Severn river              #
+##################################################################
+
+# A diversion is added at gauging station "54001"
+nodes_div <- nodes[,  c("gauge_id", "downstream_id", "distance_downstream", "area", "model")]
+names(nodes_div) <- c("id", "down", "length", "area", "model")
+nodes_div <- rbind(nodes_div,
+                   data.frame(id = "54001", # location of the diversion
+                              down = NA,    # the abstracted flow goes outside
+                              length = NA,  # down=NA, so length=NA
+                              area = NA,    # no area, diverted flow is in m3/day
+                              model = "Diversion"))
+
+g_div <- CreateGRiwrm(nodes_div)
+# The node "54001" is surrounded in red to show the diverted node
+plot(g_div)
+
+# Computation of the irrigation withdraw objective
+irrigMonthlyPlanning <- c(0.0, 0.0, 1.2, 2.4, 3.2, 3.6, 3.6, 2.8, 1.8, 0.0, 0.0, 0.0)
+names(irrigMonthlyPlanning) <- month.abb
+irrigMonthlyPlanning
+DatesR_month <- as.numeric(format(DatesR, "%m"))
+# Withdrawn flow calculated for each day is negative
+Qirrig <- matrix(-irrigMonthlyPlanning[DatesR_month] * 86400, ncol = 1)
+colnames(Qirrig) <- "54001"
+
+# Minimum flow to remain downstream the diversion is 12 m3/s
+Qmin <- matrix(12 * 86400, nrow = length(DatesR), ncol = 1)
+colnames(Qmin) = "54001"
+
+# Creation of GRimwrInputsModel object
+IM_div <- CreateInputsModel(g_div, DatesR, Precip, PotEvap, Qobs = Qirrig, Qmin = Qmin)
+
+# RunOptions and parameters are unchanged, we can directly run the simulation
+OM_div <- RunModel(IM_div,
+                   RunOptions = RO_severn,
+                   Param = P_severn)
+
+# Retrieve diverted flow at "54001" and convert it from m3/day to m3/s
+Qdiv_m3s <- OM_div$`54001`$Qdiv_m3 / 86400
+
+# Plot the diverted flow for the year 2003
+Ind_Plot <- which(
+  OM_div[[1]]$DatesR >= as.POSIXct("2003-01-01", tz = "UTC") &
+  OM_div[[1]]$DatesR <= as.POSIXct("2003-12-31", tz = "UTC")
+)
+dfQdiv <- data.frame(DatesR = OM_div[[1]]$DatesR[Ind_Plot],
+                     Diverted_flow = Qdiv_m3s[Ind_Plot])
+
+oldpar <- par(mfrow=c(2,1), mar = c(2.5,4,1,1))
+plot.Qm3s(dfQdiv)
+
+# Plot natural and influenced flow at station "54001"
+df54001 <- cbind(attr(OM_div, "Qm3s")[Ind_Plot, c("DatesR", "54001")],
+                 attr(OM_severn, "Qm3s")[Ind_Plot, "54001"])
+names(df54001) <- c("DatesR", "54001 with irrigation", "54001 natural flow")
+plot.Qm3s(df54001, ylim = c(0,70))
+abline(h = 12, col = "green")
+par(oldpar)
diff --git a/man-examples/RunModel.Supervisor.R b/man-examples/RunModel.Supervisor.R
new file mode 100644
index 0000000000000000000000000000000000000000..6eacf4f8e91e432492ae70a762af9265f93908ea
--- /dev/null
+++ b/man-examples/RunModel.Supervisor.R
@@ -0,0 +1,124 @@
+###############################################################################
+# An example of reservoir management on an hypothetical dam at station "54095"
+# on the Severn river build to support low-flows at "54057"
+###############################################################################
+# A minimum flow of 20 m3/s is maintained at the dam location and an extra-release
+# is provided when the flow at the downstream station "54057" cross a minimum
+# threshold of 45 m3/s. The dam has a storage capacity of 60 millions m3
+###############################################################################
+library(airGRiwrm)
+
+# Load Severn network information
+data(Severn)
+nodes <- Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")]
+nodes$model <- "RunModel_GR4J"
+
+# Insert a dam downstream the location the gauging station 54095
+# The dam is a direct injection node
+nodes$downstream_id[nodes$gauge_id == "54095"] <- "Dam"
+nodes$distance_downstream[nodes$gauge_id == "54095"] <- 0
+nodes <- rbind(nodes,
+               data.frame(gauge_id = "Dam",
+                          downstream_id = "54001",
+                          distance_downstream = 42,
+                          area = NA,
+                          model = NA))
+
+griwrm <- CreateGRiwrm(nodes,
+                 list(id = "gauge_id",
+                      down = "downstream_id",
+                      length = "distance_downstream"))
+plot(griwrm)
+
+# Format meteorological inputs for CreateInputs
+BasinsObs <- Severn$BasinsObs
+DatesR <- BasinsObs[[1]]$DatesR
+PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
+PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
+Precip <- ConvertMeteoSD(griwrm, PrecipTot)
+PotEvap <- ConvertMeteoSD(griwrm, PotEvapTot)
+
+# Create a release flow time series for the dam
+# This release will be modified by the Supervisor
+# We initiate it with the natural flow for having a good initialisation of the
+# model at the first time step of the running period
+Qobs <- data.frame(
+  Dam = BasinsObs$`54095`$discharge_spec * griwrm$area[griwrm$id == "54095"] * 1E3
+)
+Qobs[,] <- Qobs[which(DatesR == as.POSIXct("2002-10-01", tz = "UTC")), 1]
+
+# InputsModel object
+IM_severn <- CreateInputsModel(griwrm, DatesR, Precip, PotEvap, Qobs)
+
+# Initialisation of the Supervisor
+sv <- CreateSupervisor(IM_severn)
+
+# States of the reservoir are stored in the Supervisor variable
+# The Supervisor variable is an environment which can be available in
+# the controller function for storing and exchange data during the simulation
+sv$Vres <- 0 # Reservoir storage time series
+
+# Dam management is modeled by a controller
+# This controller usually releases Qmin and provides
+# extra release if flow mesured somewhere is below Qthreshold
+# Flow is expressed in m3 / time step
+# Y[1] = runoff flow at gauging station 54095 filling the reservoir
+# Y[2] = flow at gauging station 54057, location of the low-flow objective
+# The returned value is the release calculated at the reservoir
+# We need to enclose the Supervisor variable and other parameters in
+# the environment of the function with a function returning the logic function
+factoryDamLogic <- function(sv, Vmin, Vmax, Qmin, Qthreshold) {
+  function(Y) {
+    # Filling of the reservoir
+    sv$Vres <- c(sv$Vres, tail(sv$Vres, 1) + Y[1])
+    # The release is the max between: overflow, low-flow support and minimum flow
+    U <- U <- max(tail(sv$Vres, 1) - Vmax, Qthreshold - Y[2], Qmin)
+    sv$Vres[length(sv$Vres)] <- tail(sv$Vres, 1) - U
+    if (tail(sv$Vres, 1) < Vmin) {
+      # Reservoir is empty
+      U <- U - (Vmin - tail(sv$Vres, 1))
+      sv$Vres[length(sv$Vres)] <- Vmin
+    }
+    return(U)
+  }
+}
+
+# And define a final function enclosing logic and parameters together
+funDamLogic <- factoryDamLogic(
+  sv = sv, # The Supervisor which store the states of reservoir storage
+  Vmin = 0, # Minimum volume in the reservoir (m3)
+  Vmax = 60 * 1E6, # Maximum volume in the reservoir (m3)
+  Qmin = 20 * 86400, # Min flow to maintain downstream the reservoir (m3/day)
+  Qthreshold = 45 * 86400 # Min flow threshold to support at station 54057 (m3/day)
+)
+
+CreateController(sv, "DamRelease", Y = c("54095", "54057"), U = c("Dam"), FUN = funDamLogic)
+
+# GRiwrmRunOptions object simulation of the hydrological year 2002-2003
+IndPeriod_Run <- which(
+  DatesR >= as.POSIXct("2002-10-15", tz = "UTC") &
+  DatesR <= as.POSIXct("2003-10-15", tz = "UTC")
+)
+IndPeriod_WarmUp <- seq.int(IndPeriod_Run[1] - 366, IndPeriod_Run[1] - 1)
+RO_severn <- CreateRunOptions(
+  IM_severn,
+  IndPeriod_WarmUp = IndPeriod_WarmUp,
+  IndPeriod_Run = IndPeriod_Run
+)
+
+# Load parameters of the model from Calibration in vignette V02
+P_severn <- readRDS(system.file("vignettes", "ParamV02.RDS", package = "airGRiwrm"))
+
+# The Supervisor is used instead of InputsModel for running the model
+OM_dam <- RunModel(sv,
+                      RunOptions = RO_severn,
+                      Param = P_severn)
+
+# Plotting the time series of flows and reservoir storage
+oldpar <- par(mfrow=c(2,1), mar = c(2.5,4,1,1))
+plot(attr(OM_dam, "Qm3s")[, c("DatesR", "54095", "Dam", "54057")],
+     ylim = c(0, 200))
+Vres <- data.frame(DatesR = attr(OM_dam, "Qm3s")$DatesR,
+                   V_reservoir = sv$Vres)
+plot.Qm3s(Vres)
+par(oldpar)
diff --git a/man/CreateController.Rd b/man/CreateController.Rd
index 75eb2d4ed9bea474d55eee25a575e7aec291e558..93c1021881deccf5b70c0c29573c50d042492f12 100644
--- a/man/CreateController.Rd
+++ b/man/CreateController.Rd
@@ -43,26 +43,128 @@ for the previous time step and returns calculated \code{U}. These \code{U} will
 at their location for the current time step of calculation of the model.
 }
 \examples{
-# First create a Supervisor from a model
+###############################################################################
+# An example of reservoir management on an hypothetical dam at station "54095"
+# on the Severn river build to support low-flows at "54057"
+###############################################################################
+# A minimum flow of 20 m3/s is maintained at the dam location and an extra-release
+# is provided when the flow at the downstream station "54057" cross a minimum
+# threshold of 45 m3/s. The dam has a storage capacity of 60 millions m3
+###############################################################################
+library(airGRiwrm)
+
+# Load Severn network information
 data(Severn)
 nodes <- Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")]
 nodes$model <- "RunModel_GR4J"
+
+# Insert a dam downstream the location the gauging station 54095
+# The dam is a direct injection node
+nodes$downstream_id[nodes$gauge_id == "54095"] <- "Dam"
+nodes$distance_downstream[nodes$gauge_id == "54095"] <- 0
+nodes <- rbind(nodes,
+               data.frame(gauge_id = "Dam",
+                          downstream_id = "54001",
+                          distance_downstream = 42,
+                          area = NA,
+                          model = NA))
+
 griwrm <- CreateGRiwrm(nodes,
                  list(id = "gauge_id",
                       down = "downstream_id",
                       length = "distance_downstream"))
+plot(griwrm)
+
+# Format meteorological inputs for CreateInputs
 BasinsObs <- Severn$BasinsObs
 DatesR <- BasinsObs[[1]]$DatesR
 PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
 PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
-Qobs <- cbind(sapply(BasinsObs, function(x) {x$discharge_spec}))
 Precip <- ConvertMeteoSD(griwrm, PrecipTot)
 PotEvap <- ConvertMeteoSD(griwrm, PotEvapTot)
-InputsModel <- CreateInputsModel(griwrm, DatesR, Precip, PotEvap, Qobs)
-sv <- CreateSupervisor(InputsModel)
 
-# A controller which usually releases 0.1 m3/s and provides
-# extra release if the downstream flow is below 0.5 m3/s
-logicDamRelease <- function(Y) max(0.5 - Y[1], 0.1)
-CreateController(sv, "DamRelease", Y = c("54001"), U = c("54095"), FUN = logicDamRelease)
+# Create a release flow time series for the dam
+# This release will be modified by the Supervisor
+# We initiate it with the natural flow for having a good initialisation of the
+# model at the first time step of the running period
+Qobs <- data.frame(
+  Dam = BasinsObs$`54095`$discharge_spec * griwrm$area[griwrm$id == "54095"] * 1E3
+)
+Qobs[,] <- Qobs[which(DatesR == as.POSIXct("2002-10-01", tz = "UTC")), 1]
+
+# InputsModel object
+IM_severn <- CreateInputsModel(griwrm, DatesR, Precip, PotEvap, Qobs)
+
+# Initialisation of the Supervisor
+sv <- CreateSupervisor(IM_severn)
+
+# States of the reservoir are stored in the Supervisor variable
+# The Supervisor variable is an environment which can be available in
+# the controller function for storing and exchange data during the simulation
+sv$Vres <- 0 # Reservoir storage time series
+
+# Dam management is modeled by a controller
+# This controller usually releases Qmin and provides
+# extra release if flow mesured somewhere is below Qthreshold
+# Flow is expressed in m3 / time step
+# Y[1] = runoff flow at gauging station 54095 filling the reservoir
+# Y[2] = flow at gauging station 54057, location of the low-flow objective
+# The returned value is the release calculated at the reservoir
+# We need to enclose the Supervisor variable and other parameters in
+# the environment of the function with a function returning the logic function
+factoryDamLogic <- function(sv, Vmin, Vmax, Qmin, Qthreshold) {
+  function(Y) {
+    # Filling of the reservoir
+    sv$Vres <- c(sv$Vres, tail(sv$Vres, 1) + Y[1])
+    # The release is the max between: overflow, low-flow support and minimum flow
+    U <- U <- max(tail(sv$Vres, 1) - Vmax, Qthreshold - Y[2], Qmin)
+    sv$Vres[length(sv$Vres)] <- tail(sv$Vres, 1) - U
+    if (tail(sv$Vres, 1) < Vmin) {
+      # Reservoir is empty
+      U <- U - (Vmin - tail(sv$Vres, 1))
+      sv$Vres[length(sv$Vres)] <- Vmin
+    }
+    return(U)
+  }
+}
+
+# And define a final function enclosing logic and parameters together
+funDamLogic <- factoryDamLogic(
+  sv = sv, # The Supervisor which store the states of reservoir storage
+  Vmin = 0, # Minimum volume in the reservoir (m3)
+  Vmax = 60 * 1E6, # Maximum volume in the reservoir (m3)
+  Qmin = 20 * 86400, # Min flow to maintain downstream the reservoir (m3/day)
+  Qthreshold = 45 * 86400 # Min flow threshold to support at station 54057 (m3/day)
+)
+
+CreateController(sv, "DamRelease", Y = c("54095", "54057"), U = c("Dam"), FUN = funDamLogic)
+
+# GRiwrmRunOptions object simulation of the hydrological year 2002-2003
+IndPeriod_Run <- which(
+  DatesR >= as.POSIXct("2002-10-15", tz = "UTC") &
+  DatesR <= as.POSIXct("2003-10-15", tz = "UTC")
+)
+IndPeriod_WarmUp <- seq.int(IndPeriod_Run[1] - 366, IndPeriod_Run[1] - 1)
+RO_severn <- CreateRunOptions(
+  IM_severn,
+  IndPeriod_WarmUp = IndPeriod_WarmUp,
+  IndPeriod_Run = IndPeriod_Run
+)
+
+# Load parameters of the model from Calibration in vignette V02
+P_severn <- readRDS(system.file("vignettes", "ParamV02.RDS", package = "airGRiwrm"))
+
+# The Supervisor is used instead of InputsModel for running the model
+OM_dam <- RunModel(sv,
+                      RunOptions = RO_severn,
+                      Param = P_severn)
+
+# Plotting the time series of flows and reservoir storage
+oldpar <- par(mfrow=c(2,1), mar = c(2.5,4,1,1))
+plot(attr(OM_dam, "Qm3s")[, c("DatesR", "54095", "Dam", "54057")],
+     ylim = c(0, 200))
+Vres <- data.frame(DatesR = attr(OM_dam, "Qm3s")$DatesR,
+                   V_reservoir = sv$Vres)
+plot.Qm3s(Vres)
+par(oldpar)
 }
diff --git a/man/CreateGRiwrm.Rd b/man/CreateGRiwrm.Rd
index 24d40194789be032f734d5425a6b9c16cc052407..f2ee4db078b466de81be4b225cb94036b87da3b3 100644
--- a/man/CreateGRiwrm.Rd
+++ b/man/CreateGRiwrm.Rd
@@ -62,16 +62,22 @@ The "model" column should be filled by one of the following:
 \itemize{
 \item One of the hydrological models available in the \emph{airGR} package defined by its
 \code{RunModel} function (i.e.: \code{RunModel_GR4J}, \code{RunModel_GR5HCemaneige}...)
-\item \code{NA} for injecting (or abstracting) a flow time series at the location of the node
-(direct flow injection)
 \item \code{Ungauged} for an ungauged node. The sub-basin inherits hydrological model and
 parameters from a "donor" sub-basin. By default the donor is the first gauged
 node at downstream
+\item \code{NA} for injecting (or abstracting) a flow time series at the location of the node
+(direct flow injection)
+\item \code{Diversion} for abstracting a flow time series from an existing node transfer it
+to another node. As a \code{Diversion} is attached to an existing node, this node is
+then described with 2 lines: one for the hydrological model and another one for the
+diversion
 }
 }
 }
 \examples{
-# Network of 2 nodes distant of 150 km:
+#########################################
+# Network of 2 nodes distant of 150 km: #
+#########################################
 # - an upstream reservoir modelled as a direct flow injection (no model)
 # - a gauging station downstream a catchment of 360 km² modelled with GR4J
 db <- data.frame(id = c("Reservoir", "GaugingDown"),
@@ -85,7 +91,9 @@ griwrm_basic
 # Network diagram with direct flow node in red, intermediate sub-basin in green
 plot(griwrm_basic)
 
-# GR4J semi-distributed model of the Severn River
+###################################################
+# GR4J semi-distributed model of the Severn River #
+###################################################
 data(Severn)
 nodes <- Severn$BasinsInfo
 nodes$model <- "RunModel_GR4J"
@@ -99,7 +107,9 @@ griwrm_severn
 # Network diagram with upstream basin nodes in blue, intermediate sub-basin in green
 plot(griwrm_severn)
 
-# Same model with an ungauged station at nodes 54029 and 54001
+####################################################################
+# Severn network with an ungauged station at nodes 54029 and 54001 #
+####################################################################
 # By default the first gauged node at downstream is used for parameter calibration (54032)
 nodes_ungauged <- nodes
 nodes_ungauged$model[nodes_ungauged$gauge_id \%in\% c("54029", "54001")] <- "Ungauged"
@@ -108,4 +118,18 @@ griwrm_ungauged <- CreateGRiwrm(nodes_ungauged, rename_columns)
 griwrm_ungauged
 # Network diagram with gauged nodes of vivid color, and ungauged nodes of dull color
 plot(griwrm_ungauged)
+
+#######################################################
+# Severn network with a Diversion on the node "54029" #
+# which transfer flows to the node "54001"            #
+#######################################################
+nodes_div <- nodes[, c("gauge_id", "downstream_id", "distance_downstream", "model", "area")]
+nodes_div <- rbind(nodes_div, data.frame(gauge_id = "54029",
+                                         downstream_id = "54001",
+                                         distance_downstream = 20,
+                                         model = "Diversion",
+                                         area = NA))
+griwrm_div <- CreateGRiwrm(nodes_div, rename_columns)
+# Network diagram figures Diversion node by a red frame and a red arrow
+plot(griwrm_div)
 }
diff --git a/man/CreateInputsModel.GRiwrm.Rd b/man/CreateInputsModel.GRiwrm.Rd
index 29aaf5501b2ac4fc76b713fae301ab854f271857..9a438b0061505b4c1de25efb53f0d3191ffb97bc 100644
--- a/man/CreateInputsModel.GRiwrm.Rd
+++ b/man/CreateInputsModel.GRiwrm.Rd
@@ -10,6 +10,7 @@
   Precip = NULL,
   PotEvap = NULL,
   Qobs = NULL,
+  Qmin = NULL,
   PrecipScale = TRUE,
   TempMean = NULL,
   TempMin = NULL,
@@ -25,38 +26,79 @@
 
 \item{DatesR}{\link{POSIXt} vector of dates}
 
-\item{Precip}{(optional) \link{matrix} or \link{data.frame} frame of numeric containing precipitation in [mm per time step]. Column names correspond to node IDs}
+\item{Precip}{(optional) \link{matrix} or \link{data.frame} of \link{numeric} containing
+precipitation in [mm per time step]. Column names correspond to node IDs}
 
-\item{PotEvap}{(optional) \link{matrix} or \link{data.frame} frame of numeric containing potential evaporation [mm per time step]. Column names correspond to node IDs}
+\item{PotEvap}{(optional) \link{matrix} or \link{data.frame} of \link{numeric} containing
+potential evaporation [mm per time step]. Column names correspond to node IDs}
 
-\item{Qobs}{(optional) \link{matrix} or \link{data.frame} frame of numeric containing observed flows in [mm per time step]. Column names correspond to node IDs}
+\item{Qobs}{(optional) \link{matrix} or \link{data.frame} of \link{numeric} containing
+observed flows. It must be provided only for nodes of type "Direct
+injection" and "Diversion". See \link{CreateGRiwrm} for
+details about these node types. Unit is [mm per time step] for nodes
+with an area, and [m3 per time step] for nodes with \code{area=NA}.
+Column names correspond to node IDs. Negative flows are abstracted from
+the model and positive flows are injected to the model}
 
-\item{PrecipScale}{(optional) named \link{vector} of \link{logical} indicating if the mean of the precipitation interpolated on the elevation layers must be kept or not, required to create CemaNeige module inputs, default \code{TRUE} (the mean of the precipitation is kept to the original value)}
+\item{Qmin}{(optional) \link{matrix} or \link{data.frame} of \link{numeric} containing
+minimum flows to let downstream of a node with a Diversion [m3 per
+time step]. Default is zero. Column names correspond to node IDs}
 
-\item{TempMean}{(optional) \link{matrix} or \link{data.frame} of time series of mean air temperature [°C], required to create the CemaNeige module inputs}
+\item{PrecipScale}{(optional) named \link{vector} of \link{logical} indicating if the
+mean of the precipitation interpolated on the elevation layers must be
+kept or not, required to create CemaNeige module inputs, default \code{TRUE}
+(the mean of the precipitation is kept to the original value)}
 
-\item{TempMin}{(optional) \link{matrix} or \link{data.frame} of time series of minimum air temperature [°C], possibly used to create the CemaNeige module inputs}
+\item{TempMean}{(optional) \link{matrix} or \link{data.frame} of time series of mean
+air temperature [°C], required to create the CemaNeige module inputs}
 
-\item{TempMax}{(optional) \link{matrix} or \link{data.frame} of time series of maximum air temperature [°C], possibly used to create the CemaNeige module inputs}
+\item{TempMin}{(optional) \link{matrix} or \link{data.frame} of time series of minimum
+air temperature [°C], possibly used to create the CemaNeige module inputs}
 
-\item{ZInputs}{(optional) named \link{vector} of \link{numeric} giving the mean elevation of the Precip and Temp series (before extrapolation) [m], possibly used to create the CemaNeige module input}
+\item{TempMax}{(optional) \link{matrix} or \link{data.frame} of time series of maximum
+air temperature [°C], possibly used to create the CemaNeige module inputs}
 
-\item{HypsoData}{(optional) \link{matrix} or \link{data.frame} containing 101 \link{numeric} rows: min, q01 to q99 and max of catchment elevation distribution [m], if not defined a single elevation is used for CemaNeige}
+\item{ZInputs}{(optional) named \link{vector} of \link{numeric} giving the mean
+elevation of the Precip and Temp series (before extrapolation) [m],
+possibly used to create the CemaNeige module input}
 
-\item{NLayers}{(optional) named \link{vector} of \link{numeric} integer giving the number of elevation layers requested \link{-}, required to create CemaNeige module inputs, default=5}
+\item{HypsoData}{(optional) \link{matrix} or \link{data.frame} containing 101 \link{numeric}
+rows: min, q01 to q99 and max of catchment elevation distribution [m],
+if not defined a single elevation is used for CemaNeige}
+
+\item{NLayers}{(optional) named \link{vector} of \link{numeric} integer giving the number
+of elevation layers requested \link{-}, required to create CemaNeige module
+inputs, default=5}
 
 \item{...}{used for compatibility with S3 methods}
 }
 \value{
-A \emph{GRiwrmInputsModel} object which is a list of \emph{InputsModel} objects created by \link[airGR:CreateInputsModel]{airGR::CreateInputsModel} with one item per modeled sub-catchment.
+A \emph{GRiwrmInputsModel} object which is a list of \emph{InputsModel}
+objects created by \link[airGR:CreateInputsModel]{airGR::CreateInputsModel} with one item per modeled sub-catchment.
 }
 \description{
 Creation of an InputsModel object for a \strong{airGRiwrm} network
 }
 \details{
-Meteorological data are needed for the nodes of the network that represent a catchment simulated by a rainfall-runoff model. Instead of \link[airGR:CreateInputsModel]{airGR::CreateInputsModel} that has \link{numeric} \link{vector} as time series inputs, this function uses \link{matrix} or \link{data.frame} with the id of the sub-catchment as column names. For single values (\code{ZInputs} or \code{NLayers}), the function requires named \link{vector} with the id of the sub-catchment as name item. If an argument is optional, only the column or the named item has to be provided.
+Meteorological data are needed for the nodes of the network that
+represent a catchment simulated by a rainfall-runoff model. Instead of
+\link[airGR:CreateInputsModel]{airGR::CreateInputsModel} that has \link{numeric} \link{vector} as time series inputs,
+this function uses \link{matrix} or \link{data.frame} with the id of the sub-catchment
+as column names. For single values (\code{ZInputs} or \code{NLayers}), the function
+requires named \link{vector} with the id of the sub-catchment as name item. If an
+argument is optional, only the column or the named item has to be provided.
 
 See \link[airGR:CreateInputsModel]{airGR::CreateInputsModel} documentation for details concerning each input.
+
+Number of rows of \code{Precip}, \code{PotEvap}, \code{Qobs}, \code{Qmin}, \code{TempMean}, \code{TempMin},
+\code{TempMax} must be the same of the length of \code{DatesR} (each row corresponds to
+a time step defined in \code{DatesR}).
+
+For example of use of Direct Injection nodes, see vignettes
+"V03_Open-loop_influenced_flow" and "V04_Closed-loop_regulated_withdrawal".
+
+For example of use of Diversion nodes, see example below and vignette
+"V06_Modelling_regulated_diversion".
 }
 \examples{
 ###################################################################
@@ -125,7 +167,7 @@ str(InputsModels)
 Ind_Run <- seq(which(format(BasinObs$DatesR, format = "\%Y-\%m-\%d")=="1990-01-01"),
                which(format(BasinObs$DatesR, format = "\%Y-\%m-\%d")=="1999-12-31"))
 
-# Creation of the GriwmRunOptions object
+# Creation of the GRiwmRunOptions object
 RunOptions <- CreateRunOptions(InputsModels,
                                 IndPeriod_Run = Ind_Run)
 str(RunOptions)
@@ -140,6 +182,133 @@ OutputsModels <- RunModel(InputsModels,
                           Param = Param)
 str(OutputsModels)
 
-# Compare Simulation with reservoir and observation of natural flow
-plot(OutputsModels, data.frame(GaugingDown = BasinObs$Qmm[Ind_Run]))
+# Compare regimes of the simulation with reservoir and observation of natural flow
+plot(OutputsModels,
+     data.frame(GaugingDown = BasinObs$Qmm[Ind_Run]),
+     which = "Regime")
+
+# Plot together simulated flows (m3/s) of the reservoir and the gauging station
+plot(attr(OutputsModels, "Qm3s"))
+
+
+########################################################
+# Run the Severn example provided with this package    #
+# A natural catchment composed with 6 gauging stations #
+########################################################
+
+data(Severn)
+nodes <- Severn$BasinsInfo
+nodes$model <- "RunModel_GR4J"
+# Mismatch column names are renamed to stick with GRiwrm requirements
+rename_columns <- list(id = "gauge_id",
+                       down = "downstream_id",
+                       length = "distance_downstream")
+g_severn <- CreateGRiwrm(nodes, rename_columns)
+
+# Network diagram with upstream basin nodes in blue, intermediate sub-basin in green
+plot(g_severn)
+
+# Format CAMEL-GB meteorological dataset for airGRiwrm inputs
+BasinsObs <- Severn$BasinsObs
+DatesR <- BasinsObs[[1]]$DatesR
+PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
+PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
+
+# Precipitation and Potential Evaporation are related to the whole catchment
+# at each gauging station. We need to compute them for intermediate catchments
+# for use in a semi-distributed model
+Precip <- ConvertMeteoSD(g_severn, PrecipTot)
+PotEvap <- ConvertMeteoSD(g_severn, PotEvapTot)
+
+# CreateInputsModel object
+IM_severn <- CreateInputsModel(g_severn, DatesR, Precip, PotEvap)
+
+# GRiwrmRunOptions object
+# Run period is set aside the one-year warm-up period
+IndPeriod_Run <- seq(
+  which(IM_severn[[1]]$DatesR == (IM_severn[[1]]$DatesR[1] + 365*24*60*60)),
+  length(IM_severn[[1]]$DatesR) # Until the end of the time series
+)
+IndPeriod_WarmUp <- seq(1, IndPeriod_Run[1] - 1)
+
+RO_severn <- CreateRunOptions(
+  IM_severn,
+  IndPeriod_WarmUp = IndPeriod_WarmUp,
+  IndPeriod_Run = IndPeriod_Run
+)
+
+# Load parameters of the model from Calibration in vignette V02
+P_severn <- readRDS(system.file("vignettes", "ParamV02.RDS", package = "airGRiwrm"))
+
+# Run the simulation
+OM_severn <- RunModel(IM_severn,
+                          RunOptions = RO_severn,
+                          Param = P_severn)
+
+# Plot results of simulated flows in m3/s
+Qm3s <- attr(OM_severn, "Qm3s")
+plot(Qm3s[1:150, ])
+
+
+##################################################################
+# An example of water withdrawal for irrigation with restriction #
+# modeled with a Diversion node on the Severn river              #
+##################################################################
+
+# A diversion is added at gauging station "54001"
+nodes_div <- nodes[,  c("gauge_id", "downstream_id", "distance_downstream", "area", "model")]
+names(nodes_div) <- c("id", "down", "length", "area", "model")
+nodes_div <- rbind(nodes_div,
+                   data.frame(id = "54001", # location of the diversion
+                              down = NA,    # the abstracted flow goes outside
+                              length = NA,  # down=NA, so length=NA
+                              area = NA,    # no area, diverted flow is in m3/day
+                              model = "Diversion"))
+
+g_div <- CreateGRiwrm(nodes_div)
+# The node "54001" is surrounded in red to show the diverted node
+plot(g_div)
+
+# Computation of the irrigation withdraw objective
+irrigMonthlyPlanning <- c(0.0, 0.0, 1.2, 2.4, 3.2, 3.6, 3.6, 2.8, 1.8, 0.0, 0.0, 0.0)
+names(irrigMonthlyPlanning) <- month.abb
+irrigMonthlyPlanning
+DatesR_month <- as.numeric(format(DatesR, "\%m"))
+# Withdrawn flow calculated for each day is negative
+Qirrig <- matrix(-irrigMonthlyPlanning[DatesR_month] * 86400, ncol = 1)
+colnames(Qirrig) <- "54001"
+
+# Minimum flow to remain downstream the diversion is 12 m3/s
+Qmin <- matrix(12 * 86400, nrow = length(DatesR), ncol = 1)
+colnames(Qmin) = "54001"
+
+# Creation of GRimwrInputsModel object
+IM_div <- CreateInputsModel(g_div, DatesR, Precip, PotEvap, Qobs = Qirrig, Qmin = Qmin)
+
+# RunOptions and parameters are unchanged, we can directly run the simulation
+OM_div <- RunModel(IM_div,
+                   RunOptions = RO_severn,
+                   Param = P_severn)
+
+# Retrieve diverted flow at "54001" and convert it from m3/day to m3/s
+Qdiv_m3s <- OM_div$`54001`$Qdiv_m3 / 86400
+
+# Plot the diverted flow for the year 2003
+Ind_Plot <- which(
+  OM_div[[1]]$DatesR >= as.POSIXct("2003-01-01", tz = "UTC") &
+  OM_div[[1]]$DatesR <= as.POSIXct("2003-12-31", tz = "UTC")
+)
+dfQdiv <- data.frame(DatesR = OM_div[[1]]$DatesR[Ind_Plot],
+                     Diverted_flow = Qdiv_m3s[Ind_Plot])
+
+oldpar <- par(mfrow=c(2,1), mar = c(2.5,4,1,1))
+plot.Qm3s(dfQdiv)
+
+# Plot natural and influenced flow at station "54001"
+df54001 <- cbind(attr(OM_div, "Qm3s")[Ind_Plot, c("DatesR", "54001")],
+                 attr(OM_severn, "Qm3s")[Ind_Plot, "54001"])
+names(df54001) <- c("DatesR", "54001 with irrigation", "54001 natural flow")
+plot.Qm3s(df54001, ylim = c(0,70))
+abline(h = 12, col = "green")
+par(oldpar)
 }
diff --git a/man/CreateRunOptions.Rd b/man/CreateRunOptions.Rd
index d244dea0cb88e899186054ea87b6fe41ce6b0aef..51c0478531a6d9864f02d6f654f2b9dbce81ecdd 100644
--- a/man/CreateRunOptions.Rd
+++ b/man/CreateRunOptions.Rd
@@ -110,7 +110,7 @@ str(InputsModels)
 Ind_Run <- seq(which(format(BasinObs$DatesR, format = "\%Y-\%m-\%d")=="1990-01-01"),
                which(format(BasinObs$DatesR, format = "\%Y-\%m-\%d")=="1999-12-31"))
 
-# Creation of the GriwmRunOptions object
+# Creation of the GRiwmRunOptions object
 RunOptions <- CreateRunOptions(InputsModels,
                                 IndPeriod_Run = Ind_Run)
 str(RunOptions)
@@ -125,6 +125,133 @@ OutputsModels <- RunModel(InputsModels,
                           Param = Param)
 str(OutputsModels)
 
-# Compare Simulation with reservoir and observation of natural flow
-plot(OutputsModels, data.frame(GaugingDown = BasinObs$Qmm[Ind_Run]))
+# Compare regimes of the simulation with reservoir and observation of natural flow
+plot(OutputsModels,
+     data.frame(GaugingDown = BasinObs$Qmm[Ind_Run]),
+     which = "Regime")
+
+# Plot together simulated flows (m3/s) of the reservoir and the gauging station
+plot(attr(OutputsModels, "Qm3s"))
+
+
+########################################################
+# Run the Severn example provided with this package    #
+# A natural catchment composed with 6 gauging stations #
+########################################################
+
+data(Severn)
+nodes <- Severn$BasinsInfo
+nodes$model <- "RunModel_GR4J"
+# Mismatch column names are renamed to stick with GRiwrm requirements
+rename_columns <- list(id = "gauge_id",
+                       down = "downstream_id",
+                       length = "distance_downstream")
+g_severn <- CreateGRiwrm(nodes, rename_columns)
+
+# Network diagram with upstream basin nodes in blue, intermediate sub-basin in green
+plot(g_severn)
+
+# Format CAMEL-GB meteorological dataset for airGRiwrm inputs
+BasinsObs <- Severn$BasinsObs
+DatesR <- BasinsObs[[1]]$DatesR
+PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
+PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
+
+# Precipitation and Potential Evaporation are related to the whole catchment
+# at each gauging station. We need to compute them for intermediate catchments
+# for use in a semi-distributed model
+Precip <- ConvertMeteoSD(g_severn, PrecipTot)
+PotEvap <- ConvertMeteoSD(g_severn, PotEvapTot)
+
+# CreateInputsModel object
+IM_severn <- CreateInputsModel(g_severn, DatesR, Precip, PotEvap)
+
+# GRiwrmRunOptions object
+# Run period is set aside the one-year warm-up period
+IndPeriod_Run <- seq(
+  which(IM_severn[[1]]$DatesR == (IM_severn[[1]]$DatesR[1] + 365*24*60*60)),
+  length(IM_severn[[1]]$DatesR) # Until the end of the time series
+)
+IndPeriod_WarmUp <- seq(1, IndPeriod_Run[1] - 1)
+
+RO_severn <- CreateRunOptions(
+  IM_severn,
+  IndPeriod_WarmUp = IndPeriod_WarmUp,
+  IndPeriod_Run = IndPeriod_Run
+)
+
+# Load parameters of the model from Calibration in vignette V02
+P_severn <- readRDS(system.file("vignettes", "ParamV02.RDS", package = "airGRiwrm"))
+
+# Run the simulation
+OM_severn <- RunModel(IM_severn,
+                          RunOptions = RO_severn,
+                          Param = P_severn)
+
+# Plot results of simulated flows in m3/s
+Qm3s <- attr(OM_severn, "Qm3s")
+plot(Qm3s[1:150, ])
+
+
+##################################################################
+# An example of water withdrawal for irrigation with restriction #
+# modeled with a Diversion node on the Severn river              #
+##################################################################
+
+# A diversion is added at gauging station "54001"
+nodes_div <- nodes[,  c("gauge_id", "downstream_id", "distance_downstream", "area", "model")]
+names(nodes_div) <- c("id", "down", "length", "area", "model")
+nodes_div <- rbind(nodes_div,
+                   data.frame(id = "54001", # location of the diversion
+                              down = NA,    # the abstracted flow goes outside
+                              length = NA,  # down=NA, so length=NA
+                              area = NA,    # no area, diverted flow is in m3/day
+                              model = "Diversion"))
+
+g_div <- CreateGRiwrm(nodes_div)
+# The node "54001" is surrounded in red to show the diverted node
+plot(g_div)
+
+# Computation of the irrigation withdraw objective
+irrigMonthlyPlanning <- c(0.0, 0.0, 1.2, 2.4, 3.2, 3.6, 3.6, 2.8, 1.8, 0.0, 0.0, 0.0)
+names(irrigMonthlyPlanning) <- month.abb
+irrigMonthlyPlanning
+DatesR_month <- as.numeric(format(DatesR, "\%m"))
+# Withdrawn flow calculated for each day is negative
+Qirrig <- matrix(-irrigMonthlyPlanning[DatesR_month] * 86400, ncol = 1)
+colnames(Qirrig) <- "54001"
+
+# Minimum flow to remain downstream the diversion is 12 m3/s
+Qmin <- matrix(12 * 86400, nrow = length(DatesR), ncol = 1)
+colnames(Qmin) = "54001"
+
+# Creation of GRimwrInputsModel object
+IM_div <- CreateInputsModel(g_div, DatesR, Precip, PotEvap, Qobs = Qirrig, Qmin = Qmin)
+
+# RunOptions and parameters are unchanged, we can directly run the simulation
+OM_div <- RunModel(IM_div,
+                   RunOptions = RO_severn,
+                   Param = P_severn)
+
+# Retrieve diverted flow at "54001" and convert it from m3/day to m3/s
+Qdiv_m3s <- OM_div$`54001`$Qdiv_m3 / 86400
+
+# Plot the diverted flow for the year 2003
+Ind_Plot <- which(
+  OM_div[[1]]$DatesR >= as.POSIXct("2003-01-01", tz = "UTC") &
+  OM_div[[1]]$DatesR <= as.POSIXct("2003-12-31", tz = "UTC")
+)
+dfQdiv <- data.frame(DatesR = OM_div[[1]]$DatesR[Ind_Plot],
+                     Diverted_flow = Qdiv_m3s[Ind_Plot])
+
+oldpar <- par(mfrow=c(2,1), mar = c(2.5,4,1,1))
+plot.Qm3s(dfQdiv)
+
+# Plot natural and influenced flow at station "54001"
+df54001 <- cbind(attr(OM_div, "Qm3s")[Ind_Plot, c("DatesR", "54001")],
+                 attr(OM_severn, "Qm3s")[Ind_Plot, "54001"])
+names(df54001) <- c("DatesR", "54001 with irrigation", "54001 natural flow")
+plot.Qm3s(df54001, ylim = c(0,70))
+abline(h = 12, col = "green")
+par(oldpar)
 }
diff --git a/man/CreateSupervisor.Rd b/man/CreateSupervisor.Rd
index e3c95b7cb3b51c78b61d2eadeba5c1f823ca0e3c..053aa41c25ff3b4f114c217b7ff429ce03b292d1 100644
--- a/man/CreateSupervisor.Rd
+++ b/man/CreateSupervisor.Rd
@@ -25,20 +25,128 @@ A \code{Supervisor} object which is an \link{environment} containing all the nec
 Creation of a Supervisor for handling regulation in a model
 }
 \examples{
+###############################################################################
+# An example of reservoir management on an hypothetical dam at station "54095"
+# on the Severn river build to support low-flows at "54057"
+###############################################################################
+# A minimum flow of 20 m3/s is maintained at the dam location and an extra-release
+# is provided when the flow at the downstream station "54057" cross a minimum
+# threshold of 45 m3/s. The dam has a storage capacity of 60 millions m3
+###############################################################################
+library(airGRiwrm)
+
+# Load Severn network information
 data(Severn)
 nodes <- Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")]
 nodes$model <- "RunModel_GR4J"
+
+# Insert a dam downstream the location the gauging station 54095
+# The dam is a direct injection node
+nodes$downstream_id[nodes$gauge_id == "54095"] <- "Dam"
+nodes$distance_downstream[nodes$gauge_id == "54095"] <- 0
+nodes <- rbind(nodes,
+               data.frame(gauge_id = "Dam",
+                          downstream_id = "54001",
+                          distance_downstream = 42,
+                          area = NA,
+                          model = NA))
+
 griwrm <- CreateGRiwrm(nodes,
                  list(id = "gauge_id",
                       down = "downstream_id",
                       length = "distance_downstream"))
+plot(griwrm)
+
+# Format meteorological inputs for CreateInputs
 BasinsObs <- Severn$BasinsObs
 DatesR <- BasinsObs[[1]]$DatesR
 PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
 PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
-Qobs <- cbind(sapply(BasinsObs, function(x) {x$discharge_spec}))
 Precip <- ConvertMeteoSD(griwrm, PrecipTot)
 PotEvap <- ConvertMeteoSD(griwrm, PotEvapTot)
-InputsModel <- CreateInputsModel(griwrm, DatesR, Precip, PotEvap, Qobs)
-sv <- CreateSupervisor(InputsModel)
+
+# Create a release flow time series for the dam
+# This release will be modified by the Supervisor
+# We initiate it with the natural flow for having a good initialisation of the
+# model at the first time step of the running period
+Qobs <- data.frame(
+  Dam = BasinsObs$`54095`$discharge_spec * griwrm$area[griwrm$id == "54095"] * 1E3
+)
+Qobs[,] <- Qobs[which(DatesR == as.POSIXct("2002-10-01", tz = "UTC")), 1]
+
+# InputsModel object
+IM_severn <- CreateInputsModel(griwrm, DatesR, Precip, PotEvap, Qobs)
+
+# Initialisation of the Supervisor
+sv <- CreateSupervisor(IM_severn)
+
+# States of the reservoir are stored in the Supervisor variable
+# The Supervisor variable is an environment which can be available in
+# the controller function for storing and exchange data during the simulation
+sv$Vres <- 0 # Reservoir storage time series
+
+# Dam management is modeled by a controller
+# This controller usually releases Qmin and provides
+# extra release if flow mesured somewhere is below Qthreshold
+# Flow is expressed in m3 / time step
+# Y[1] = runoff flow at gauging station 54095 filling the reservoir
+# Y[2] = flow at gauging station 54057, location of the low-flow objective
+# The returned value is the release calculated at the reservoir
+# We need to enclose the Supervisor variable and other parameters in
+# the environment of the function with a function returning the logic function
+factoryDamLogic <- function(sv, Vmin, Vmax, Qmin, Qthreshold) {
+  function(Y) {
+    # Filling of the reservoir
+    sv$Vres <- c(sv$Vres, tail(sv$Vres, 1) + Y[1])
+    # The release is the max between: overflow, low-flow support and minimum flow
+    U <- U <- max(tail(sv$Vres, 1) - Vmax, Qthreshold - Y[2], Qmin)
+    sv$Vres[length(sv$Vres)] <- tail(sv$Vres, 1) - U
+    if (tail(sv$Vres, 1) < Vmin) {
+      # Reservoir is empty
+      U <- U - (Vmin - tail(sv$Vres, 1))
+      sv$Vres[length(sv$Vres)] <- Vmin
+    }
+    return(U)
+  }
+}
+
+# And define a final function enclosing logic and parameters together
+funDamLogic <- factoryDamLogic(
+  sv = sv, # The Supervisor which store the states of reservoir storage
+  Vmin = 0, # Minimum volume in the reservoir (m3)
+  Vmax = 60 * 1E6, # Maximum volume in the reservoir (m3)
+  Qmin = 20 * 86400, # Min flow to maintain downstream the reservoir (m3/day)
+  Qthreshold = 45 * 86400 # Min flow threshold to support at station 54057 (m3/day)
+)
+
+CreateController(sv, "DamRelease", Y = c("54095", "54057"), U = c("Dam"), FUN = funDamLogic)
+
+# GRiwrmRunOptions object simulation of the hydrological year 2002-2003
+IndPeriod_Run <- which(
+  DatesR >= as.POSIXct("2002-10-15", tz = "UTC") &
+  DatesR <= as.POSIXct("2003-10-15", tz = "UTC")
+)
+IndPeriod_WarmUp <- seq.int(IndPeriod_Run[1] - 366, IndPeriod_Run[1] - 1)
+RO_severn <- CreateRunOptions(
+  IM_severn,
+  IndPeriod_WarmUp = IndPeriod_WarmUp,
+  IndPeriod_Run = IndPeriod_Run
+)
+
+# Load parameters of the model from Calibration in vignette V02
+P_severn <- readRDS(system.file("vignettes", "ParamV02.RDS", package = "airGRiwrm"))
+
+# The Supervisor is used instead of InputsModel for running the model
+OM_dam <- RunModel(sv,
+                      RunOptions = RO_severn,
+                      Param = P_severn)
+
+# Plotting the time series of flows and reservoir storage
+oldpar <- par(mfrow=c(2,1), mar = c(2.5,4,1,1))
+plot(attr(OM_dam, "Qm3s")[, c("DatesR", "54095", "Dam", "54057")],
+     ylim = c(0, 200))
+Vres <- data.frame(DatesR = attr(OM_dam, "Qm3s")$DatesR,
+                   V_reservoir = sv$Vres)
+plot.Qm3s(Vres)
+par(oldpar)
 }
diff --git a/man/RunModel.GRiwrmInputsModel.Rd b/man/RunModel.GRiwrmInputsModel.Rd
index 80cc2f5b8cf9e035908fc4c8b483f2cdcca8ccf9..a87734567e37ae701cdfbea76d0696324bba1bf0 100644
--- a/man/RunModel.GRiwrmInputsModel.Rd
+++ b/man/RunModel.GRiwrmInputsModel.Rd
@@ -88,7 +88,7 @@ str(InputsModels)
 Ind_Run <- seq(which(format(BasinObs$DatesR, format = "\%Y-\%m-\%d")=="1990-01-01"),
                which(format(BasinObs$DatesR, format = "\%Y-\%m-\%d")=="1999-12-31"))
 
-# Creation of the GriwmRunOptions object
+# Creation of the GRiwmRunOptions object
 RunOptions <- CreateRunOptions(InputsModels,
                                 IndPeriod_Run = Ind_Run)
 str(RunOptions)
@@ -103,6 +103,133 @@ OutputsModels <- RunModel(InputsModels,
                           Param = Param)
 str(OutputsModels)
 
-# Compare Simulation with reservoir and observation of natural flow
-plot(OutputsModels, data.frame(GaugingDown = BasinObs$Qmm[Ind_Run]))
+# Compare regimes of the simulation with reservoir and observation of natural flow
+plot(OutputsModels,
+     data.frame(GaugingDown = BasinObs$Qmm[Ind_Run]),
+     which = "Regime")
+
+# Plot together simulated flows (m3/s) of the reservoir and the gauging station
+plot(attr(OutputsModels, "Qm3s"))
+
+
+########################################################
+# Run the Severn example provided with this package    #
+# A natural catchment composed with 6 gauging stations #
+########################################################
+
+data(Severn)
+nodes <- Severn$BasinsInfo
+nodes$model <- "RunModel_GR4J"
+# Mismatch column names are renamed to stick with GRiwrm requirements
+rename_columns <- list(id = "gauge_id",
+                       down = "downstream_id",
+                       length = "distance_downstream")
+g_severn <- CreateGRiwrm(nodes, rename_columns)
+
+# Network diagram with upstream basin nodes in blue, intermediate sub-basin in green
+plot(g_severn)
+
+# Format CAMEL-GB meteorological dataset for airGRiwrm inputs
+BasinsObs <- Severn$BasinsObs
+DatesR <- BasinsObs[[1]]$DatesR
+PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
+PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
+
+# Precipitation and Potential Evaporation are related to the whole catchment
+# at each gauging station. We need to compute them for intermediate catchments
+# for use in a semi-distributed model
+Precip <- ConvertMeteoSD(g_severn, PrecipTot)
+PotEvap <- ConvertMeteoSD(g_severn, PotEvapTot)
+
+# CreateInputsModel object
+IM_severn <- CreateInputsModel(g_severn, DatesR, Precip, PotEvap)
+
+# GRiwrmRunOptions object
+# Run period is set aside the one-year warm-up period
+IndPeriod_Run <- seq(
+  which(IM_severn[[1]]$DatesR == (IM_severn[[1]]$DatesR[1] + 365*24*60*60)),
+  length(IM_severn[[1]]$DatesR) # Until the end of the time series
+)
+IndPeriod_WarmUp <- seq(1, IndPeriod_Run[1] - 1)
+
+RO_severn <- CreateRunOptions(
+  IM_severn,
+  IndPeriod_WarmUp = IndPeriod_WarmUp,
+  IndPeriod_Run = IndPeriod_Run
+)
+
+# Load parameters of the model from Calibration in vignette V02
+P_severn <- readRDS(system.file("vignettes", "ParamV02.RDS", package = "airGRiwrm"))
+
+# Run the simulation
+OM_severn <- RunModel(IM_severn,
+                          RunOptions = RO_severn,
+                          Param = P_severn)
+
+# Plot results of simulated flows in m3/s
+Qm3s <- attr(OM_severn, "Qm3s")
+plot(Qm3s[1:150, ])
+
+
+##################################################################
+# An example of water withdrawal for irrigation with restriction #
+# modeled with a Diversion node on the Severn river              #
+##################################################################
+
+# A diversion is added at gauging station "54001"
+nodes_div <- nodes[,  c("gauge_id", "downstream_id", "distance_downstream", "area", "model")]
+names(nodes_div) <- c("id", "down", "length", "area", "model")
+nodes_div <- rbind(nodes_div,
+                   data.frame(id = "54001", # location of the diversion
+                              down = NA,    # the abstracted flow goes outside
+                              length = NA,  # down=NA, so length=NA
+                              area = NA,    # no area, diverted flow is in m3/day
+                              model = "Diversion"))
+
+g_div <- CreateGRiwrm(nodes_div)
+# The node "54001" is surrounded in red to show the diverted node
+plot(g_div)
+
+# Computation of the irrigation withdraw objective
+irrigMonthlyPlanning <- c(0.0, 0.0, 1.2, 2.4, 3.2, 3.6, 3.6, 2.8, 1.8, 0.0, 0.0, 0.0)
+names(irrigMonthlyPlanning) <- month.abb
+irrigMonthlyPlanning
+DatesR_month <- as.numeric(format(DatesR, "\%m"))
+# Withdrawn flow calculated for each day is negative
+Qirrig <- matrix(-irrigMonthlyPlanning[DatesR_month] * 86400, ncol = 1)
+colnames(Qirrig) <- "54001"
+
+# Minimum flow to remain downstream the diversion is 12 m3/s
+Qmin <- matrix(12 * 86400, nrow = length(DatesR), ncol = 1)
+colnames(Qmin) = "54001"
+
+# Creation of GRimwrInputsModel object
+IM_div <- CreateInputsModel(g_div, DatesR, Precip, PotEvap, Qobs = Qirrig, Qmin = Qmin)
+
+# RunOptions and parameters are unchanged, we can directly run the simulation
+OM_div <- RunModel(IM_div,
+                   RunOptions = RO_severn,
+                   Param = P_severn)
+
+# Retrieve diverted flow at "54001" and convert it from m3/day to m3/s
+Qdiv_m3s <- OM_div$`54001`$Qdiv_m3 / 86400
+
+# Plot the diverted flow for the year 2003
+Ind_Plot <- which(
+  OM_div[[1]]$DatesR >= as.POSIXct("2003-01-01", tz = "UTC") &
+  OM_div[[1]]$DatesR <= as.POSIXct("2003-12-31", tz = "UTC")
+)
+dfQdiv <- data.frame(DatesR = OM_div[[1]]$DatesR[Ind_Plot],
+                     Diverted_flow = Qdiv_m3s[Ind_Plot])
+
+oldpar <- par(mfrow=c(2,1), mar = c(2.5,4,1,1))
+plot.Qm3s(dfQdiv)
+
+# Plot natural and influenced flow at station "54001"
+df54001 <- cbind(attr(OM_div, "Qm3s")[Ind_Plot, c("DatesR", "54001")],
+                 attr(OM_severn, "Qm3s")[Ind_Plot, "54001"])
+names(df54001) <- c("DatesR", "54001 with irrigation", "54001 natural flow")
+plot.Qm3s(df54001, ylim = c(0,70))
+abline(h = 12, col = "green")
+par(oldpar)
 }
diff --git a/man/RunModel.Supervisor.Rd b/man/RunModel.Supervisor.Rd
index 385707baec6f5a7c62c116e80aaac71c9af0d221..540bc339d495580bd6b64944710a3c773954b0ac 100644
--- a/man/RunModel.Supervisor.Rd
+++ b/man/RunModel.Supervisor.Rd
@@ -21,3 +21,129 @@
 \description{
 RunModel function for a GRiwrmInputsModel object
 }
+\examples{
+###############################################################################
+# An example of reservoir management on an hypothetical dam at station "54095"
+# on the Severn river build to support low-flows at "54057"
+###############################################################################
+# A minimum flow of 20 m3/s is maintained at the dam location and an extra-release
+# is provided when the flow at the downstream station "54057" cross a minimum
+# threshold of 45 m3/s. The dam has a storage capacity of 60 millions m3
+###############################################################################
+library(airGRiwrm)
+
+# Load Severn network information
+data(Severn)
+nodes <- Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")]
+nodes$model <- "RunModel_GR4J"
+
+# Insert a dam downstream the location the gauging station 54095
+# The dam is a direct injection node
+nodes$downstream_id[nodes$gauge_id == "54095"] <- "Dam"
+nodes$distance_downstream[nodes$gauge_id == "54095"] <- 0
+nodes <- rbind(nodes,
+               data.frame(gauge_id = "Dam",
+                          downstream_id = "54001",
+                          distance_downstream = 42,
+                          area = NA,
+                          model = NA))
+
+griwrm <- CreateGRiwrm(nodes,
+                 list(id = "gauge_id",
+                      down = "downstream_id",
+                      length = "distance_downstream"))
+plot(griwrm)
+
+# Format meteorological inputs for CreateInputs
+BasinsObs <- Severn$BasinsObs
+DatesR <- BasinsObs[[1]]$DatesR
+PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
+PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
+Precip <- ConvertMeteoSD(griwrm, PrecipTot)
+PotEvap <- ConvertMeteoSD(griwrm, PotEvapTot)
+
+# Create a release flow time series for the dam
+# This release will be modified by the Supervisor
+# We initiate it with the natural flow for having a good initialisation of the
+# model at the first time step of the running period
+Qobs <- data.frame(
+  Dam = BasinsObs$`54095`$discharge_spec * griwrm$area[griwrm$id == "54095"] * 1E3
+)
+Qobs[,] <- Qobs[which(DatesR == as.POSIXct("2002-10-01", tz = "UTC")), 1]
+
+# InputsModel object
+IM_severn <- CreateInputsModel(griwrm, DatesR, Precip, PotEvap, Qobs)
+
+# Initialisation of the Supervisor
+sv <- CreateSupervisor(IM_severn)
+
+# States of the reservoir are stored in the Supervisor variable
+# The Supervisor variable is an environment which can be available in
+# the controller function for storing and exchange data during the simulation
+sv$Vres <- 0 # Reservoir storage time series
+
+# Dam management is modeled by a controller
+# This controller usually releases Qmin and provides
+# extra release if flow mesured somewhere is below Qthreshold
+# Flow is expressed in m3 / time step
+# Y[1] = runoff flow at gauging station 54095 filling the reservoir
+# Y[2] = flow at gauging station 54057, location of the low-flow objective
+# The returned value is the release calculated at the reservoir
+# We need to enclose the Supervisor variable and other parameters in
+# the environment of the function with a function returning the logic function
+factoryDamLogic <- function(sv, Vmin, Vmax, Qmin, Qthreshold) {
+  function(Y) {
+    # Filling of the reservoir
+    sv$Vres <- c(sv$Vres, tail(sv$Vres, 1) + Y[1])
+    # The release is the max between: overflow, low-flow support and minimum flow
+    U <- U <- max(tail(sv$Vres, 1) - Vmax, Qthreshold - Y[2], Qmin)
+    sv$Vres[length(sv$Vres)] <- tail(sv$Vres, 1) - U
+    if (tail(sv$Vres, 1) < Vmin) {
+      # Reservoir is empty
+      U <- U - (Vmin - tail(sv$Vres, 1))
+      sv$Vres[length(sv$Vres)] <- Vmin
+    }
+    return(U)
+  }
+}
+
+# And define a final function enclosing logic and parameters together
+funDamLogic <- factoryDamLogic(
+  sv = sv, # The Supervisor which store the states of reservoir storage
+  Vmin = 0, # Minimum volume in the reservoir (m3)
+  Vmax = 60 * 1E6, # Maximum volume in the reservoir (m3)
+  Qmin = 20 * 86400, # Min flow to maintain downstream the reservoir (m3/day)
+  Qthreshold = 45 * 86400 # Min flow threshold to support at station 54057 (m3/day)
+)
+
+CreateController(sv, "DamRelease", Y = c("54095", "54057"), U = c("Dam"), FUN = funDamLogic)
+
+# GRiwrmRunOptions object simulation of the hydrological year 2002-2003
+IndPeriod_Run <- which(
+  DatesR >= as.POSIXct("2002-10-15", tz = "UTC") &
+  DatesR <= as.POSIXct("2003-10-15", tz = "UTC")
+)
+IndPeriod_WarmUp <- seq.int(IndPeriod_Run[1] - 366, IndPeriod_Run[1] - 1)
+RO_severn <- CreateRunOptions(
+  IM_severn,
+  IndPeriod_WarmUp = IndPeriod_WarmUp,
+  IndPeriod_Run = IndPeriod_Run
+)
+
+# Load parameters of the model from Calibration in vignette V02
+P_severn <- readRDS(system.file("vignettes", "ParamV02.RDS", package = "airGRiwrm"))
+
+# The Supervisor is used instead of InputsModel for running the model
+OM_dam <- RunModel(sv,
+                      RunOptions = RO_severn,
+                      Param = P_severn)
+
+# Plotting the time series of flows and reservoir storage
+oldpar <- par(mfrow=c(2,1), mar = c(2.5,4,1,1))
+plot(attr(OM_dam, "Qm3s")[, c("DatesR", "54095", "Dam", "54057")],
+     ylim = c(0, 200))
+Vres <- data.frame(DatesR = attr(OM_dam, "Qm3s")$DatesR,
+                   V_reservoir = sv$Vres)
+plot.Qm3s(Vres)
+par(oldpar)
+}
diff --git a/man/getNoSD_Ids.Rd b/man/getNoSD_Ids.Rd
index 50750697f100619ec9e4813a74cc898fa21400aa..644d49eaf4ad79b18c723423d51f58d8ecf10e4d 100644
--- a/man/getNoSD_Ids.Rd
+++ b/man/getNoSD_Ids.Rd
@@ -4,10 +4,12 @@
 \alias{getNoSD_Ids}
 \title{Function to obtain the ID of sub-basins not using SD model}
 \usage{
-getNoSD_Ids(InputsModel)
+getNoSD_Ids(InputsModel, include_diversion = TRUE)
 }
 \arguments{
 \item{InputsModel}{[\code{GRiwrmInputsModel} object]}
+
+\item{include_diversion}{\link{logical} for including diversion nodes}
 }
 \value{
 \link{character} IDs of the sub-basins not using the SD model
diff --git a/man/getSD_Ids.Rd b/man/getSD_Ids.Rd
index 1a863101f37fddc766c1d33d37152fd54350cf5a..a1987eca097fe7e47c1da1a9408e39dadae1ede8 100644
--- a/man/getSD_Ids.Rd
+++ b/man/getSD_Ids.Rd
@@ -4,10 +4,12 @@
 \alias{getSD_Ids}
 \title{Function to obtain the ID of sub-basins using SD model}
 \usage{
-getSD_Ids(InputsModel)
+getSD_Ids(InputsModel, add_diversion = FALSE)
 }
 \arguments{
 \item{InputsModel}{[\code{GRiwrmInputsModel} object]}
+
+\item{add_diversion}{\link{logical} for adding upstream nodes with diversion}
 }
 \value{
 \link{character} IDs of the sub-basins using SD model
diff --git a/man/plot.GRiwrm.Rd b/man/plot.GRiwrm.Rd
index 280c22d5708d8c29b6db9a4ee4244f40b9d8e16b..ff59579bf370a7530878c2b8120e07f360a2a7c6 100644
--- a/man/plot.GRiwrm.Rd
+++ b/man/plot.GRiwrm.Rd
@@ -10,8 +10,8 @@
   orientation = "LR",
   width = "100\%",
   height = "100\%",
-  box_colors = c(UpstreamUngauged = "#eef", UpstreamGauged = "#aaf", IntermUngauged =
-    "#efe", IntermGauged = "#afa", DirectInjection = "#faa"),
+  box_colors = c(UpstreamUngauged = "#eef", UpstreamGauged = "#aaf", IntermediateUngauged
+    = "#efe", IntermediateGauged = "#afa", DirectInjection = "#faa"),
   ...
 )
 }
@@ -41,7 +41,9 @@ This function only works inside RStudio because the HTMLwidget produced by Diagr
 is not handled on some platforms
 }
 \examples{
-# Network of 2 nodes distant of 150 km:
+#########################################
+# Network of 2 nodes distant of 150 km: #
+#########################################
 # - an upstream reservoir modelled as a direct flow injection (no model)
 # - a gauging station downstream a catchment of 360 km² modelled with GR4J
 db <- data.frame(id = c("Reservoir", "GaugingDown"),
@@ -55,7 +57,9 @@ griwrm_basic
 # Network diagram with direct flow node in red, intermediate sub-basin in green
 plot(griwrm_basic)
 
-# GR4J semi-distributed model of the Severn River
+###################################################
+# GR4J semi-distributed model of the Severn River #
+###################################################
 data(Severn)
 nodes <- Severn$BasinsInfo
 nodes$model <- "RunModel_GR4J"
@@ -69,7 +73,9 @@ griwrm_severn
 # Network diagram with upstream basin nodes in blue, intermediate sub-basin in green
 plot(griwrm_severn)
 
-# Same model with an ungauged station at nodes 54029 and 54001
+####################################################################
+# Severn network with an ungauged station at nodes 54029 and 54001 #
+####################################################################
 # By default the first gauged node at downstream is used for parameter calibration (54032)
 nodes_ungauged <- nodes
 nodes_ungauged$model[nodes_ungauged$gauge_id \%in\% c("54029", "54001")] <- "Ungauged"
@@ -78,4 +84,18 @@ griwrm_ungauged <- CreateGRiwrm(nodes_ungauged, rename_columns)
 griwrm_ungauged
 # Network diagram with gauged nodes of vivid color, and ungauged nodes of dull color
 plot(griwrm_ungauged)
+
+#######################################################
+# Severn network with a Diversion on the node "54029" #
+# which transfer flows to the node "54001"            #
+#######################################################
+nodes_div <- nodes[, c("gauge_id", "downstream_id", "distance_downstream", "model", "area")]
+nodes_div <- rbind(nodes_div, data.frame(gauge_id = "54029",
+                                         downstream_id = "54001",
+                                         distance_downstream = 20,
+                                         model = "Diversion",
+                                         area = NA))
+griwrm_div <- CreateGRiwrm(nodes_div, rename_columns)
+# Network diagram figures Diversion node by a red frame and a red arrow
+plot(griwrm_div)
 }
diff --git a/man/plot.GRiwrmOutputsModel.Rd b/man/plot.GRiwrmOutputsModel.Rd
index f25a416c29c271b075685bf13ed5fd8e7a6b024e..a2f12a09d49e28228f10befe657c404c61ca4fa0 100644
--- a/man/plot.GRiwrmOutputsModel.Rd
+++ b/man/plot.GRiwrmOutputsModel.Rd
@@ -88,7 +88,7 @@ str(InputsModels)
 Ind_Run <- seq(which(format(BasinObs$DatesR, format = "\%Y-\%m-\%d")=="1990-01-01"),
                which(format(BasinObs$DatesR, format = "\%Y-\%m-\%d")=="1999-12-31"))
 
-# Creation of the GriwmRunOptions object
+# Creation of the GRiwmRunOptions object
 RunOptions <- CreateRunOptions(InputsModels,
                                 IndPeriod_Run = Ind_Run)
 str(RunOptions)
@@ -103,6 +103,133 @@ OutputsModels <- RunModel(InputsModels,
                           Param = Param)
 str(OutputsModels)
 
-# Compare Simulation with reservoir and observation of natural flow
-plot(OutputsModels, data.frame(GaugingDown = BasinObs$Qmm[Ind_Run]))
+# Compare regimes of the simulation with reservoir and observation of natural flow
+plot(OutputsModels,
+     data.frame(GaugingDown = BasinObs$Qmm[Ind_Run]),
+     which = "Regime")
+
+# Plot together simulated flows (m3/s) of the reservoir and the gauging station
+plot(attr(OutputsModels, "Qm3s"))
+
+
+########################################################
+# Run the Severn example provided with this package    #
+# A natural catchment composed with 6 gauging stations #
+########################################################
+
+data(Severn)
+nodes <- Severn$BasinsInfo
+nodes$model <- "RunModel_GR4J"
+# Mismatch column names are renamed to stick with GRiwrm requirements
+rename_columns <- list(id = "gauge_id",
+                       down = "downstream_id",
+                       length = "distance_downstream")
+g_severn <- CreateGRiwrm(nodes, rename_columns)
+
+# Network diagram with upstream basin nodes in blue, intermediate sub-basin in green
+plot(g_severn)
+
+# Format CAMEL-GB meteorological dataset for airGRiwrm inputs
+BasinsObs <- Severn$BasinsObs
+DatesR <- BasinsObs[[1]]$DatesR
+PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
+PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
+
+# Precipitation and Potential Evaporation are related to the whole catchment
+# at each gauging station. We need to compute them for intermediate catchments
+# for use in a semi-distributed model
+Precip <- ConvertMeteoSD(g_severn, PrecipTot)
+PotEvap <- ConvertMeteoSD(g_severn, PotEvapTot)
+
+# CreateInputsModel object
+IM_severn <- CreateInputsModel(g_severn, DatesR, Precip, PotEvap)
+
+# GRiwrmRunOptions object
+# Run period is set aside the one-year warm-up period
+IndPeriod_Run <- seq(
+  which(IM_severn[[1]]$DatesR == (IM_severn[[1]]$DatesR[1] + 365*24*60*60)),
+  length(IM_severn[[1]]$DatesR) # Until the end of the time series
+)
+IndPeriod_WarmUp <- seq(1, IndPeriod_Run[1] - 1)
+
+RO_severn <- CreateRunOptions(
+  IM_severn,
+  IndPeriod_WarmUp = IndPeriod_WarmUp,
+  IndPeriod_Run = IndPeriod_Run
+)
+
+# Load parameters of the model from Calibration in vignette V02
+P_severn <- readRDS(system.file("vignettes", "ParamV02.RDS", package = "airGRiwrm"))
+
+# Run the simulation
+OM_severn <- RunModel(IM_severn,
+                          RunOptions = RO_severn,
+                          Param = P_severn)
+
+# Plot results of simulated flows in m3/s
+Qm3s <- attr(OM_severn, "Qm3s")
+plot(Qm3s[1:150, ])
+
+
+##################################################################
+# An example of water withdrawal for irrigation with restriction #
+# modeled with a Diversion node on the Severn river              #
+##################################################################
+
+# A diversion is added at gauging station "54001"
+nodes_div <- nodes[,  c("gauge_id", "downstream_id", "distance_downstream", "area", "model")]
+names(nodes_div) <- c("id", "down", "length", "area", "model")
+nodes_div <- rbind(nodes_div,
+                   data.frame(id = "54001", # location of the diversion
+                              down = NA,    # the abstracted flow goes outside
+                              length = NA,  # down=NA, so length=NA
+                              area = NA,    # no area, diverted flow is in m3/day
+                              model = "Diversion"))
+
+g_div <- CreateGRiwrm(nodes_div)
+# The node "54001" is surrounded in red to show the diverted node
+plot(g_div)
+
+# Computation of the irrigation withdraw objective
+irrigMonthlyPlanning <- c(0.0, 0.0, 1.2, 2.4, 3.2, 3.6, 3.6, 2.8, 1.8, 0.0, 0.0, 0.0)
+names(irrigMonthlyPlanning) <- month.abb
+irrigMonthlyPlanning
+DatesR_month <- as.numeric(format(DatesR, "\%m"))
+# Withdrawn flow calculated for each day is negative
+Qirrig <- matrix(-irrigMonthlyPlanning[DatesR_month] * 86400, ncol = 1)
+colnames(Qirrig) <- "54001"
+
+# Minimum flow to remain downstream the diversion is 12 m3/s
+Qmin <- matrix(12 * 86400, nrow = length(DatesR), ncol = 1)
+colnames(Qmin) = "54001"
+
+# Creation of GRimwrInputsModel object
+IM_div <- CreateInputsModel(g_div, DatesR, Precip, PotEvap, Qobs = Qirrig, Qmin = Qmin)
+
+# RunOptions and parameters are unchanged, we can directly run the simulation
+OM_div <- RunModel(IM_div,
+                   RunOptions = RO_severn,
+                   Param = P_severn)
+
+# Retrieve diverted flow at "54001" and convert it from m3/day to m3/s
+Qdiv_m3s <- OM_div$`54001`$Qdiv_m3 / 86400
+
+# Plot the diverted flow for the year 2003
+Ind_Plot <- which(
+  OM_div[[1]]$DatesR >= as.POSIXct("2003-01-01", tz = "UTC") &
+  OM_div[[1]]$DatesR <= as.POSIXct("2003-12-31", tz = "UTC")
+)
+dfQdiv <- data.frame(DatesR = OM_div[[1]]$DatesR[Ind_Plot],
+                     Diverted_flow = Qdiv_m3s[Ind_Plot])
+
+oldpar <- par(mfrow=c(2,1), mar = c(2.5,4,1,1))
+plot.Qm3s(dfQdiv)
+
+# Plot natural and influenced flow at station "54001"
+df54001 <- cbind(attr(OM_div, "Qm3s")[Ind_Plot, c("DatesR", "54001")],
+                 attr(OM_severn, "Qm3s")[Ind_Plot, "54001"])
+names(df54001) <- c("DatesR", "54001 with irrigation", "54001 natural flow")
+plot.Qm3s(df54001, ylim = c(0,70))
+abline(h = 12, col = "green")
+par(oldpar)
 }
diff --git a/man/plot.Qm3s.Rd b/man/plot.Qm3s.Rd
index 7c2ddcf3df9604fcd5ff5ed9494ab104719ba9fc..2bb899b633fa59113db059f8936f716c3e485eb2 100644
--- a/man/plot.Qm3s.Rd
+++ b/man/plot.Qm3s.Rd
@@ -8,7 +8,7 @@
   x,
   type = "l",
   xlab = "Date",
-  ylab = expression("Flow (m"^"3" * "/s)"),
+  ylab = expression("Flow rate (m"^"3" * "/s)"),
   main = "Simulated flows",
   col = rainbow(ncol(x) - 1),
   legend = colnames(x)[-1],
@@ -20,7 +20,8 @@
 )
 }
 \arguments{
-\item{x}{\link{data.frame} with a first column with \link{POSIXt} dates and followings columns with flows at each node of the network}
+\item{x}{\link{data.frame} with a first column with \link{POSIXt} dates and followings
+columns with flows at each node of the network}
 
 \item{type}{\link{character} plot type (See \link{plot.default}), default "l"}
 
@@ -32,7 +33,8 @@
 
 \item{col}{\link{character} plotting color (See \link{par}), default to rainbow colors}
 
-\item{legend}{\link{character} see parameter \code{legend} of \link{legend}. Set to \link{NULL} if display of the legend is not wanted}
+\item{legend}{\link{character} see parameter \code{legend} of \link{legend}. Set it to \link{NULL}
+to hide the legend}
 
 \item{legend.cex}{\link{character} \code{cex} parameter for the text of the legend (See \link{par})}
 
@@ -46,5 +48,219 @@
 Screen plot window.
 }
 \description{
-Plot of a \code{Qm3s} object (time series of simulated flows)
+This function plot time series of flow rate in m3/s. It's a method for object
+of class "Qm3s" which can be directly called by \code{plot}. It can also be called
+as a function \code{plot.Qm3s} if the first parameter has the good format.
+}
+\examples{
+###################################################################
+# Run the `airGR::RunModel_Lag` example in the GRiwrm fashion way #
+# Simulation of a reservoir with a purpose of low-flow mitigation #
+###################################################################
+
+## ---- preparation of the InputsModel object
+
+## loading package and catchment data
+library(airGRiwrm)
+data(L0123001)
+
+## ---- specifications of the reservoir
+
+## the reservoir withdraws 1 m3/s when it's possible considering the flow observed in the basin
+Qupstream <- matrix(-sapply(BasinObs$Qls / 1000 - 1, function(x) {
+  min(1, max(0, x, na.rm = TRUE))
+}), ncol = 1)
+
+## except between July and September when the reservoir releases 3 m3/s for low-flow mitigation
+month <- as.numeric(format(BasinObs$DatesR, "\%m"))
+Qupstream[month >= 7 & month <= 9] <- 3
+Qupstream <- Qupstream * 86400 ## Conversion in m3/day
+
+## the reservoir is not an upstream subcachment: its areas is NA
+BasinAreas <- c(NA, BasinInfo$BasinArea)
+
+## delay time between the reservoir and the catchment outlet is 2 days and the distance is 150 km
+LengthHydro <- 150
+## with a delay of 2 days for 150 km, the flow velocity is 75 km per day
+Velocity <- (LengthHydro * 1e3 / 2) / (24 * 60 * 60) ## Conversion km/day -> m/s
+
+# This example is a network of 2 nodes which can be describe like this:
+db <- data.frame(id = c("Reservoir", "GaugingDown"),
+                 length = c(LengthHydro, NA),
+                 down = c("GaugingDown", NA),
+                 area = c(NA, BasinInfo$BasinArea),
+                 model = c(NA, "RunModel_GR4J"),
+                 stringsAsFactors = FALSE)
+
+# Create GRiwrm object from the data.frame
+griwrm <- CreateGRiwrm(db)
+str(griwrm)
+
+# Formatting observations for the hydrological models
+# Each input data should be a matrix or a data.frame with the good id in the name of the column
+Precip <- matrix(BasinObs$P, ncol = 1)
+colnames(Precip) <- "GaugingDown"
+PotEvap <- matrix(BasinObs$E, ncol = 1)
+colnames(PotEvap) <- "GaugingDown"
+
+# Observed flows contain flows that are directly injected in the model
+Qobs = matrix(Qupstream, ncol = 1)
+colnames(Qobs) <- "Reservoir"
+
+# Creation of the GRiwrmInputsModel object (= a named list of InputsModel objects)
+InputsModels <- CreateInputsModel(griwrm,
+                            DatesR = BasinObs$DatesR,
+                            Precip = Precip,
+                            PotEvap = PotEvap,
+                            Qobs = Qobs)
+str(InputsModels)
+
+## run period selection
+Ind_Run <- seq(which(format(BasinObs$DatesR, format = "\%Y-\%m-\%d")=="1990-01-01"),
+               which(format(BasinObs$DatesR, format = "\%Y-\%m-\%d")=="1999-12-31"))
+
+# Creation of the GRiwmRunOptions object
+RunOptions <- CreateRunOptions(InputsModels,
+                                IndPeriod_Run = Ind_Run)
+str(RunOptions)
+
+# Parameters of the SD models should be encapsulated in a named list
+ParamGR4J <- c(X1 = 257.238, X2 = 1.012, X3 = 88.235, X4 = 2.208)
+Param <- list(`GaugingDown` = c(Velocity, ParamGR4J))
+
+# RunModel for the whole network
+OutputsModels <- RunModel(InputsModels,
+                          RunOptions = RunOptions,
+                          Param = Param)
+str(OutputsModels)
+
+# Compare regimes of the simulation with reservoir and observation of natural flow
+plot(OutputsModels,
+     data.frame(GaugingDown = BasinObs$Qmm[Ind_Run]),
+     which = "Regime")
+
+# Plot together simulated flows (m3/s) of the reservoir and the gauging station
+plot(attr(OutputsModels, "Qm3s"))
+
+
+########################################################
+# Run the Severn example provided with this package    #
+# A natural catchment composed with 6 gauging stations #
+########################################################
+
+data(Severn)
+nodes <- Severn$BasinsInfo
+nodes$model <- "RunModel_GR4J"
+# Mismatch column names are renamed to stick with GRiwrm requirements
+rename_columns <- list(id = "gauge_id",
+                       down = "downstream_id",
+                       length = "distance_downstream")
+g_severn <- CreateGRiwrm(nodes, rename_columns)
+
+# Network diagram with upstream basin nodes in blue, intermediate sub-basin in green
+plot(g_severn)
+
+# Format CAMEL-GB meteorological dataset for airGRiwrm inputs
+BasinsObs <- Severn$BasinsObs
+DatesR <- BasinsObs[[1]]$DatesR
+PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
+PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
+
+# Precipitation and Potential Evaporation are related to the whole catchment
+# at each gauging station. We need to compute them for intermediate catchments
+# for use in a semi-distributed model
+Precip <- ConvertMeteoSD(g_severn, PrecipTot)
+PotEvap <- ConvertMeteoSD(g_severn, PotEvapTot)
+
+# CreateInputsModel object
+IM_severn <- CreateInputsModel(g_severn, DatesR, Precip, PotEvap)
+
+# GRiwrmRunOptions object
+# Run period is set aside the one-year warm-up period
+IndPeriod_Run <- seq(
+  which(IM_severn[[1]]$DatesR == (IM_severn[[1]]$DatesR[1] + 365*24*60*60)),
+  length(IM_severn[[1]]$DatesR) # Until the end of the time series
+)
+IndPeriod_WarmUp <- seq(1, IndPeriod_Run[1] - 1)
+
+RO_severn <- CreateRunOptions(
+  IM_severn,
+  IndPeriod_WarmUp = IndPeriod_WarmUp,
+  IndPeriod_Run = IndPeriod_Run
+)
+
+# Load parameters of the model from Calibration in vignette V02
+P_severn <- readRDS(system.file("vignettes", "ParamV02.RDS", package = "airGRiwrm"))
+
+# Run the simulation
+OM_severn <- RunModel(IM_severn,
+                          RunOptions = RO_severn,
+                          Param = P_severn)
+
+# Plot results of simulated flows in m3/s
+Qm3s <- attr(OM_severn, "Qm3s")
+plot(Qm3s[1:150, ])
+
+
+##################################################################
+# An example of water withdrawal for irrigation with restriction #
+# modeled with a Diversion node on the Severn river              #
+##################################################################
+
+# A diversion is added at gauging station "54001"
+nodes_div <- nodes[,  c("gauge_id", "downstream_id", "distance_downstream", "area", "model")]
+names(nodes_div) <- c("id", "down", "length", "area", "model")
+nodes_div <- rbind(nodes_div,
+                   data.frame(id = "54001", # location of the diversion
+                              down = NA,    # the abstracted flow goes outside
+                              length = NA,  # down=NA, so length=NA
+                              area = NA,    # no area, diverted flow is in m3/day
+                              model = "Diversion"))
+
+g_div <- CreateGRiwrm(nodes_div)
+# The node "54001" is surrounded in red to show the diverted node
+plot(g_div)
+
+# Computation of the irrigation withdraw objective
+irrigMonthlyPlanning <- c(0.0, 0.0, 1.2, 2.4, 3.2, 3.6, 3.6, 2.8, 1.8, 0.0, 0.0, 0.0)
+names(irrigMonthlyPlanning) <- month.abb
+irrigMonthlyPlanning
+DatesR_month <- as.numeric(format(DatesR, "\%m"))
+# Withdrawn flow calculated for each day is negative
+Qirrig <- matrix(-irrigMonthlyPlanning[DatesR_month] * 86400, ncol = 1)
+colnames(Qirrig) <- "54001"
+
+# Minimum flow to remain downstream the diversion is 12 m3/s
+Qmin <- matrix(12 * 86400, nrow = length(DatesR), ncol = 1)
+colnames(Qmin) = "54001"
+
+# Creation of GRimwrInputsModel object
+IM_div <- CreateInputsModel(g_div, DatesR, Precip, PotEvap, Qobs = Qirrig, Qmin = Qmin)
+
+# RunOptions and parameters are unchanged, we can directly run the simulation
+OM_div <- RunModel(IM_div,
+                   RunOptions = RO_severn,
+                   Param = P_severn)
+
+# Retrieve diverted flow at "54001" and convert it from m3/day to m3/s
+Qdiv_m3s <- OM_div$`54001`$Qdiv_m3 / 86400
+
+# Plot the diverted flow for the year 2003
+Ind_Plot <- which(
+  OM_div[[1]]$DatesR >= as.POSIXct("2003-01-01", tz = "UTC") &
+  OM_div[[1]]$DatesR <= as.POSIXct("2003-12-31", tz = "UTC")
+)
+dfQdiv <- data.frame(DatesR = OM_div[[1]]$DatesR[Ind_Plot],
+                     Diverted_flow = Qdiv_m3s[Ind_Plot])
+
+oldpar <- par(mfrow=c(2,1), mar = c(2.5,4,1,1))
+plot.Qm3s(dfQdiv)
+
+# Plot natural and influenced flow at station "54001"
+df54001 <- cbind(attr(OM_div, "Qm3s")[Ind_Plot, c("DatesR", "54001")],
+                 attr(OM_severn, "Qm3s")[Ind_Plot, "54001"])
+names(df54001) <- c("DatesR", "54001 with irrigation", "54001 natural flow")
+plot.Qm3s(df54001, ylim = c(0,70))
+abline(h = 12, col = "green")
+par(oldpar)
 }
diff --git a/tests/testthat/helper_RunModel.R b/tests/testthat/helper_RunModel.R
index 2b5b500e8743b67327376ce9b2db44c80d9e6679..20ce78b829f5b9711f046abde6dbbe96bf4d365a 100644
--- a/tests/testthat/helper_RunModel.R
+++ b/tests/testthat/helper_RunModel.R
@@ -34,16 +34,9 @@ setupRunModel <-
 
     # Set network
     if(is.null(griwrm)) {
-      nodes <-
-        Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")]
-      nodes$model <- "RunModel_GR4J"
+      nodes <- loadSevernNodes()
       griwrm <-
-        CreateGRiwrm(nodes,
-                     list(
-                       id = "gauge_id",
-                       down = "downstream_id",
-                       length = "distance_downstream"
-                     ))
+        CreateGRiwrm(nodes)
     }
 
     # Convert meteo data to SD (remove upstream areas)
@@ -54,7 +47,7 @@ setupRunModel <-
     if (!runInputsModel)
       return(environment())
     InputsModel <-
-      suppressWarnings(CreateInputsModel(griwrm, DatesR, Precip, PotEvap, Qobs))
+      suppressWarnings(CreateInputsModel(griwrm, DatesR, Precip, PotEvap))
 
     # RunOptions
     if (!runRunOptions)
@@ -126,3 +119,19 @@ setupRunOptions <- function(InputsModel) {
 
   return(environment())
 }
+
+#' Load Severn example and format BasinsInfo for use in CreateGRiwrm
+#'
+#' @return [data.frame] with columns "id", "down", "length", "area"
+#' @noRd
+#'
+#' @examples
+#' nodes <- loadNodes
+loadSevernNodes <- function() {
+  data(Severn)
+  nodes <-
+    Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")]
+  names(nodes) <- c("id", "down", "length", "area")
+  nodes$model <- "RunModel_GR4J"
+  return(nodes)
+}
diff --git a/tests/testthat/test-Calibration.R b/tests/testthat/test-Calibration.R
index 8a27cb827a4fe5c197b24f71add625ed0b08f1f0..8ff1ccc36d38d22aa65b353dcdb3a0da720e2948 100644
--- a/tests/testthat/test-Calibration.R
+++ b/tests/testthat/test-Calibration.R
@@ -98,3 +98,29 @@ test_that("Calibration with regularization is OK", {
     )
   })
 })
+
+test_that("Calibration with Diversion works", {
+  n_div <- rbind(nodes,
+                 data.frame(id = "54029", down = "54002", length = 50, area = NA, model = "Diversion"))
+  g_div <- CreateGRiwrm(n_div)
+  Qmin = matrix(1E5, nrow = length(DatesR), ncol = 1)
+  colnames(Qmin) = "54029"
+  Qdiv <- -Qmin
+  IM_div <- CreateInputsModel(g_div, DatesR, Precip, PotEvap, Qobs = Qdiv, Qmin = Qmin)
+  RO_div <- setupRunOptions(IM_div)$RunOptions
+  P_div <- ParamMichel
+  P_div$`54002` <- c(1, ParamMichel$`54002`)
+  IC_div <- CreateInputsCrit(
+    InputsModel = IM_div,
+    RunOptions = RO_div,
+    Obs = Qobs[IndPeriod_Run,],
+  )
+  CO_div <- CreateCalibOptions(IM_div)
+  OC <- Calibration(
+    InputsModel = IM_div,
+    RunOptions = RO_div,
+    InputsCrit = IC_div,
+    CalibOptions = CO_div
+  )
+  expect_length(OC$`54002`$ParamFinalR, 5)
+})
diff --git a/tests/testthat/test-CreateInputsCrit.R b/tests/testthat/test-CreateInputsCrit.R
index 3d02d28056fedb515635e283026b6655c0f7b45b..3b419ae5b8401affc4142881864ab97e9fee5c81 100644
--- a/tests/testthat/test-CreateInputsCrit.R
+++ b/tests/testthat/test-CreateInputsCrit.R
@@ -122,13 +122,9 @@ test_that("Lavenne criterion: current node and a priori node must use the same m
 })
 
 test_that("Ungauged node as Apriori node should throw an error", {
-  nodes$model[nodes$gauge_id == "54001"] <- "Ungauged"
-  griwrm <- CreateGRiwrm(
-    nodes,
-    list(id = "gauge_id", down = "downstream_id", length = "distance_downstream")
-  )
-  InputsModel <-
-    suppressWarnings(CreateInputsModel(griwrm, DatesR, Precip, PotEvap, Qobs))
+  nodes$model[nodes$id == "54001"] <- "Ungauged"
+  griwrm <- CreateGRiwrm(nodes)
+  InputsModel <- CreateInputsModel(griwrm, DatesR, Precip, PotEvap)
   expect_error(
     CreateInputsCrit(InputsModel = InputsModel,
                      RunOptions = RunOptions,
diff --git a/tests/testthat/test-CreateInputsModel.R b/tests/testthat/test-CreateInputsModel.R
index 4622038f1b169fe6e7352984f92559ebc5f0af0b..d383a5c856d22697c8e70c332a2e6a8a6be078c7 100644
--- a/tests/testthat/test-CreateInputsModel.R
+++ b/tests/testthat/test-CreateInputsModel.R
@@ -127,7 +127,7 @@ test_that("throws error when missing CemaNeige data", {
                regexp = "'TempMean' is missing")
 })
 
-test_that("throws error when missing Qobs on node not related to an hydrological model", {
+test_that("throws error when missing Qobs on node Direct Injection node", {
   l$griwrm$model[1] <- NA
   expect_error(CreateInputsModel(l$griwrm,
                                  DatesR = l$DatesR,
@@ -159,14 +159,16 @@ test_that("must works with node not related to an hydrological model", {
   expect_equal(colnames(IM[[2]]$Qupstream), c("Up1", "Up2"))
 })
 
-test_that("negative observed flow on catchment should throw error", {
-  l$Qobs[100, 1] <- -99
+test_that("Qobs on hydrological nodes should throw en error", {
   expect_error(CreateInputsModel(l$griwrm,
                                  DatesR = l$DatesR,
                                  Precip = l$Precip,
                                  PotEvap = l$PotEvap,
-                                 Qobs = l$Qobs),
-               regexp = "Negative flow found")
+                                 Qobs = l$Qobs,
+                                 TempMean = l$TempMean,
+                                 ZInputs = l$ZInputs,
+                                 HypsoData = l$HypsoData),
+               regexp = "columns in 'Qobs' don't match with")
   l$griwrm$model[1] <- NA
   expect_s3_class(suppressWarnings(
     CreateInputsModel(
@@ -174,7 +176,7 @@ test_that("negative observed flow on catchment should throw error", {
       DatesR = l$DatesR,
       Precip = l$Precip,
       PotEvap = l$PotEvap,
-      Qobs = l$Qobs,
+      Qobs = l$Qobs[,1, drop = F],
       TempMean = l$TempMean,
       ZInputs = l$ZInputs,
       HypsoData = l$HypsoData
@@ -191,13 +193,51 @@ for(x in ls(e)) assign(x, get(x, e))
 
 test_that("Ungauged node should inherits its FUN_MOD from the downstream gauged node", {
 
-  nodes$model[nodes$gauge_id == "54032"] <- "Ungauged"
-  griwrmV05 <- CreateGRiwrm(
-    nodes,
-    list(id = "gauge_id", down = "downstream_id", length = "distance_downstream")
-  )
+  nodes$model[nodes$id == "54032"] <- "Ungauged"
+  griwrmV05 <- CreateGRiwrm(nodes)
   IM <- suppressWarnings(
-    CreateInputsModel(griwrmV05, DatesR, Precip, PotEvap, Qobs)
+    CreateInputsModel(griwrmV05, DatesR, Precip, PotEvap)
   )
   expect_equal(IM[["54032"]]$FUN_MOD, "RunModel_GR4J")
 })
+
+test_that("Network with Diversion works", {
+  n_div <- rbind(nodes, data.frame(id = "54029",
+                                   down = "54002",
+                                   length = 20,
+                                   model = "Diversion",
+                                   area = NA))
+  g <- CreateGRiwrm(n_div)
+  Qobs = matrix(-1, nrow = length(DatesR), ncol = 1)
+  colnames(Qobs) = "54029"
+  IM <- suppressWarnings(
+    CreateInputsModel(g, DatesR, Precip, PotEvap, Qobs)
+  )
+  expect_equal(IM[["54032"]]$UpstreamNodes, c("54001", "54029"))
+  expect_equal(IM[["54032"]]$UpstreamVarQ , c("Qsim_m3", "Qsim_m3"))
+  expect_equal(IM[["54002"]]$UpstreamNodes, "54029")
+  expect_equal(IM[["54002"]]$UpstreamIsModeled  , TRUE)
+  expect_equal(IM[["54002"]]$UpstreamVarQ , "Qdiv_m3")
+  expect_equivalent(IM$`54029`$Qmin, matrix(0, nrow = length(DatesR), ncol = 1))
+})
+
+test_that("Diversion node: checks about 'Qmin'", {
+  n_div <- rbind(nodes,
+                 data.frame(id = "54029", down = "54002", length = 50, area = NA, model = "Diversion"))
+  g <- CreateGRiwrm(n_div)
+  Qobs = matrix(-1, nrow = length(DatesR), ncol = 1)
+  colnames(Qobs) = "54029"
+  expect_warning(CreateInputsModel(g, DatesR, Precip, PotEvap, Qobs = Qobs),
+                 regexp = "Zero values")
+  Qmin <- -Qobs
+  IM <- CreateInputsModel(g, DatesR, Precip, PotEvap, Qobs = Qobs, Qmin = Qmin)
+  expect_equivalent(IM$`54029`$Qmin, Qmin)
+  QminNA <- Qmin
+  QminNA[1] <- NA
+  expect_error(CreateInputsModel(g, DatesR, Precip, PotEvap, Qobs = Qobs, Qmin = QminNA),
+               regexp = "NA")
+  QminBadCol <- Qmin
+  colnames(QminBadCol) = "54002"
+  expect_error(CreateInputsModel(g, DatesR, Precip, PotEvap, Qobs = Qobs, Qmin = QminBadCol),
+               regexp = "columns that does not match with IDs of Diversion nodes")
+})
diff --git a/tests/testthat/test-CreateSupervisor.R b/tests/testthat/test-CreateSupervisor.R
new file mode 100644
index 0000000000000000000000000000000000000000..28bd79d2c75452ca22b218e40761dbc74e06eeca
--- /dev/null
+++ b/tests/testthat/test-CreateSupervisor.R
@@ -0,0 +1,45 @@
+# data set up
+e <- setupRunModel(runInputsModel = FALSE)
+# variables are copied from environment 'e' to the current environment
+# https://stackoverflow.com/questions/9965577/r-copy-move-one-environment-to-another
+for(x in ls(e)) assign(x, get(x, e))
+
+# Add 2 nodes to the network
+nodes2 <- rbind(nodes,
+                data.frame(
+                  id = c("R1", "R2"),
+                  down = "54057",
+                  length = 100,
+                  area = NA,
+                  model = NA
+                ))
+griwrm2 <- CreateGRiwrm(nodes2)
+
+# Add Qobs for the 2 new nodes and create InputsModel
+Qobs <- matrix(data = rep(0, 2*nrow(Qobs)), ncol = 2)
+colnames(Qobs) <- c("R1", "R2")
+InputsModel <-
+  CreateInputsModel(griwrm2, DatesR, Precip, PotEvap, Qobs)
+sv <- CreateSupervisor(InputsModel)
+
+test_that("Checks in CreateSupervisor", {
+  expect_error(CreateSupervisor(InputsModel, 3.14), regexp  = "integer")
+  expect_error(CreateSupervisor(InputsModel, 0L), regexp = "positive")
+  expect_s3_class(sv, "Supervisor")
+})
+
+test_that("Checks in CreateController",  {
+  FUN <- function(Y) return(0)
+  expect_error(CreateController(sv, 0, "54057", "R1", FUN),
+               regexp = "character")
+  expect_error(CreateController(sv, c("toto1", "toto2"), "54057", "R1", FUN),
+               regexp = "length")
+  expect_error(CreateController(sv, "toto", "fake", "R1", FUN),
+               regexp = "GRiwrm")
+  expect_error(CreateController(sv, "toto", "54057", "54057", FUN),
+               regexp = "DirectInjection")
+  CreateController(sv, "toto", "54057", "R1", FUN)
+  expect_s3_class(sv$controllers, "Controllers")
+  expect_s3_class(sv$controllers$toto, "Controller")
+})
+
diff --git a/tests/testthat/test-RunModel.R b/tests/testthat/test-RunModel.R
index 4b48b0e0abed15d40a68d00e277ae66fba6a8380..27868ca43cd226af01dd04738ea3acb5b5afc8bb 100644
--- a/tests/testthat/test-RunModel.R
+++ b/tests/testthat/test-RunModel.R
@@ -4,8 +4,6 @@ e <- setupRunModel()
 # https://stackoverflow.com/questions/9965577/r-copy-move-one-environment-to-another
 for(x in ls(e)) assign(x, get(x, e))
 
-context("RunModel.GRiwrmInputsModel")
-
 test_that("RunModel.GRiwrmInputsModel should return same result with separated warm-up", {
   RO_WarmUp <- CreateRunOptions(
     InputsModel,
@@ -34,8 +32,6 @@ test_that("RunModel.GRiwrmInputsModel should return same result with separated w
   })
 })
 
-context("RunModel.Supervisor")
-
 test_that("RunModel.Supervisor with no regulation should returns same results as RunModel.GRiwrmInputsModel", {
   sv <- CreateSupervisor(InputsModel)
   OM_Supervisor <- RunModel(
@@ -48,61 +44,6 @@ test_that("RunModel.Supervisor with no regulation should returns same results as
   })
 })
 
-# Add 2 nodes to the network
-nodes2 <- rbind(nodes,
-                data.frame(
-                  gauge_id = c("R1", "R2"),
-                  downstream_id = "54057",
-                  distance_downstream = 100,
-                  area = NA,
-                  model = NA
-                ))
-griwrm2 <- CreateGRiwrm(nodes2,
-                        list(id = "gauge_id",
-                             down = "downstream_id",
-                             length = "distance_downstream"))
-
-# Add Qobs for the 2 new nodes and create InputsModel
-Qobs2 <- cbind(Qobs, matrix(data = rep(0, 2*nrow(Qobs)), ncol = 2))
-colnames(Qobs2) <- c(colnames(Qobs2)[1:6], "R1", "R2")
-InputsModel <- suppressWarnings(
-  CreateInputsModel(griwrm2, DatesR, Precip, PotEvap, Qobs2)
-)
-
-test_that("RunModel.Supervisor with two regulations that cancel each other out should returns same results as RunModel.GRiwrmInputsModel", {
-  # Create Supervisor
-  sv <- CreateSupervisor(InputsModel)
-  # Function to withdraw half of the measured flow
-  fWithdrawal <- function(y) { -y/2 }
-  # Function to release half of the the measured flow
-  fRelease <- function(y) { y/2 }
-  # Controller that withdraw half of the flow measured at node "54002" at location "R1"
-  CreateController(sv, "Withdrawal", Y = c("54002"), U = c("R1"), FUN = fWithdrawal)
-  # Controller that release half of the flow measured at node "54002" at location "R2"
-  CreateController(sv, "Release", Y = c("54002"), U = c("R2"), FUN = fRelease)
-
-  OM_Supervisor <- RunModel(
-    sv,
-    RunOptions = RunOptions,
-    Param = ParamMichel
-  )
-  expect_equal(OM_Supervisor[["54057"]]$Qsim, OM_GriwrmInputs[["54057"]]$Qsim)
-})
-
-test_that("RunModel.Supervisor with multi time steps controller, two regulations in 1 centralised controller that cancel each other out should returns same results as RunModel.GRiwrmInputsModel", {
-  sv <- CreateSupervisor(InputsModel, TimeStep = 10L)
-  fEverything <- function(y) {
-    matrix(c(y[,1]/2, -y[,1]/2), ncol = 2)
-  }
-  CreateController(sv, "Everything", Y = c("54002", "54032"), U = c("R1", "R2"), FUN = fEverything)
-  OM_Supervisor <- RunModel(
-    sv,
-    RunOptions = RunOptions,
-    Param = ParamMichel
-  )
-  expect_equal(OM_Supervisor[["54057"]]$Qsim, OM_GriwrmInputs[["54057"]]$Qsim)
-})
-
 test_that("RunModel.GRiwrmInputsModel handles CemaNeige", {
   l <- setUpCemaNeigeData()
   l$griwrm[l$griwrm$id == "Down", "model"] <- "RunModel_GR4J"
@@ -118,8 +59,7 @@ test_that("RunModel.GRiwrmInputsModel handles CemaNeige", {
       PotEvap = l$PotEvap,
       TempMean = l$TempMean,
       ZInputs = l$ZInputs,
-      HypsoData = l$HypsoData,
-      Qobs = l$Qobs
+      HypsoData = l$HypsoData
     )
   )
   ## run period selection
@@ -145,25 +85,45 @@ test_that("RunModel.GRiwrmInputsModel handles CemaNeige", {
   expect_equal(Qm3s[,4], rowSums(Qm3s[,2:3]))
 })
 
-test_that("RunModel.Supervisor with NA values in Qupstream", {
-  # Create Supervisor
-  InputsModel$`54057`$Qupstream[, c("R1", "R2")] <- NA
-  sv <- CreateSupervisor(InputsModel)
-  # Function to withdraw half of the measured flow
-  fWithdrawal <- function(y) { -y/2 }
-  # Function to release half of the the measured flow
-  fRelease <- function(y) { y/2 }
-  # Controller that withdraw half of the flow measured at node "54002" at location "R1"
-  CreateController(sv, "Withdrawal", Y = c("54002"), U = c("R1"), FUN = fWithdrawal)
-  # Controller that release half of the flow measured at node "54002" at location "R2"
-  CreateController(sv, "Release", Y = c("54002"), U = c("R2"), FUN = fRelease)
+n_div <- rbind(nodes,
+               data.frame(id = "54029", down = "54002", length = 50, area = NA, model = "Diversion"))
+g_div <- CreateGRiwrm(n_div)
+Qmin = matrix(1E5, nrow = length(DatesR), ncol = 1)
+colnames(Qmin) = "54029"
+Qobs <- -Qmin
+IM_div <- CreateInputsModel(g_div, DatesR, Precip, PotEvap, Qobs = Qobs, Qmin = Qmin)
+RO_div <- setupRunOptions(IM_div)$RunOptions
+P_div <- ParamMichel
+P_div$`54002` <- c(1, ParamMichel$`54002`)
 
-  OM_Supervisor <- RunModel(
-    sv,
-    RunOptions = RunOptions,
-    Param = ParamMichel
-  )
-  expect_equal(OM_Supervisor[["54057"]]$Qsim[1:3], rep(as.double(NA),3))
-  expect_equal(OM_Supervisor[["54057"]]$Qsim[4:length(IndPeriod_Run)],
-               OM_GriwrmInputs[["54057"]]$Qsim[4:length(IndPeriod_Run)])
+test_that("RunModel_Diversion with zero diversion equals no diversion", {
+  Qobs[, ] <- 0
+  IM <- CreateInputsModel(g_div, DatesR, Precip, PotEvap, Qobs = Qobs, Qmin = Qmin)
+  OM <- RunModel(IM, RunOptions = RO_div, Param = P_div)
+  expect_s3_class(OM, "GRiwrmOutputsModel")
+  lapply(names(OM), function(id) {
+    expect_equal(OM[[!!id]]$Qsim, OM_GriwrmInputs[[!!id]]$Qsim)
+    expect_equal(OM[[!!id]]$Qsim_m3, OM_GriwrmInputs[[!!id]]$Qsim_m3)
+    expect_equal(OM[[!!id]]$RunOptions$WarmUpQsim, OM_GriwrmInputs[[!!id]]$RunOptions$WarmUpQsim)
+    expect_equal(OM[[!!id]]$RunOptions$WarmUpQsim_m3, OM_GriwrmInputs[[!!id]]$RunOptions$WarmUpQsim_m3)
+  })
+})
+
+test_that("Huge diversion would result in Qsim_m3 == Qmin", {
+  Qobs[, ] <- -1E12
+  IM <- CreateInputsModel(g_div, DatesR, Precip, PotEvap, Qobs = Qobs, Qmin = Qmin)
+  OM <- RunModel(IM, RunOptions = RO_div, Param = P_div)
+  expect_equal(OM[["54029"]]$Qsim_m3, Qmin[RunOptions[[1]]$IndPeriod_Run])
+  expect_equal(OM[["54029"]]$Qsim,
+               Qmin[RunOptions[[1]]$IndPeriod_Run] /
+                 g_div$area[g_div$id == "54029" & g_div$model != "Diversion"] / 1E3)
+})
+
+test_that("Huge minimum remaining flow results in Qdiv = 0", {
+  Qobs[, ] <- -1000
+  Qmin[, ] <- 1E12
+  IM <- CreateInputsModel(g_div, DatesR, Precip, PotEvap, Qobs = Qobs, Qmin = Qmin)
+  OM <- RunModel(IM, RunOptions = RO_div, Param = P_div)
+  expect_equal(OM[["54029"]]$Qsim, OM[["54029"]]$Qnat)
+  expect_equal(OM[["54029"]]$Qdiv_m3, rep(0, length(IndPeriod_Run)))
 })
diff --git a/tests/testthat/test-RunModel.Supervisor.R b/tests/testthat/test-RunModel.Supervisor.R
new file mode 100644
index 0000000000000000000000000000000000000000..d1f1636ab00cfa8f87b802ab843eeb9388e0b1d1
--- /dev/null
+++ b/tests/testthat/test-RunModel.Supervisor.R
@@ -0,0 +1,82 @@
+# data set up
+e <- setupRunModel()
+# variables are copied from environment 'e' to the current environment
+# https://stackoverflow.com/questions/9965577/r-copy-move-one-environment-to-another
+for(x in ls(e)) assign(x, get(x, e))
+
+# Add 2 nodes to the network
+nodes2 <- rbind(nodes,
+                data.frame(
+                  id = c("R1", "R2"),
+                  down = "54057",
+                  length = 100,
+                  area = NA,
+                  model = NA
+                ))
+griwrm2 <- CreateGRiwrm(nodes2)
+
+# Add Qobs for the 2 new nodes and create InputsModel
+Qobs <- matrix(data = rep(0, 2*nrow(Qobs)), ncol = 2)
+colnames(Qobs) <- c("R1", "R2")
+InputsModel <-
+  CreateInputsModel(griwrm2, DatesR, Precip, PotEvap, Qobs)
+
+test_that("RunModel.Supervisor with two regulations that cancel each other out should returns same results as RunModel.GRiwrmInputsModel", {
+  # Create Supervisor
+  sv <- CreateSupervisor(InputsModel)
+  # Function to withdraw half of the measured flow
+  fWithdrawal <- function(y) { -y/2 }
+  # Function to release half of the the measured flow
+  fRelease <- function(y) { y/2 }
+  # Controller that withdraw half of the flow measured at node "54002" at location "R1"
+  CreateController(sv, "Withdrawal", Y = c("54002"), U = c("R1"), FUN = fWithdrawal)
+  # Controller that release half of the flow measured at node "54002" at location "R2"
+  CreateController(sv, "Release", Y = c("54002"), U = c("R2"), FUN = fRelease)
+
+  OM_Supervisor <- RunModel(
+    sv,
+    RunOptions = RunOptions,
+    Param = ParamMichel
+  )
+  expect_equal(OM_Supervisor[["54057"]]$Qsim, OM_GriwrmInputs[["54057"]]$Qsim)
+})
+
+test_that("RunModel.Supervisor with multi time steps controller, two regulations
+          in 1 centralised controller that cancel each other out should returns
+          same results as RunModel.GRiwrmInputsModel", {
+  sv <- CreateSupervisor(InputsModel, TimeStep = 10L)
+  fEverything <- function(y) {
+    m <- matrix(c(y[,1]/2, -y[,1]/2), ncol = 2)
+  }
+  CreateController(sv, "Everything", Y = c("54002", "54032"), U = c("R1", "R2"), FUN = fEverything)
+  OM_Supervisor <- RunModel(
+    sv,
+    RunOptions = RunOptions,
+    Param = ParamMichel
+  )
+  expect_equal(OM_Supervisor[["54057"]]$Qsim, OM_GriwrmInputs[["54057"]]$Qsim)
+})
+
+test_that("RunModel.Supervisor with NA values in Qupstream", {
+  # Create Supervisor
+  InputsModel$`54057`$Qupstream[, c("R1", "R2")] <- NA
+  sv <- CreateSupervisor(InputsModel)
+  # Function to withdraw half of the measured flow
+  fWithdrawal <- function(y) { -y/2 }
+  # Function to release half of the the measured flow
+  fRelease <- function(y) { y/2 }
+  # Controller that withdraw half of the flow measured at node "54002" at location "R1"
+  CreateController(sv, "Withdrawal", Y = c("54002"), U = c("R1"), FUN = fWithdrawal)
+  # Controller that release half of the flow measured at node "54002" at location "R2"
+  CreateController(sv, "Release", Y = c("54002"), U = c("R2"), FUN = fRelease)
+
+  OM_Supervisor <- RunModel(
+    sv,
+    RunOptions = RunOptions,
+    Param = ParamMichel
+  )
+  expect_equal(OM_Supervisor[["54057"]]$Qsim[1:3], rep(as.double(NA),3))
+  expect_equal(OM_Supervisor[["54057"]]$Qsim[4:length(IndPeriod_Run)],
+               OM_GriwrmInputs[["54057"]]$Qsim[4:length(IndPeriod_Run)])
+})
+
diff --git a/tests/testthat/test-calc_Qdiv.R b/tests/testthat/test-calc_Qdiv.R
new file mode 100644
index 0000000000000000000000000000000000000000..f4499f34f923e2dd989dbf3c25548037bfca0349
--- /dev/null
+++ b/tests/testthat/test-calc_Qdiv.R
@@ -0,0 +1,34 @@
+test_that("calc_Qdiv works", {
+  expect_equal(
+    calc_Qdiv(Qnat = 1, Qdiv = 1, Qmin = 0),
+    list(Qsim = 0, Qdiv = 1)
+  )
+  expect_equal(
+    calc_Qdiv(Qnat = 5, Qdiv = 4, Qmin = 3),
+    list(Qsim = 3, Qdiv = 2)
+  )
+  expect_equal(
+    calc_Qdiv(Qnat = 5, Qdiv = 10, Qmin = 3),
+    list(Qsim = 3, Qdiv = 2)
+  )
+  expect_equal(
+    calc_Qdiv(Qnat = 5, Qdiv = 1, Qmin = 3),
+    list(Qsim = 4, Qdiv = 1)
+  )
+  expect_equal(
+    calc_Qdiv(Qnat = 3, Qdiv = 1, Qmin = 4),
+    list(Qsim = 3, Qdiv = 0)
+  )
+  expect_equal(
+    calc_Qdiv(Qnat = 3, Qdiv = -1, Qmin = 5),
+    list(Qsim = 4, Qdiv = -1)
+  )
+  expect_equal(
+    calc_Qdiv(Qnat = 3, Qdiv = -1, Qmin = 2),
+    list(Qsim = 4, Qdiv = -1)
+  )
+  expect_equal(
+    calc_Qdiv(Qnat = rep(1E6, 2), Qdiv = rep(1000, 2), Qmin = rep(1E12, 2)),
+    list(Qsim = rep(1E6, 2), Qdiv = rep(0, 2))
+  )
+})
diff --git a/tests/testthat/test-createGRiwrm.R b/tests/testthat/test-createGRiwrm.R
index 5b0e896fc0cb48171ec88138cfbfb973802402a2..8d34821d91cc64fd04649dd0e4e48e64fdff8773 100644
--- a/tests/testthat/test-createGRiwrm.R
+++ b/tests/testthat/test-createGRiwrm.R
@@ -19,29 +19,50 @@ H5920010	602213	2427449	43824.66	La Seine à Paris [Austerlitz après création
 
 })
 
+# Setup a simple data.frame for GRiwrm
+nodes <- loadSevernNodes()
+
+test_that("Hydrological model nodes must have numeric area", {
+  nodes$area[nodes$id == "54057"] <- NA
+  expect_error(CreateGRiwrm(nodes),
+               regexp = "hydrological")
+})
+
+test_that("Duplicated nodes",  {
+  nodes <- rbind(nodes, nodes[4,])
+  expect_error(CreateGRiwrm(nodes),
+               regexp = "Duplicated nodes detected")
+})
+
 test_that("NA or Ungauged nodes at downstream should throw an error", {
-  data(Severn)
-  nodes <-
-    Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")]
-  nodes$model <- "RunModel_GR4J"
-  nodes$model[nodes$gauge_id == "54057"] <- "Ungauged"
-  expect_error(CreateGRiwrm(
-    nodes,
-    list(
-      id = "gauge_id",
-      down = "downstream_id",
-      length = "distance_downstream"
-    )
-  ),
-  regexp = "downstream node")
+  nodes$model[nodes$id == "54057"] <- "Ungauged"
+  expect_error(CreateGRiwrm(nodes),
+               regexp = "downstream node")
   nodes$model[nodes$gauge_id == "54057"] <- NA
-  expect_error(CreateGRiwrm(
-    nodes,
-    list(
-      id = "gauge_id",
-      down = "downstream_id",
-      length = "distance_downstream"
-    )
-  ),
-  regexp = "downstream node")
+  expect_error(CreateGRiwrm(nodes),
+               regexp = "downstream node")
+})
+
+test_that("Diversion node", {
+  nodes <- rbind(nodes,
+                 data.frame(id = "54029", down = "54002", length = 50, area = NA, model = "Diversion"))
+  expect_s3_class(CreateGRiwrm(nodes), "GRiwrm")
+  n99 <- nodes
+  n99$area[n99$model == "Diversion"] <- 99
+  expect_error(CreateGRiwrm(n99),
+               regexp = "Diversion node must have its area")
+  n_orphan <- nodes
+  n_orphan$id[n_orphan$model == "Diversion"] <- "54999"
+  expect_error(CreateGRiwrm(n_orphan),
+               regexp = "Diversion node must have the same `id` of")
+  n_samedown <- nodes
+  n_samedown$down[n_samedown$model == "Diversion"] <- "54032"
+  expect_error(CreateGRiwrm(n_samedown),
+               regexp = "downstream node of a Diversion node must be different")
+})
+
+test_that("Allow several downstream ends", {
+  nodes <- rbind(nodes,
+                 data.frame(id = "54029", down = NA, length = NA, area = NA, model = "Diversion"))
+  expect_s3_class(CreateGRiwrm(nodes), "GRiwrm")
 })
diff --git a/tests/testthat/test-getNodeRanking.R b/tests/testthat/test-getNodeRanking.R
new file mode 100644
index 0000000000000000000000000000000000000000..2fcf4dc1d072061d23b58329a4693bda7335b146
--- /dev/null
+++ b/tests/testthat/test-getNodeRanking.R
@@ -0,0 +1,26 @@
+nodes <- loadSevernNodes()
+
+test_that("Check ranking on Severn example", {
+  g <- CreateGRiwrm(nodes)
+  expect_equal(getNodeRanking(g),
+               c("54095", "54002", "54029", "54001", "54032", "54057"))
+})
+
+test_that("Check ranking with direct injection node", {
+  nodes$model[nodes$id == "54029"] <- NA
+  g <- CreateGRiwrm(nodes)
+  expect_equal(getNodeRanking(g),
+               c("54095", "54002", "54001", "54032", "54057"))
+})
+
+test_that("Check ranking with Diversion", {
+  n_div <- rbind(nodes, data.frame(id = "54029",
+                                   down = "54002",
+                                   length = 20,
+                                   model = "Diversion",
+                                   area = NA))
+  g <- CreateGRiwrm(n_div)
+  r <- getNodeRanking(g)
+  expect_lt(which(r == "54029"), which(r == "54002"))
+})
+
diff --git a/vignettes/V04_Closed-loop_regulated_withdrawal.Rmd b/vignettes/V04_Closed-loop_regulated_withdrawal.Rmd
index e2e46c119142e3a9758df053890563b0bfeaf4f6..8325e86da6ed16f781a1c098624cd7c00c1a88b3 100644
--- a/vignettes/V04_Closed-loop_regulated_withdrawal.Rmd
+++ b/vignettes/V04_Closed-loop_regulated_withdrawal.Rmd
@@ -255,10 +255,10 @@ for (x in 1:ncol(m))
 As for the previous model, we need to set up an `GRiwrmInputsModel` object containing all the model inputs:
 
 ```{r}
-# A flow is needed for all direct injection nodes in the network
+# Flow time series are needed for all direct injection nodes in the network
 # even if they may be overwritten after by a controller
-# The Qobs matrix is completed with 2 new columns for the new nodes
-QobsIrrig <- cbind(Qobs, Irrigation1 = 0, Irrigation2 = 0)
+QobsIrrig <- data.frame(Irrigation1 = rep(0, length(DatesR)), 
+                        Irrigation2 = rep(0, length(DatesR)))
 
 # Creation of the GRiwrmInputsModel object
 IM_Irrig <- CreateInputsModel(griwrmV04, DatesR, Precip, PotEvap, QobsIrrig)
diff --git a/vignettes/V05_Modelling_ungauged_nodes.Rmd b/vignettes/V05_Modelling_ungauged_nodes.Rmd
index 4aace25a8d5a3d82db4a3c42a14f2593b6f7c2cd..190fedfefd03af1d93c2f9d90d88933009655c99 100644
--- a/vignettes/V05_Modelling_ungauged_nodes.Rmd
+++ b/vignettes/V05_Modelling_ungauged_nodes.Rmd
@@ -117,13 +117,12 @@ PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
 PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
 Precip <- ConvertMeteoSD(griwrmV05, PrecipTot)
 PotEvap <- ConvertMeteoSD(griwrmV05, PotEvapTot)
-Qobs <- cbind(sapply(BasinsObs, function(x) {x$discharge_spec}))
 ```
 
 Then, the `GRiwrmInputsModel` object can be generated taking into account the new `GRiwrm` object:
 
 ```{r InputsModel}
-IM_U <- CreateInputsModel(griwrmV05, DatesR, Precip, PotEvap, Qobs)
+IM_U <- CreateInputsModel(griwrmV05, DatesR, Precip, PotEvap)
 ```
 ## Calibration of the model integrating ungauged nodes
 
@@ -141,6 +140,7 @@ IndPeriod_WarmUp = seq(1,IndPeriod_Run[1]-1)
 RunOptions <- CreateRunOptions(IM_U,
                                IndPeriod_WarmUp = IndPeriod_WarmUp,
                                IndPeriod_Run = IndPeriod_Run)
+Qobs <- cbind(sapply(BasinsObs, function(x) {x$discharge_spec}))
 InputsCrit <- CreateInputsCrit(IM_U,
                                FUN_CRIT = ErrorCrit_KGE2,
                                RunOptions = RunOptions, Obs = Qobs[IndPeriod_Run,],
diff --git a/vignettes/V06_Modelling_regulated_diversion.Rmd b/vignettes/V06_Modelling_regulated_diversion.Rmd
new file mode 100644
index 0000000000000000000000000000000000000000..d8a64b4bcc4d62835b73ae29e0c5a50dfa015b04
--- /dev/null
+++ b/vignettes/V06_Modelling_regulated_diversion.Rmd
@@ -0,0 +1,215 @@
+---
+title: "Severn_06: Modelling of a regulated diversion"
+output: rmarkdown::html_vignette
+vignette: >
+  %\VignetteIndexEntry{Severn_06: Modelling of a regulated diversion}
+  %\VignetteEngine{knitr::rmarkdown}
+  %\VignetteEncoding{UTF-8}
+---
+
+```{r, include = FALSE}
+knitr::opts_chunk$set(
+  collapse = TRUE,
+  comment = "#>",
+  fig.width = 6,
+  fig.asp = 0.68,
+  out.width = "70%",
+  fig.align = "center"
+)
+```
+
+```{r setup}
+library(airGRiwrm)
+data(Severn)
+```
+
+## The study case
+
+In this vignette, we are still using the study case of the vignette #1 and #2, and 
+we are going to simulate a diversion at the node "54001" to provide flow to the node 
+"54029" in order to support low flows in the Severn river.
+
+This objective is to maintain a minimum flow equals to the 3th decile of the flow 
+at station "54029" without remaining less than the first decile of the flow downstream 
+the station "54001".
+
+Let's compute the flow quantiles at each station in m3/s:
+
+```{r}
+Qobs <- cbind(sapply(Severn$BasinsObs, function(x) {x$discharge_spec}))
+Qobs <- Qobs[, Severn$BasinsInfo$gauge_id]
+Qobs_m3s <- t(apply(Qobs, 1, function(r) r * Severn$BasinsInfo$area * 1E3 / 86400))
+apply(Qobs_m3s[, c("54029", "54001")], 2, quantile, probs = seq(0,1,0.1), na.rm = TRUE)
+```
+
+The rule to apply is expressed as follow:
+
+> The diversion from "54001" is computed to maintain a minimum flow of 5.3 m3/s at
+the gauging station "54029". The diversion is allowed as far as the flow at the 
+gauging station "54001" is above 11.5 m3/s.
+
+## Network
+
+```{r}
+
+nodes_div <- Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")]
+nodes_div$model <- "RunModel_GR4J"
+nodes_div <- rbind(nodes_div, data.frame(gauge_id = "54001",
+                                         downstream_id = "54029",
+                                         distance_downstream = 25,
+                                         model = "Diversion",
+                                         area = NA))
+renameCols <- list(id = "gauge_id", down = "downstream_id", length = "distance_downstream")
+griwrmV06 <- CreateGRiwrm(nodes_div, renameCols)
+plot(griwrmV06)
+```
+
+## GRiwrmInputsModel object
+
+We produce below the same operations as in the vignette "V02_Calibration_SD_model" to prepare the input data:
+
+```{r}
+data(Severn)
+nodes <- Severn$BasinsInfo[, c("gauge_id", "downstream_id", "distance_downstream", "area")]
+nodes$model <- "RunModel_GR4J"
+griwrm <- CreateGRiwrm(nodes, list(id = "gauge_id", down = "downstream_id", length = "distance_downstream"))
+BasinsObs <- Severn$BasinsObs
+DatesR <- BasinsObs[[1]]$DatesR
+PrecipTot <- cbind(sapply(BasinsObs, function(x) {x$precipitation}))
+PotEvapTot <- cbind(sapply(BasinsObs, function(x) {x$peti}))
+Precip <- ConvertMeteoSD(griwrm, PrecipTot)
+PotEvap <- ConvertMeteoSD(griwrm, PotEvapTot)
+```
+
+The main difference here is that we need to provide a diverted flow and a minimum
+remaining flow at station "54029". As, the diverted flow will be calculated during 
+simulation, we provide a initial diverted flow equals to zero for all the time steps.
+
+```{r}
+Qdiv <- matrix(rep(0, length(DatesR)), ncol = 1)
+colnames(Qdiv) <- "54001"
+Qmin <- matrix(rep(11.5 * 86400, length(DatesR)), ncol = 1)
+colnames(Qmin) <- "54001"
+IM_div <- CreateInputsModel(griwrmV06, DatesR, Precip, PotEvap, Qobs = Qdiv, Qmin = Qmin)
+```
+
+## Implementation of the regulation controller
+
+### The supervisor
+
+The simulation is piloted through a `Supervisor` that can contain one or more 
+`Controller`. The supervision time step will be here the same as the simulation 
+time step:  1 day. Each day, the decision is taken for the current day from the 
+measurement simulated the previous time step.
+
+```{r}
+sv <- CreateSupervisor(IM_div, TimeStep = 1L)
+```
+
+### The control logic function
+
+On a Diversion node, the minimum remaining flow is provided with the inputs and 
+is automatically taken into account by the model. So the control logic function
+has only to take care about how much water to divert to the gauging station 
+"54002".
+
+We need to enclose the logic function in a function factory providing the 
+Supervisor in the environment of the function:
+
+```{r}
+#' @param sv the Supervisor environment
+logicFunFactory <- function(sv) {
+  #' @param Y Flow measured at "54002" the previous time step
+  function(Y) {
+    Qnat <- Y
+    #  We need to remove the diverted flow to compute the natural flow at "54002"
+    lastU <- sv$controllers[[sv$controller.id]]$U
+    if (length(lastU) > 0) {
+      Qnat <- max(0, Y + lastU)
+    }
+    message(paste(round(c(Y, lastU, Qnat, -max(5.3 * 86400 - Qnat, 0))), collapse = ", "))
+    return(-max(5.3 * 86400 - Qnat, 0))
+  }
+}
+```
+
+### The controller
+
+We declare the controller which defines where is the measurement `Y` , where to 
+apply the decision `U` with which logic function:
+
+```{r}
+CreateController(sv,
+                 ctrl.id = "Low flow support",
+                 Y = "54029",
+                 U = "54001",
+                 FUN = logicFunFactory(sv))
+```
+
+
+## Running the simulation
+
+First we need to create a `GRiwrmRunOptions` object and load the parameters calibrated in the vignette "V02_Calibration_SD_model":
+
+```{r}
+# Running simulation between 2002 and 2005
+IndPeriod_Run <- which(
+  DatesR >= as.POSIXct("2003-03-01", tz = "UTC") & 
+    DatesR <= as.POSIXct("2004-01-01", tz = "UTC")
+)
+IndPeriod_WarmUp = seq(IndPeriod_Run[1] - 366,IndPeriod_Run[1] - 1)
+RunOptions <- CreateRunOptions(IM_div,
+                               IndPeriod_WarmUp = IndPeriod_WarmUp,
+                               IndPeriod_Run = IndPeriod_Run)
+ParamV02 <- readRDS(system.file("vignettes", "ParamV02.RDS", package = "airGRiwrm"))
+```
+
+The node "54029" was initially an upstream node. As it receive water from "54001"
+it is no longer an upstream node and need a parameter for routing its upstream 
+flows. We arbitrary say that the velocity in the channel between "54001" and 
+"54029" is 1 m/s.
+
+```{r}
+ParamV02$`54029` <- c(1, ParamV02$`54029`)
+```
+
+And we run the supervised model:
+
+```{r}
+OM_div <- RunModel(sv, RunOptions = RunOptions, Param = ParamV02)
+```
+
+To compare results with diversion and without diversion, we run the model without
+the supervision (remember that we have set the diverted flow at zero in the inputs):
+
+```{r}
+OM_nat <- RunModel(IM_div, RunOptions = RunOptions, Param = ParamV02)
+```
+
+
+## Exploring results
+
+Let's plot the diverted flow, and compare the flow at stations 54029 and 54001, 
+with and without low-flow support at station 54001:
+
+```{r, fig.asp=1}
+dfQdiv <- data.frame(DatesR = OM_div[[1]]$DatesR,
+                     Diverted_flow = OM_div$`54001`$Qdiv_m3 / 86400)
+
+oldpar <- par(mfrow=c(3,1), mar = c(2.5,4,1,1))
+plot.Qm3s(dfQdiv)
+
+# Plot natural and influenced flow at station "54001" and "54029"
+thresholds <- c("54001" = 11.5, "54029" = 5.3)
+lapply(names(thresholds), function(id) {
+  df <- cbind(attr(OM_div, "Qm3s")[, c("DatesR", id)],
+                   attr(OM_nat, "Qm3s")[, id])
+  names(df) <- c("DatesR", 
+                      paste(id, "with low-flow support"), 
+                      paste(id, "natural flow"))
+  plot.Qm3s(df, ylim = c(0,50), lty = c("solid", "dashed"))
+  abline(h = thresholds[id], col = "green", lty = "dotted")
+})
+par(oldpar)
+```
+