Skip to content

Qmec is a physically based, fully nonlinear, and nonstead reach-averaged river model to provide instantaneous freshwater discharge rates in tidal rivers using water level measurements alone at two tide gauge stations (https://doi.org/10.1029/2019JC015992). This version is enhanced by the inclusion of associated uncertainties during calibration

License

GPL-3.0, GPL-3.0 licenses found

Licenses found

GPL-3.0
LICENSE
GPL-3.0
LICENSE.md
Notifications You must be signed in to change notification settings

Felipemendezrios/QmecBaM

Repository files navigation

Qmec BaM

Felipe MENDEZ (INRAE, RiverLy) Novemeber 2024

Acknowledgement

Felipe MENDEZ, Clara CHABRILLANGEAS, Benjamin RENARD, Jérôme LE COZ (INRAE, RiverLy and RECOVER). November 2024. Acknowledgement to Pascal MATTE (Enviroment Canada) and Daniel BOURGAULT (UQAR, Canada) for developing and sharing the code of Qmec,Bourgault and Matte (2022), as well as for their support and collaboration throughout this project.

Introduction

Qmec is a physically based, fully nonlinear, and nonstead reach-averaged river model to provide instantaneous freshwater discharge rates in tidal rivers using water level measurements alone at two tide gauge stations developed by Bourgault and Matte (2020).

The goal of QmecBaM is to incorporate the associated uncertainties during the calibration and simulation of discharge time series for a tidal river, achieved using Bayesian estimation. To achieve this, the package BaM! will be applied.

Installation

You can install the development version of QmecBaM from GitHub using the following command. Please note that the RBaM package developed by Renard (2017) is also required to run this package.

# Before first use, install RatingShiftHappens and RBaM packages ones and for all, following these commands: 

# devtools::install_github("Felipemendezrios/QmecBaM")
# devtools::install_github('BaM-tools/RBaM') 

library(QmecBaM)

Case Saint Lawrence in Canada

The first case study is the Saint Lawrence River, located in eastern Canada, from Bécancourt station to Saint-François station. This section was chosen because it is strongly influenced by the tide, being close to the mouth of the Gulf of Saint Lawrence, which flows into the Atlantic Ocean.

In this example, the reach concerned covers the section between Neuville and Lauzon. Prior knowledge on geometric properties is required to run the model, as shown below:

 # Prior knowledge
 priors=data.frame(
   # constant effective width of the rectangular channel
   Be=c(1500, # initial guess
        'LogNormal', # distribution
        log(1500),0.1), # parameters of the distribution 
   # River bed elevation relative to a reference system
   be=c(-14.6915,
        'Gaussian',
        -14.6915,2),
   # Leveling error
   delta=c(0,
           'Gaussian',
           0,0.02),
   # effective friction coefficient
   ne=c(0.023,
        'LogNormal',
        log(0.023),0.15),
   # Initial discharge 
   Q0=c(12500,
        'Gaussian',
        12500,10000),
   # Distance between two gauge stations
   dx=c(38000,
        'Gaussian',
        38000,250))

 # Put in object for using RBaM package
 Be=RBaM::parameter(name='Be',
                    init=as.numeric(priors$Be[1]),
                    prior.dist=priors$Be[2],
                    prior.par=as.numeric(priors$Be[c(3,4)]))

 be=RBaM::parameter(name='be',
                    init=as.numeric(priors$be[1]),
                    prior.dist=priors$be[2],
                    prior.par=as.numeric(priors$be[c(3,4)]))

 delta=RBaM::parameter(name='delta',
                       init=as.numeric(priors$delta[1]),
                       prior.dist=priors$delta[2],
                       prior.par=as.numeric(priors$delta[c(3,4)]))

 ne=RBaM::parameter(name='ne',
                    init=as.numeric(priors$ne[1]),
                    prior.dist=priors$ne[2],
                    prior.par=as.numeric(priors$ne[c(3,4)]))

 Q0=RBaM::parameter(name='Q0',
                    init=as.numeric(priors$Q0[1]),
                    prior.dist=priors$Q0[2],
                    prior.par=as.numeric(priors$Q0[c(3,4)]))

 dx=RBaM::parameter(name='dx',
                    init=as.numeric(priors$dx[1]),
                    prior.dist=priors$dx[2],
                    prior.par=as.numeric(priors$dx[c(3,4)]))

 # Chart Datum of the upstream tide gauge
 d1= -1.379
 # Chart Datum of the downstream tide gauge
 d2= -1.958
 # temporal discretization of the model in seconds
 dt_model= 60

 results_calibration=Estimation_Qmec(CalibrationData=Saint_Laurent_F2,
                                     Be_object=Be,
                                     be_object=be,
                                     delta_object=delta,
                                     ne_object=ne,
                                     Q0_object=Q0,
                                     dx_object=dx,
                                     CD1=d1,
                                     CD2=d2,
                                     dt_model=dt_model)

 # See MCMC results:
 MCMC_exploration=RBaM::tracePlot(results_calibration$MCMC)
 gridExtra::grid.arrange(grobs=MCMC_exploration,ncol=3)

 # See scatterplot
 psych::pairs.panels(results_calibration$MCMC[,-c(length(results_calibration$MCMC)-1,
                     length(results_calibration$MCMC))],
                     smooth=FALSE,
                     lm=T,
                     scale = T,
                     method = "pearson", # correlation method
                     hist.col = "#00AFBB",
                     cor=T,
                     ci=TRUE,
                     density = TRUE,  # show density plots
                     ellipses = TRUE) # show correlation ellipses

In the context of Bayesian estimation, it is necessary to check the prior and posterior distribution to ensure that the estimate is correct or diagnostic of the data or model.

Plot_prior_posterior(DF_prior_posterior=results_calibration$prior_vs_posterior)

The model parameters have been estimated so far. Let’s simulate the discharge time series.

simulation_QMEC=Prediction_Q_Qmec(CalibrationData=Saint_Laurent_F2,
             Model_object=results_calibration$Model_object)

Let’s plot the simulations with the associated uncertainties and the observations:

Q_plot=plot_Q_sim_Qmec(Q_observed=simulation_QMEC$Data_obs_plot,
                       Q_simulated=simulation_QMEC$Qsim)

Q_plot

# Zoom:
library(ggplot2)

Q_plot+
  coord_cartesian(x=c(min(Saint_Laurent_F2$date[which(Saint_Laurent_F2$Q!=-9999)]),
                                    max(Saint_Laurent_F2$date[which(Saint_Laurent_F2$Q!=-9999)])))

Finally, it is also possible to plot the components of the 1D shallow water equation (pressure gradient, bottom friction and advection) to understand tidal dynamics:

SW_plot=plot_shallow_water(pressure_SW=simulation_QMEC$pressure,
                   friction_SW=simulation_QMEC$friction,
                   advection_SW=simulation_QMEC$advection)
# Total uncertainty:
SW_plot$TotalU

# MaxPost:
SW_plot$MaxPost

# combine input and output data
input_stage_plot=ggplot(Saint_Laurent_F2,aes(x=date))+
  geom_line(aes(y=h1,col='Upstream'))+
  geom_line(aes(y=h2,col='Downstream'))+
  labs(x='Time',
                y='Stage [m]',
                col='Gauge station')+
  theme_bw()

library(patchwork)

input_stage_plot+
  Q_plot+
  SW_plot$MaxPost+
  plot_layout(ncol =   1,
              guides = 'collect',
              axis_titles = "collect")

Case Lower Seine in France

A second case study is proposed to test the tool and assess its applicability to other tidal rivers.

The Lower Seine is located between the Poses dam and the mouth of the Seine, where it flows into the English Channel. It lies within the Seine-Normandy basin in the Normandy region.

It was decided to test the tool on the section extending from the gauge station at Oissel upstream to Petite-Couronne downstream. The prior knowledge is specified here:

 # Prior knowledge
 priors_LS=data.frame(
   # constant effective width of the rectangular channel
   Be=c(150, # initial guess
        'LogNormal', # distribution
        log(150),0.3), # parameters of the distribution 
   # River bed elevation relative to a reference system
   be=c(-5,
        'Gaussian',
        -5,1),
   # Leveling error
   delta=c(0,
           'Gaussian',
           0,0.02),
   # effective friction coefficient
   ne=c(0.025,
        'LogNormal',
        log(0.025),0.15),
   # Initial discharge 
   Q0=c(410,
        'Gaussian',
        410,100),
   # Distance between two gauge stations
   dx=c(23747,
        'Gaussian',
        23747,200))

 # Put in object for using RBaM package
 Be_LS=RBaM::parameter(name='Be',
                    init=as.numeric(priors_LS$Be[1]),
                    prior.dist=priors_LS$Be[2],
                    prior.par=as.numeric(priors_LS$Be[c(3,4)]))

 be_LS=RBaM::parameter(name='be',
                    init=as.numeric(priors_LS$be[1]),
                    prior.dist=priors_LS$be[2],
                    prior.par=as.numeric(priors_LS$be[c(3,4)]))

 delta_LS=RBaM::parameter(name='delta',
                       init=as.numeric(priors_LS$delta[1]),
                       prior.dist=priors_LS$delta[2],
                       prior.par=as.numeric(priors_LS$delta[c(3,4)]))

 ne_LS=RBaM::parameter(name='ne',
                    init=as.numeric(priors_LS$ne[1]),
                    prior.dist=priors_LS$ne[2],
                    prior.par=as.numeric(priors_LS$ne[c(3,4)]))

 Q0_LS=RBaM::parameter(name='Q0',
                    init=as.numeric(priors_LS$Q0[1]),
                    prior.dist=priors_LS$Q0[2],
                    prior.par=as.numeric(priors_LS$Q0[c(3,4)]))

 dx_LS=RBaM::parameter(name='dx',
                    init=as.numeric(priors_LS$dx[1]),
                    prior.dist=priors_LS$dx[2],
                    prior.par=as.numeric(priors_LS$dx[c(3,4)]))

 # Chart Datum of the upstream tide gauge
 d1_LS= 0
 # Chart Datum of the downstream tide gauge
 d2_LS= 0
 # temporal discretization of the model in seconds
 dt_model_LS= 60

 results_calibration_LS=Estimation_Qmec(CalibrationData=Lower_Seine_Rouen,
                                     Be_object=Be_LS,
                                     be_object=be_LS,
                                     delta_object=delta_LS,
                                     ne_object=ne_LS,
                                     Q0_object=Q0_LS,
                                     dx_object=dx_LS,
                                     CD1=d1_LS,
                                     CD2=d2_LS,
                                     dt_model=dt_model_LS)

 # See MCMC results:
 MCMC_exploration_LS=RBaM::tracePlot(results_calibration_LS$MCMC)
 gridExtra::grid.arrange(grobs=MCMC_exploration_LS,ncol=3)

 # See scatterplot
 psych::pairs.panels(results_calibration_LS$MCMC[,-c(length(results_calibration_LS$MCMC)-1,
                     length(results_calibration_LS$MCMC))],
                     smooth=FALSE,
                     lm=T,
                     scale = T,
                     method = "pearson", # correlation method
                     hist.col = "#00AFBB",
                     cor=T,
                     ci=TRUE,
                     density = TRUE,  # show density plots
                     ellipses = TRUE) # show correlation ellipses

Here a plot indicating the prior and posterior distribution:

Plot_prior_posterior(DF_prior_posterior=results_calibration_LS$prior_vs_posterior)

Here the discharge simulation:

simulation_QMEC_LS=Prediction_Q_Qmec(CalibrationData=Lower_Seine_Rouen,
                                     Model_object=results_calibration_LS$Model_object)

Let’s plot the simulations with the associated uncertainties and the observations:

Q_plot_LS=plot_Q_sim_Qmec(Q_observed=simulation_QMEC_LS$Data_obs_plot,
                          Q_simulated=simulation_QMEC_LS$Qsim)

Q_plot_LS

# Zoom:
Q_plot_LS+
  coord_cartesian(x=c(min(Lower_Seine_Rouen$date[which(Lower_Seine_Rouen$Q!=-9999)]),
                                    max(Lower_Seine_Rouen$date[which(Lower_Seine_Rouen$Q!=-9999)])))

Finally, it is also possible to plot the components of the 1D shallow water equation:

SW_plot_LS=plot_shallow_water(pressure_SW=simulation_QMEC_LS$pressure,
                              friction_SW=simulation_QMEC_LS$friction,
                              advection_SW=simulation_QMEC_LS$advection)
# Total uncertainty:
SW_plot_LS$TotalU

# MaxPost:
SW_plot_LS$MaxPost

# combine input and output data
input_stage_plot_LS=ggplot(Lower_Seine_Rouen,aes(x=date))+
  geom_line(aes(y=h1,col='Upstream'))+
  geom_line(aes(y=h2,col='Downstream'))+
  labs(x='Time',
       y='Stage [m]',
       col='Gauge station')+
  theme_bw()

input_stage_plot_LS+
  Q_plot_LS+
  SW_plot_LS$MaxPost+
  plot_layout(ncol =   1,
              guides = 'collect',
              axis_titles = "collect")

Bourgault, Daniel, and Pascal Matte. 2020. “A Physically Based Method for Real-Time Monitoring of Tidal River Discharges From Water Level Observations, With an Application to the St. Lawrence River.” Journal of Geophysical Research: Oceans 125 (5): e2019JC015992. https://doi.org/10.1029/2019JC015992.

———. 2022. “Qmec : A Matlab Code to Compute Tidal River Discharge from Water Level.” Code Ocean. https://doi.org/10.24433/CO.7299598.V2.

Renard, Benjamin. 2017. “BaM ! (Bayesian Modeling): Un code de calcul pour l’estimation d’un modèle quelconque et son utilisation en prédiction.” {Report}. irstea.

About

Qmec is a physically based, fully nonlinear, and nonstead reach-averaged river model to provide instantaneous freshwater discharge rates in tidal rivers using water level measurements alone at two tide gauge stations (https://doi.org/10.1029/2019JC015992). This version is enhanced by the inclusion of associated uncertainties during calibration

Resources

License

GPL-3.0, GPL-3.0 licenses found

Licenses found

GPL-3.0
LICENSE
GPL-3.0
LICENSE.md

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published