diff --git a/NAMESPACE b/NAMESPACE
index 8348ba43e310606ba7183ff78740ef1d789dbab3..7769adf8b96150e8c1790d81bc2aabe724578fcb 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -55,6 +55,7 @@ export(RunModel_GR5J)
 export(RunModel_GR6J)
 export(RunModel_Lag)
 export(RunModel_LLR)
+export(RunModel_LBLR)
 export(SeriesAggreg)
 export(TransfoParam)
 export(TransfoParam_CemaNeige)
@@ -68,6 +69,7 @@ export(TransfoParam_GR5J)
 export(TransfoParam_GR6J)
 export(TransfoParam_Lag)
 export(TransfoParam_LLR)
+export(TransfoParam_LBLR)
 export(.ErrorCrit)
 export(.FeatModels)
 
diff --git a/R/CreateCalibOptions.R b/R/CreateCalibOptions.R
index 9102561e3700abb14637a8546f1a4db45b3bb8b8..8c2cb2e0539d0a78878f7bc72048e0f93e2f598d 100644
--- a/R/CreateCalibOptions.R
+++ b/R/CreateCalibOptions.R
@@ -207,10 +207,16 @@ CreateCalibOptions <- function(FUN_MOD,
                              +5.00), ncol = 1, byrow = TRUE)
         ParamT <- cbind(ParamTSD, ParamT)
       }
-      if (identical(RunModel_LLR, FUN_SD)){
-        ParamTSD <- matrix(c(+1.25, +1.25,
-                             +2.50, +2.50,
-                             +5.00, +5.00), ncol = 2, byrow = TRUE)
+      else if (identical(RunModel_LLR, FUN_SD)){
+        ParamTSD <- matrix(c(+1.25, 0,
+                             +2.50, 250,
+                             +5.00, 500), ncol = 2, byrow = TRUE)
+        ParamT <- cbind(ParamTSD, ParamT)
+      }
+      else if (identical(RunModel_LBLR, FUN_SD)){
+        ParamTSD <- matrix(c(+1.25, 0,
+                             +2.50, 250,
+                             +5.00, 500), ncol = 2, byrow = TRUE)
         ParamT <- cbind(ParamTSD, ParamT)
       }
     }
