sandbox/nlemoine/SWE/diffwave/fullsaintvenant.c
#include "terrain.h"
#include "saint-venant.h"
#include "utils.h"
#include "output.h"
#include "nlemoine/SWE/manning-tilt.h"
#define ETABF 10.6
#define n_ch 0.03
#define n_fp 0.06
#define sec_per_day 86400.
#define M_PI acos(-1.0)
#define ETAE 1e-2 // error on water depth (1 cm)
#define HE 1e-2 // error on water depth (1 cm)
#define UE 1e-2 // 0.01 m/s
#define LEVEL 7
#define MINLEVEL 5
double stage_hydrograph (double tt)
{
return( ETABF-2.0*cos(2.0*M_PI*tt/sec_per_day) );
}
double segment_Q (coord segment[2], scalar h, vector u) // vient de "layered/hydro.h"
{
coord m = {segment[0].y - segment[1].y, segment[1].x - segment[0].x};
normalize (&m);
double tot = 0.;
foreach_segment (segment, p) {
double dl = 0.;
foreach_dimension() {
double dp = (p[1].x - p[0].x)*Delta/Delta_x*(fm.y[] + fm.y[0,1])/2.;
dl += sq(dp);
}
dl = sqrt (dl);
for (int i = 0; i < 2; i++) {
coord a = p[i];
tot += dl/2.*
interpolate_linear (point, (struct _interpolate)
{h, a.x, a.y, 0.})*
(m.x*interpolate_linear (point, (struct _interpolate)
{u.x, a.x, a.y, 0.}) +
m.y*interpolate_linear (point, (struct _interpolate)
{u.y, a.x, a.y, 0.}));
}
}
// reduction
#if _MPI
MPI_Allreduce (MPI_IN_PLACE, &tot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
#endif
return tot;
}
double segment_eta (coord segment[2], scalar h, scalar eta)
{
coord m = {segment[0].y - segment[1].y, segment[1].x - segment[0].x};
normalize (&m);
double tot = 0., wtot = 0.;
foreach_segment (segment, p) {
double dl = 0.;
foreach_dimension() {
double dp = (p[1].x - p[0].x)*Delta/Delta_x*(fm.y[] + fm.y[0,1])/2.;
dl += sq(dp);
}
dl = sqrt (dl);
for (int i = 0; i < 2; i++) {
coord a = p[i];
tot += dl/2.*
interpolate_linear (point, (struct _interpolate)
{h, a.x, a.y, 0.})*
interpolate_linear (point, (struct _interpolate)
{eta, a.x, a.y, 0.}) ;
wtot += dl/2.* interpolate_linear (point, (struct _interpolate)
{h, a.x, a.y, 0.});
}
}
// reduction
#if _MPI
MPI_Allreduce (MPI_IN_PLACE, &tot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
MPI_Allreduce (MPI_IN_PLACE, &wtot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
#endif
return (tot/wtot);
}
FILE * fpcontrol;
int main (int argc, char * argv[])
{
size (2048.);
origin (-424.,-2332.);
init_grid (1 << LEVEL);
// Get .kdt file
system("wget https://dropsu.sorbonne-universite.fr/s/sT5GkqPqzsaMYab/download");
system("mv download garonne_local.kdt");
// Get .pts file
system("wget https://dropsu.sorbonne-universite.fr/s/5TWiFJaAXGKcb6L/download");
system("mv download garonne_local.pts");
// Get .sum file
system("wget https://dropsu.sorbonne-universite.fr/s/sz5qF6fc7MwkPzz/download");
system("mv download garonne_local.sum");
G = 9.81;
tilt.x = 0.;
tilt.y = 1.103e-3;
run();
if(pid()==0.)
fclose(fpcontrol);
}
event initialize (i=0)
{
terrain(zb,"garonne_local", NULL);
scalar zmin = zb.dmin;
output_ppm (zb, min = 3, max = 20, file = "topo6.png",
n = 512, linear = true);
foreach()
{
double etaini = stage_hydrograph(0.);
eta[] = zb[]>etaini ? zb[] : etaini;
h[] = eta[] > zb[] ? eta[]-zb[] : 0.;
eta[] = zb[] + h[];
u.x[] = 0.;
u.y[] = 0.;
double zzmin = zmin[]<nodata ? zmin[] : zb[];
nmanning[] = zzmin<ETABF ? n_ch : n_fp ;
}
if(pid()==0)
fpcontrol = fopen("outlet_info.txt","w");
}
event update_BC(i++)
{
// Conditions aux limites
u.n[top] = neumann(0.);
// u.t[top] = dirichlet(0.);
u.t[top] = neumann(0.);
h[top] = neumann(0.);
zb[top] = neumann(0.);
eta[top] = neumann(0.);
nmanning[top] = neumann(0.);
u.n[bottom] = neumann(0.);
u.t[bottom] = dirichlet(0.);
zb[bottom] = neumann(0.);
nmanning[bottom] = neumann(0.);
foreach_boundary(bottom)
{
eta[] = fmax(zb[],stage_hydrograph(t));
h[] = eta[]-zb[];
}
eta[bottom] = neumann(0.);
h[bottom] = neumann(0.);
boundary(all);
}
scalar l[];
event snapshot (t+=300. ; t<=86400.)
{
scalar m[], etam[];
foreach() {
m[] = eta[]*(h[] > dry) - zb[];
etam[] = h[] < dry ? 0. : (zb[] > 0. ? eta[] - zb[] : eta[]);
}
output_ppm (h, mask = m, min = 0, max = 10,
n = 2048, linear = true, file = "h.mp4");
}
event info_conservation (t+=30. ; t<=86400.)
{
coord Section[2];
Section[0] = (coord) { X0 , Y0+L0-L0/N };
Section[1] = (coord) { X0+L0 , Y0+L0-L0/N };
// "Measure" discharge at top (outlet) section
double Q = segment_Q (Section,h,u);
// "Measure" mean elevation at top (outlet) section
double etam = segment_eta (Section,h,eta);
// Total water volume in domain
double Vol = 0.;
foreach()
Vol += h[] * Delta * Delta ;
if(pid()==0){
fprintf(fpcontrol,"%g %g %g %g\n",t/3600.,Q,etam,Vol);
fflush(fpcontrol);
}
}
// Adaptivity
scalar absu[];
int adapt() {
#if TREE
scalar eta[];
foreach()
eta[] = h[] > dry ? h[] + zb[] : 0;
boundary ({eta});
foreach()
absu[]= h[] > dry ? sqrt(u.y[]*u.y[]+u.x[]*u.x[]) : 0.;
astats s = adapt_wavelet ({h,eta,absu}, (double[]){HE,ETAE,UE},
LEVEL, MINLEVEL);
scalar zmin = zb.dmin;
foreach(){
double zzmin = zmin[]<nodata ? zmin[] : zb[];
nmanning[] = zzmin<ETABF ? n_ch : n_fp;
l[] = level;
}
boundary(all);
// fprintf (ferr, "# refined %d cells, coarsened %d cells\n", s.nf, s.nc);
return s.nf;
#else // Cartesian
return 0;
#endif
}
event do_adapt (i++) adapt();
Results
Simulated water depth (flow direction is from bottom to top)
outlet_info.txt