sandbox/geoffroy/friction/fricsubsup_darcy.c
Friction in saint-venant : subcritical to super-critical test case
with Darcy
In this example, we reproduce the MacDonald benchmark[1]. We test the friction source term for a fluvial flow becoming torrential. The leading equations can be written as :
\begin{array}{cc} \partial_t h + \partial_x q = 0 \\ \partial_t q + \partial_x \left(\frac{q^2}{h}+ \frac{1}{2} g h^2 \right) = -gh (S_0 + S_f) \end{array}
S_0 is the slope and S_f is the friction term in its kinematic form.
Declarations
We call the saint venant solver and we add the Darcy friction term.
#include "grid/cartesian1D.h"
#include "saint-venant.h"
#include "saintvenant/darcy.h"
int LEVEL;
scalar e[];
double e1 = 0., e2 = 0., emax = 0.;
int ne = 0;
double pause, tmax, q0 = 2, z0, h0, tb = 1500 ;
// Analytical solution for h and dh/dx
double hex(double x){
if(x < 500)
return pow(4/G,1/3.)*(1 - 1/3.*tanh(3*(-0.5 + x/1000.)));
elsereturn pow(4/G,1/3.)*(1 - 1/6.*tanh(6*(-0.5 + x/1000.)));
}
double dhex(double x){
if(x < 500)
return -pow(4/G,1/3.)/(1000*sq(cosh(3*(-0.5 + x/1000.))));
elsereturn -pow(4/G,1/3.)/(1000*sq(cosh(6*(-0.5 + x/1000.))));
}
// Darcy friction term in kinematic formulation
double sf(double x){
return -f/(8*G)*q0*q0/pow(hex(x),3);
}
// Z and dz
double dzex(double x) {
return (q0*q0/(G*pow(hex(x),3))-1)*dhex(x)+sf(x);
}
double zex(double x, double z) {
double dx = L0/N; return z + dx/3.*(dzex(x-dx)+dzex(x-0.5*dx)+dzex(x));
}
Parameters
Definition of parameters and calling of the saint venant subroutine run().
int main()
{
= 0.042;
f =0.2;
pause= 1000.;
L0 = 0;
X0 = 9.81;
G = 2000;
tmax for( LEVEL = 5; LEVEL <= 9; LEVEL++){
= e2 = emax = 0.;
e1 = 0;
ne = 1 << LEVEL;
N run();
fprintf (stderr, "%d %g %g %g\n", N, e1/ne, sqrt(e2)/ne, emax);
}
}
Boundary condition
[left] = dirichlet(zex(0,x));
zb[left] = dirichlet(max(hex(0),0));
h[left] = dirichlet(max(hex(0)+zb[],zb[]));
eta.n[left] = dirichlet(max(q0/hex(0),0));
u
[right] = dirichlet(max(hex(1000),0));
h[right] = dirichlet(max(hex(1000)+zb[],zb[]));
eta.n[right] = dirichlet(max(q0/hex(1000),0)); u
Initial conditions
event init (i = 0)
{
= 1e-2;
DT =0;
z0foreach(){
[] = zex(x,z0);
zb=zb[];
z0.x[] = 0;
u[]=0;
h}
boundary(all);
}
Computing error
event error (i++; t<=tmax) {
foreach()
[] = (h[] - hex(x));
enorm no = normf (e);
if(t > tb){
+= no.avg;
e1 += no.rms*no.rms;
e2 ++;
neif (no.max > emax)
= no.max;
emax }
if( N == 512){
static FILE * fp1 = fopen("ErrorN512.dat","w");
fprintf(fp1,"%g \t %g \t %g \t %g \n",t,no.avg,no.rms,no.max);
}
}
Gnuplot output
We can use gnuplot to produce an animation of the water surface.
event plot ( t <= tmax; t += 15 ) {
// if( N == 64 || N == 1024 ){
printf("set title 'Manning friction fluvial ----- t= %.3g , N = %i '\n"
"p[%g:%g][-60:1] '-' u 1:($2+$4) t'free surface' w p pt 1,"
"'' u 1:4 t'topo' w l lt 4,"
"'' u 1:5 t'Analytical' w l lt -1 \n",t,N,X0,X0+L0);
foreach()
printf (" %g %g %g %g %g %g\n", x, h[], u.x[], zb[], hex(x)+zb[], t);
printf ("e\n"
"pause %.4g \n\n",pause);
// }
}
Print the water profile along the channel at final time.
event printprofile ( t = tmax-1){
char name[100];
FILE * fp;
sprintf(name,"profil-%i.dat",N);
=fopen(name,"w");
fpforeach()
fprintf(fp,"%g \t %g \t %g \t %g \t %g \t %g \t %g \n"
,x,h[],zb[],hex(x),u.x[],u.x[]*h[], h[] > dry ? u.x[]/(sqrt(G*h[])) : 0);
fclose(fp);
}
Results



References
[1] I. MacDonald, M. Baines, N. Nichols, and P. G. Samuels, “Analytic Benchmark Solutions for Open-Channel Flows,” no. November, pp. 1041–1045, 1997.