diff --git a/R/RunModel_LBLR.R b/R/RunModel_LBLR.R
new file mode 100644
index 0000000000000000000000000000000000000000..9d483ee70cbcdd46d7e48011bf2d28be13693e3f
--- /dev/null
+++ b/R/RunModel_LBLR.R
@@ -0,0 +1,199 @@
+RunModel_LBLR <- function(InputsModel, RunOptions, Param, QcontribDown) {
+  NParam <- 2
+
+  ## argument check
+  if (!inherits(InputsModel, "InputsModel")) {
+    stop("'InputsModel' must be of class 'InputsModel'")
+  }
+  if (!inherits(InputsModel, "SD")) {
+    stop("'InputsModel' must be of class 'SD'")
+  }
+  if (!inherits(RunOptions, "RunOptions")) {
+    stop("'RunOptions' must be of class 'RunOptions'")
+  }
+  if (!is.vector(Param) | !is.numeric(Param)) {
+    stop("'Param' must be a numeric vector")
+  }
+  if (sum(!is.na(Param)) != NParam) {
+    stop(paste("'Param' must be a vector of length", NParam, "and contain no NA"))
+  }
+  if (inherits(QcontribDown, "OutputsModel")) {
+    if (is.null(QcontribDown$Qsim)) {
+      stop("'QcontribDown' should contain a key 'Qsim' containing the output of the runoff of the downstream subcatchment")
+    }
+    if (length(QcontribDown$Qsim) != length(RunOptions$IndPeriod_Run)) {
+      stop("Time series Qsim in 'QcontribDown' should have the same length as 'RunOptions$IndPeriod_Run'")
+    }
+    if (!identical(RunOptions$IndPeriod_WarmUp, 0L) && !identical(RunOptions$Outputs_Sim, RunOptions$Outputs_Cal)) {
+      # This test is not necessary during calibration but usefull in other cases because
+      # WarmUpQsim is then used for downstream sub-basins because of the delay in Qupstream
+      if (is.null(QcontribDown$RunOptions$WarmUpQsim) ||
+          length(QcontribDown$RunOptions$WarmUpQsim) != length(RunOptions$IndPeriod_WarmUp)) {
+        stop("Time series WarmUpQsim in 'QcontribDown' should have the same length as 'RunOptions$IndPeriod_WarmUp'")
+      }
+    }
+  } else if (is.vector(QcontribDown) && is.numeric(QcontribDown)) {
+    if (length(QcontribDown) != length(RunOptions$IndPeriod_Run)) {
+      stop("'QcontribDown' should have the same length as 'RunOptions$IndPeriod_Run'")
+    }
+  } else {
+    stop("'QcontribDown' must be a numeric vector or a 'OutputsModel' object")
+  }
+
+  # data set up
+
+  NbUpBasins <- length(InputsModel$LengthHydro)
+  if (identical(RunOptions$IndPeriod_WarmUp, 0L)) {
+    RunOptions$IndPeriod_WarmUp <- NULL
+  }
+  IndPeriod1   <- c(RunOptions$IndPeriod_WarmUp, RunOptions$IndPeriod_Run)
+  LInputSeries <- as.integer(length(IndPeriod1))
+  IndPeriod2 <- (length(RunOptions$IndPeriod_WarmUp)+1):LInputSeries
+
+  if (inherits(QcontribDown, "OutputsModel")) {
+    OutputsModel <- QcontribDown
+    if (is.null(OutputsModel$RunOptions$WarmUpQsim)) {
+      OutputsModel$RunOptions$WarmUpQsim <- rep(NA, length(RunOptions$IndPeriod_WarmUp))
+    }
+    QsimDown <- c(OutputsModel$RunOptions$WarmUpQsim, OutputsModel$Qsim)
+  } else if (is.vector(QcontribDown) && is.numeric(QcontribDown)) {
+    OutputsModel <- list()
+    class(OutputsModel) <- c("OutputsModel", class(RunOptions)[-1])
+    QsimDown <- c(rep(NA, length(RunOptions$IndPeriod_WarmUp)),
+                  QcontribDown)
+  }
+
+
+  ## Parameters set up
+  TParam <- Param[1L]
+  KParam <- Param[2L]
+
+
+  PK <- ifelse(InputsModel$LengthHydro == 0, 0,
+               sqrt(InputsModel$LengthHydro/max(InputsModel$LengthHydro)) * KParam)
+
+  PT <-  ifelse(InputsModel$LengthHydro == 0, 0,
+                InputsModel$LengthHydro/max(InputsModel$LengthHydro)) * (TParam + KParam) - PK
+  PT <- ifelse(PT < 0, 0, PT)
+  rprop <- PT - floor(PT)
+
+  ## Lag set up
+  first_lag <- function(t, Qroute, Qupstream){
+    Q <- c(Qupstream[1 : (floor(t) + 1)], Qroute[1 : (length(Qroute) - (floor(t) + 1))])
+    return(Q)
+  }
+  scnd_lag <- function(t, Qroute, Qupstream){
+    Q <-  c(Qupstream[1 : floor(t)], Qroute[1 : (length(Qroute) - floor(t))])
+    return(Q)
+  }
+
+
+  ## set up initial states
+  IniSD <- RunOptions$IniStates[grep("SD", names(RunOptions$IniStates))]
+  if (length(IniSD) > 0) {
+    if (sum(floor(PT)) + NbUpBasins != length(IniSD)) {
+      stop(
+        sprintf(
+          "SD initial states has a length of %i and a length of %i is required",
+          length(IniSD),
+          sum(floor(PT)) + NbUpBasins
+        )
+      )
+    }
+    IniStates <- lapply(seq_len(NbUpBasins), function(x) {
+      iStart <- 1
+      if (x > 1) {
+        iStart <- iStart + sum(floor(PT[1:x - 1]) + 1)
+      }
+      as.vector(IniSD[iStart:(iStart + PT[x])])
+    })
+  } else {
+    IniStates <- lapply(
+      seq_len(NbUpBasins),
+      function(iUpBasins) {
+        iWarmUp <- seq.int(
+          from = max(1, IndPeriod1[1] - floor(PT[iUpBasins]) - 1),
+          to   = max(1, IndPeriod1[1] - 1)
+        )
+        ini <- InputsModel$Qupstream[iWarmUp, iUpBasins]
+        if (length(ini) != floor(PT[iUpBasins] + 1)) {
+          # If warm-up period is not enough long complete beginning with first value
+          ini <- c(rep(ini[1], floor(PT[iUpBasins] + 1)))
+        }
+        return(as.vector(ini))
+      }
+    )
+  }
+
+
+  ## Lag & route model computation
+  Qsim_m3 <- matrix(0
+                    , nrow = length(IndPeriod1), ncol = NbUpBasins)
+  QsimDown_input <- matrix(QsimDown *
+                       InputsModel$BasinAreas[length(InputsModel$BasinAreas)] * 1e3, ncol = 1)
+  for (upstream_basin in seq_len(NbUpBasins)) {
+    Qupstream_m3 <- c(IniStates[[upstream_basin]],
+                      InputsModel$Qupstream[IndPeriod1, upstream_basin])
+    Qroute <- Qupstream_m3
+    for (q_upstream in seq_along(Qupstream_m3)[2:max(seq_along(Qupstream_m3))]){
+      Qroute[q_upstream] <- (1 - 1/PK[upstream_basin]) * Qroute[q_upstream - 1] +
+        1/ PK[upstream_basin] * Qupstream_m3[q_upstream]
+    }
+    Qsim_m3[, upstream_basin] <- first_lag(PT[upstream_basin], Qroute, Qupstream_m3)[IndPeriod1] *
+      rprop[upstream_basin] + scnd_lag(PT[upstream_basin], Qroute, Qupstream_m3)[IndPeriod1] * (1 - rprop[upstream_basin])
+  }
+  Qsim_m3 <- cbind(QsimDown_input, Qsim_m3)
+  Qsim_m3 <- rowSums(Qsim_m3)
+
+  ## OutputsModel
+  if ("Qsim_m3" %in% RunOptions$Outputs_Sim) {
+    OutputsModel$Qsim_m3 <- Qsim_m3[IndPeriod2]
+  }
+
+  if ("Qsim" %in% RunOptions$Outputs_Sim) {
+    # Convert back Qsim to mm
+    OutputsModel$Qsim <- Qsim_m3[IndPeriod2] / sum(InputsModel$BasinAreas, na.rm = TRUE) / 1e3
+    # message("Qsim: ", paste(OutputsModel$Qsim, collapse = ", "))
+  }
+
+  if ("QsimDown" %in% RunOptions$Outputs_Sim) {
+    # Convert back Qsim to mm
+    OutputsModel$QsimDown <- QsimDown[IndPeriod2]
+  }
+
+  # Warning for negative flows or NAs only in extended outputs
+  if (length(RunOptions$Outputs_Sim) > 2) {
+    if (any(OutputsModel$Qsim[!is.na(OutputsModel$Qsim)] < 0)) {
+      warning(length(which(OutputsModel$Qsim < 0)), " time steps with negative flow, set to zero.")
+      OutputsModel$Qsim[OutputsModel$Qsim < 0] <- 0
+    }
+    # Warning for NAs
+    if (any(is.na(OutputsModel$Qsim))) {
+      warning(length(which(is.na(OutputsModel$Qsim))), " time steps with NA values")
+    }
+  }
+
+  if ("StateEnd" %in% RunOptions$Outputs_Sim) {
+    SD <- lapply(seq(NbUpBasins), function(x) {
+      lastTS <- RunOptions$IndPeriod_Run[length(RunOptions$IndPeriod_Run)]
+      InputsModel$Qupstream[(lastTS - floor(PT[x])):lastTS, x]
+    })
+    if (is.null(OutputsModel$StateEnd)) {
+      OutputsModel$StateEnd <- CreateIniStates(RunModel_LLR, InputsModel, SD = SD)
+    } else {
+      OutputsModel$StateEnd$SD <- SD
+    }
+    # message("StateEnd: ", paste(OutputsModel$StateEnd$SD, collapse = ", "))
+  }
+  if ("WarmUpQsim" %in% RunOptions$Outputs_Sim) {
+    OutputsModel$RunOptions$WarmUpQsim <- Qsim_m3[seq_len(length(RunOptions$IndPeriod_WarmUp))] / sum(InputsModel$BasinAreas, na.rm = TRUE) / 1e3
+  }
+
+  if ("Param" %in% RunOptions$Outputs_Sim) {
+    OutputsModel$RunOptions$Param <- c(Param, OutputsModel$RunOptions$Param)
+  }
+
+  class(OutputsModel) <- c(class(OutputsModel), "SD")
+
+  return(OutputsModel)
+}
diff --git a/R/TransfoParam_LBLR.R b/R/TransfoParam_LBLR.R
new file mode 100644
index 0000000000000000000000000000000000000000..e92baf75630348732ac5114ded93ff9003472c76
--- /dev/null
+++ b/R/TransfoParam_LBLR.R
@@ -0,0 +1,42 @@
+TransfoParam_LBLR <- function(ParamIn, Direction) {
+
+  ## number of model parameters
+  NParam <- 2L
+
+  ## check arguments
+  isVecParamIn <- is.vector(ParamIn)
+  if (isVecParamIn) {
+    ParamIn <- matrix(ParamIn, nrow = 1)
+  }
+  if (!inherits(ParamIn, "matrix")) {
+    stop("'ParamIn' must be of class 'matrix'")
+  }
+  if (!inherits(Direction, "character") | length(Direction) != 1 | any(!Direction %in% c("RT", "TR"))) {
+    stop("'Direction' must be a character vector of length 1 equal to 'RT' or 'TR'")
+  }
+  if (ncol(ParamIn) != NParam) {
+    stop(sprintf("the Lag & Route model requires %i parameters", NParam))
+  }
+
+
+  ## transformation
+  if (Direction == "TR") {
+    ParamOut <- ParamIn
+    ParamOut[, 1] <- 20 * (ParamIn[, 1] + 10) / 20.0
+    ParamOut[, 2] <-  20 * (ParamIn[, 2] + 10) / 20.0
+  }
+  if (Direction == "RT") {
+    ParamOut <- ParamIn
+    ParamOut[, 1] <- ParamIn[, 1] * 20.0 / 20 - 10
+    ParamOut[, 2] <- ParamIn[, 2] * 20.0 / 20 - 10
+  }
+
+
+  ## check output
+  if (isVecParamIn) {
+    ParamOut <- as.vector(ParamOut)
+  }
+
+  return(ParamOut)
+
+}
diff --git a/R/Utils.R b/R/Utils.R
index 87b91ce17a5458690d7fdd290f8ab39c8c265fa0..e6cfa5ee255307c6eb258b8597c717abb8ae877c 100644
--- a/R/Utils.R
+++ b/R/Utils.R
@@ -80,6 +80,9 @@
       }else if(identical(RunModel_LLR, FUN_SD)){
         res$NParamSD <- FeatMod$NbParam[15]
         res$FUN_SD <- "LLR"
+      }else if(identical(RunModel_LBLR, FUN_SD)){
+        res$NParamSD <- FeatMod$NbParam[16]
+        res$FUN_SD <- "LBLR"
       }
     }
     return(res)
