src/test/wind-driven-stvt.c

    Wind-driven lake

    This is a simple test case of a wind-driven lake where we can compare results with an analytical solution. For the bottom of the domain we impose no-slip condition (that is the default), for the top we impose a Neumann condition (see viscous friction between layers for details).

    We run the test case for three different solvers: multilayer Saint-Venant, layered hydrostatic, layered non-hydrostatic.

    #include "grid/multigrid1D.h"
    #if STVT
      #include "saint-venant.h"
    #else
      #include "layered/hydro.h"
    #if NH
      #include "layered/nh.h"
    #endif
      #include "layered/remap.h"
    #endif

    There are five parameters L, h, g, \dot{u}, \nu. Only three are independent e.g. \displaystyle a = \frac{L}{h}, \displaystyle \text{Re} = \frac{\dot{u} h^2}{\nu} = s \frac{gh^3}{\nu^2}, \displaystyle s = \frac{\dot{u} \nu}{gh} = \frac{\dot{u}^2 h}{\text{Re} g} where a is the aspect ratio, Re the Reynolds number and s the slope of the free-surface. A characteristic time scale is \displaystyle t_{\nu} = \frac{h^2}{\nu} We choose a small Reynolds number and a small slope.

    double Re = 10.;
    double s = 1./1000.;
    
    double du0;
    scalar duv[];
    
    int main()
    {
      L0 = 10.;
      X0 = -L0/2.;
      G = 9.81;
      N = 64;
      nu = sqrt(s*G/Re);
      du0 = sqrt(s*Re*G);
      dut = duv;

    We vary the number of layers.

      for (nl = 4; nl <= 32; nl *= 2)
        run();
    }

    We set the initial water level to 1 and set the surface stress.

    event init (i = 0) {
      foreach() {
    #if STVT
        h[] = 1.;
    #else
        for (scalar h in hl)
          h[] = 1./nl;
    #endif
        duv[] = du0*(1. - pow(2.*x/L0,10));
      }
    }

    We compute the error between the numerical solution and the analytical solution.

    #define uan(z)  (du0*(z)/4.*(3.*(z) - 2.))
    
    event error (t = 10./nu)
    {
      int i = 0;
      foreach() {
        if (i++ == N/2) {
          double z = zb[], emax = 0.;
    #if STVT
          int l = 0;
          for (vector u in ul) {
    	double e = fabs(u.x[] - uan (z + h[]*layer[l]/2.));
    	if (e > emax) 
    	  emax = e;
    	z += h[]*layer[l++];
          }
    #else
          vector u;
          scalar h;
          for (u,h in ul,hl) {
    	double e = fabs(u.x[] - uan (z + h[]/2.));
    	if (e > emax)
    	  emax = e;
    	z += h[];
          }
    #endif
          fprintf (stderr, "%d %g\n", nl, emax);
        }
      }
    }

    Uncomment this part if you want on-the-fly animation.

    #if 0
    event gnuplot (i += 20) {
      static FILE * fp = popen ("gnuplot 2> /dev/null", "w");
      if (i == 0)
        fprintf (fp, "set term x11\n");
      fprintf (fp,
    	   "set title 'nl = %d, t = %.2f'\n"
    	   "p [%g:%g][0:]'-' u 1:3:2 w filledcu lc 3 t '',"
    	   " '' u 1:(-1):3 t '' w filledcu lc -1", nl, t,
    	   X0, X0 + L0);
    #if STVT
      fprintf (fp, "\n");
      foreach()
        fprintf (fp, "%g %g %g\n", x, zb[] + h[], zb[]);
    #else
      int i = 4;
      for (scalar h in hl)
        fprintf (fp, ", '' u 1:%d w l lw 2 t ''", i++);
      fprintf (fp, "\n");
      foreach() {
        double H = 0.;
        for (scalar h in hl)
          H += h[];
        fprintf (fp, "%g %g %g", x, zb[] + H, zb[]);
        double z = zb[];
        for (scalar h in hl)
          fprintf (fp, " %g", z += h[]);
        fprintf (fp, "\n");
      }
    #endif  
      fprintf (fp, "e\n\n");
      //  fprintf (fp, "pause 0.05\n");
      fflush (fp);
    }
    #endif

    We save the horizontal velocity profile at the center of the domain and the two components of the velocity field for the case with 32 layers.

    event output (t = end) {
      char name[80];
      sprintf (name, "uprof-%d", nl);
      FILE * fp = fopen (name, "w");
      int i = 0;
    #if !NH && !STVT
      scalar * wl = NULL;
      for (scalar h in hl) {
        scalar w = new scalar;
        wl = list_append (wl, w);
      }
      vertical_velocity (wl);
      foreach() {
        double wm = 0.;
        scalar h, w;
        for (h,w in hl,wl) {
          double w1 = w[];
          w[] = (w1 + wm)/2.;
          wm = w1;
        }
      }
      boundary (wl);
    #endif // !NH && !STVT
      foreach() {
        if (i++ == N/2) {
    #if STVT
          int l = 0;
          double z = zb[] + h[]*layer[l]/2.;
          for (vector u in ul)
    	fprintf (fp, "%g %g\n", z, u.x[]), z += h[]*layer[l++];
    #else
          double z = zb[];
          scalar h;
          vector u;
          for (u,h in ul,hl)
    	fprintf (fp, "%g %g\n", z + h[]/2., u.x[]), z += h[];
    #endif
        }
        if (nl == 32) {
          double z = zb[];
    #if STVT
          int l = 0;
          scalar w;
          vector u;
          for (w,u in wl,ul) {
    	printf ("%g %g %g %g\n", x, z + h[]*layer[l]/2., u.x[], w[]);
    	z += layer[l++]*h[];
          }
    #else
          scalar w, h;
          vector u;
          for (h,w,u in hl,wl,ul)
    	printf ("%g %g %g %g\n", x, z + h[]/2., u.x[], w[]), z += h[];
    #endif
          printf ("\n");
        }
      }
      fclose (fp);
    #if !NH && !STVT
      delete (wl), free (wl);
    #endif
    }

    Results

    set xr [0:1]
    set xl 'z'
    set yl 'u'
    set key left top
    G = 9.81
    s = 1./1000.
    Re = 10.
    du0 = sqrt(s*Re*G)
    plot [0:1]du0*x/4.*(3.*x-2.) t 'analytical', \
              'uprof-4' pt 5 t '4 layers', \
              'uprof-8' pt 6 t '8 layers', \
              'uprof-16' pt 9 t '16 layers', \
              'uprof-32' pt 10 t '32 layers'
    Numerical and analytical velocity profiles at the center of the lake. (script)

    Numerical and analytical velocity profiles at the center of the lake. (script)

    reset
    set cbrange [1:2]
    set logscale
    set xlabel 'Number of layers'
    set ylabel 'max|e|'
    set xtics 4,2,32
    set grid
    fit a*x+b 'log' u (log($1)):(log($2)) via a,b
    plot [3:36]'log' u 1:2 pt 7 t '', \
         exp(b)*x**a t sprintf("%.2f/N^{%4.2f}", exp(b), -a) lt 1
    Convergence of the error between the numerical and analytical solution with the number of layers. (script)

    Convergence of the error between the numerical and analytical solution with the number of layers. (script)

    reset
    unset key
    set xlabel 'x'
    set ylabel 'z'
    scale = 10.
    plot [-5:5][0:1]'out' u 1:2:($3*scale):($4*scale) w vectors
    Velocity field (32 layers). (script)

    Velocity field (32 layers). (script)

    See also