sandbox/hugoj/test_windinput/linear_wave_wind_input.c

    Wave growth: from linear to breaking

    Analytical solution

    A linear surface gravity wave will decay in a viscous fluid. The rate of this decay is E(t)=E_0 e^{-4\nu k^2 t} (Lamb 1932)

    Observations

    Re=40000 - N=1024 nl=15 n’est pas convergé. - 1 mode, N=2048 nl=15 fait apparaitre des vitesses verticale très fortes … - 1 mode, N=4096 pareil Instabilité à lambda / 4 ?? Pour lambda=1, L=1, instabilité à -0.25, 0, 0.25

    • 2 modes, N=2048 ok !
    • Diminuer Re fait augmenter les instabilités ?? + message “warning: could not conserve barotropic flux”

    Cas qui fonctionne mais trop dissipatif: k=2pi L=1 ak=0.05 g=9.81 theta_H=0.6 Re=40000 N=1024 nl=15

    References

    Horace Lamb, Hydrodynamics (6th ed., 1932), Chapter XI, Article 348, “Effect of Viscosity on Water-Waves,” pp. 623–625

    et Article 349 pour une dérivation plus sérieuse

    #include "grid/multigrid1D.h"
    #include "layered/hydro.h"
    #include "layered/nh.h"
    #include "layered/remap.h"
    #include "layered/perfs.h"
    #include "bderembl/libs/netcdf_bas.h"
    
    #if STOKES
    #include "stokes.h" // link from src/test/stokes.h
    double k_ = 2.*pi, h_ = 0.5, g_ = 1.0, ak = 0.35; 
    double RE = 40000.;
    #else
    double k_ = 2.*pi, h_ = 0.5, g_ = 9.81, ak = 0.05; 
    double RE = 40000.;
    #endif
    
    #define T0  (2.*pi/sqrt(g_*k_))
    double lam, p0;
    double base_gpe=0.;
    double NT0 = 100.;
    scalar ps[], Fp[]; 
    
    
    
    int main()
    {
      L0=1.;
      origin (-L0/2.);
      periodic (right);
      N = 512;
      nl = 15; // 60
      G = g_;
      lam = 2*pi/k_*L0;
      nu = sqrt(g_*lam*lam*lam)/RE; // sqrt(g_*lam*lam*lam)
      CFL_H = 1.0;
      //max_slope = 1.; // a bit less dissipative
      theta_H = 0.55; // >0.5 or else energy increases even without forcing ? 0.51
      p0=1.; //0.001; //4*1*nu*k_*sqrt(9.81*k_)/k_;
      base_gpe=0.5*g_*h_*h_;
      //printf("%f", nu);
      run();
    }
    
    
    
    event init (i = 0)
    {
      foreach() {
        zb[] = -h_*lam;
    #if STOKES
    #warning "STOKES branch active"
        double H =  wave(x, 0) - zb[];  
    #else
        double H =  ak/k_*cos(k_*x) - zb[];
    #endif
        double z = zb[];
        foreach_layer() {
          h[] = H/nl;
          z += h[]/2.;
    #if STOKES
          u.x[] = u_x(x, z);  
          w[] = u_y(x, z);  
    #else
          u.x[] = ak/k_*sqrt(g_*k_)*exp(k_*z)*cos(k_*x); // 
          w[] = ak/k_*sqrt(g_*k_)*exp(k_*z)*sin(k_*x);  // 
    #endif
          z += h[]/2.;
        }
      }
      create_nc({zb, eta, h, u.x, w, Fp}, "out.nc");
    }
    
    // event profiles (t += T0/4.) { 
    //   foreach (serial) {
    //     double H = zb[];
    //     foreach_layer()
    //       H += h[];
    //     fprintf (stderr, "%g %g\n", x, H);
    //   }
    //   fprintf (stderr, "\n\n");
    // }
    
    #if !STOKES
    event viscous_term (i++) {
      // vertical diffusion is done in diffusion.h (u.x) and nh.h (w)
      horizontal_diffusion ({u.x, w}, nu, dt);
    }
    #endif
    
    
    #if 1
    #if FORCING
    #warning "FORCING accel branch active"
    event acceleration(i++, last){
      double detadx = 0.;
      foreach() {
        detadx = (eta[1] - eta[-1])/(2*Delta);
        ha.x[0,0,nl-1] -= hf.x[]*(p0 * detadx * sin(atan(detadx))); //   
      }
    }
    #endif
    #endif
    
    #if 0
    #if FORCING
    #warning "FORCING accel branch active"
    event acceleration(i++, last){
      double detadx = 0.;
      foreach_face(x) {
        detadx = (eta[] - eta[-1])/Delta;
        ha.x[0,0,nl-1] += hf.x[]*(p0 * detadx * sin(atan(detadx))); //   
      }
    }
    #endif
    #endif
    
    #if 0
    #if FORCING
    #warning "FORCING diffusion branch active"
    event forcing(i++, last){
      foreach(){
        double detadx = (eta[1] - eta[-1])/(2*Delta);
        ps[] = p0 * detadx;
        Fp[] = ps[]* sin(atan(detadx));
        vertical_diffusion (point, h, u.x, dt, nu,
    			                  Fp[],      // my forcing
                            u_b.x[], lambda_b.x[]); // keep the default values
      }
    }
    #endif
    #endif 
    
    event logfile (i++; t <= NT0*T0) // target: at least 300*T0
    {
      double ke = 0., gpe = 0.;
      foreach (reduction(+:ke) reduction(+:gpe)) {
        foreach_layer() {
          double norm2 = sq(w[]);
          foreach_dimension()
    	norm2 += sq(u.x[]);
          ke += norm2*h[]*dv();
        }
        gpe += sq(eta[])*dv();
      }
      printf ("%g %g %g\n", t/T0, ke/2., g_*gpe/2.);
    }
    
    
    event movie (i+=3)
    {
      static FILE * fp = popen ("gnuplot", "w");
      if (i == 0)
        fprintf (fp, "set term pngcairo font ',9' size 800,250;"
          "set size ratio -1\n");  
      fprintf (fp,
        "set output 'plot%04d.png'\n"
        "set title 't = %.2f'\n"
        "p [%g:%g][-0.1:0.15]'-' u 1:(-1):2 w filledcu lc 3 t ''",
        i/3, t/(k_/sqrt(g_*k_)), X0, X0 + L0);
      fprintf (fp, "\n");
      foreach (serial) {
        double H = 0.;
        foreach_layer()
          H += h[];
        fprintf (fp, "%g %g %g", x, zb[] + H, zb[]);
        fprintf (fp, "\n");
      }
      fprintf (fp, "e\n\n");
      fflush (fp);
      write_nc();
    }
    
    event moviemaker (t = end)
    {
      system ("rm -f movie.mp4 && "
    	  "ffmpeg -r 25 -f image2 -i plot%04d.png "
    	  "-vcodec libx264 -vf format=yuv420p -movflags +faststart "
    	  "movie.mp4 2> /dev/null && "
    	  "rm -f plot*.png");
    }
    import numpy as np
    import matplotlib.pyplot as plt
    
    g = 9.81
    L0 = 1
    ak = 0.05
    k = 2*np.pi
    lam = 2*np.pi/k*L0
    Re = 40000
    
    nu = np.sqrt(g*lam**3)/Re
    T0 = (2*np.pi/np.sqrt(g*k))
    
    def E_linwave(E0,nu,ak,k,t):
      print('\nWave decay for linear wave (theory)')
      print(f'nu={nu},ak={ak},k={k/np.pi}pi\n')
      return E0*np.exp(-4*nu*k**2*t)
    
    data = np.loadtxt("out",skiprows=1)
    data_ref = np.loadtxt('../no_forcing/out',skiprows=1)
    time = data[:,0]
    ke  = data[:,1]
    gpe = data[:,2]
    E = ke + gpe
    timeref = data_ref[:,0]
    Eref = data_ref[:,1]+data_ref[:,2]
    E0 = E[0]
    Eth = E_linwave(E0,nu,ak,k,time*T0)
    fig, ax = plt.subplots(figsize=(5, 5))
    ax.plot(timeref,Eref/Eref[0],c='k',ls='--',label='no forcing')
    ax.plot(time,2*ke/E[0],color='b', label='2*ke')
    ax.plot(time,2*gpe/E[0],color='g', label='2*gpe')
    ax.plot(time,E/E[0], color='k', label='E')
    ax.plot(time, Eth/E[0], color='r', label=r'$E(t)=E_0 e^{-4 \nu k^2 t}$')
    ax.set_xlabel("t/T0")
    ax.set_ylabel("E/E0")
    ax.legend(loc="lower left")
    plt.tight_layout()
    plt.savefig("energy.png", dpi=150)
    plt.show()
    Wave energy (script)