diff --git a/R/UtilsCalibOptions.R b/R/UtilsCalibOptions.R
index 38d1c0337f07dde1676b0c10b9bc187580d223cc..010271e2d2a48eb9f1e908891465078e71bb8d8b 100644
--- a/R/UtilsCalibOptions.R
+++ b/R/UtilsCalibOptions.R
@@ -31,6 +31,8 @@
       FUN_ROUT <- TransfoParam_Lag
     } else if (identical(RunModel_LLR, FUN_SD)){
       FUN_ROUT <- TransfoParam_LLR
+    } else if (identical(RunModel_LBLR, FUN_SD)){
+      FUN_ROUT <- TransfoParam_LBLR
     }
   }
 
diff --git a/inst/modelsFeatures/FeatModelsGR.csv b/inst/modelsFeatures/FeatModelsGR.csv
index d23cc8e061070307219924d82aa8e0d5297c7d23..71d2324046ab3edb6a9d7255be14252da95be258 100644
--- a/inst/modelsFeatures/FeatModelsGR.csv
+++ b/inst/modelsFeatures/FeatModelsGR.csv
@@ -14,3 +14,4 @@ CemaNeigeGR4H;CemaNeigeGR4H;6;hourly;NA;GR;airGR
 CemaNeigeGR5H;CemaNeigeGR5H;7;hourly;NA;GR;airGR
 Lag;Lag;1;NA;NA;SD;airGR
 LLR;LLR;2;NA;NA;SD;airGR
+LBLR;LBLR;2;NA;NA;SD;airGR