sandbox/Antoonvh/kizner2.c

    Vortex Ejection from a mode 3 instability

    According to Kizner et al. (2013), a flow around a no-slip cylinder with radius R maybe unstable and eject three dipolar vortex pairs. We study the flow using embedded boundaries and the Navier-Stokes solver. Furthermore, we will view our results.

    #include "embed.h"
    #include "navier-stokes/centered.h"
    #include "view.h"

    The maximum resolution is set to \Delta_{min}=R/100. This allows to run on the sandbox server.

    int maxlevel = 12;
    double Re = 30000., ue = 0.003;
    face vector muc[];
    
    int main(){
      init_grid(64);
      L0 = 40;
      mu = muc;
      X0 = Y0 = -L0/2;
      run();
    }
    
    event properties (i++){
      foreach_face()
        muc.x[] = fm.x[]/Re;
      boundary ((scalar*){muc});
    }

    The cylinder is defined and the flow field is initialized c.f. Kizner et al. with an m=3 perturbation.

    #define RAD (pow(sq(x) + sq(y), 0.5))
    #define THETA(M) (M*asin(x/RAD))
    #define RADP(P, M) ((1 + P*sin(THETA(M)))/(pow(1 + 0.5*sq(P), 0.5)))
    double a1 = 1.5, b1 = 2.25;
    double P = 0.005, m = 3;
    
    event init (t = 0){
      double gamma = (sq(a1) - 1.)/(sq(b1) - sq(a1));
      refine (RAD < b1  && level < (maxlevel - 1));
      refine (RAD < 1.05 && RAD > 0.95  && level < maxlevel);
      vertex scalar phi[];
      foreach_vertex()
        phi[] = RAD - 1;
      fractions (phi, cs, fs);
      foreach(){
        double r = RAD;
        double r1 = RADP(P,m)*r;
        double vr;
        if (r1 > 0.9 && r1 < a1)
          vr = r1 - 1./r1;
        else if (r1 >= a1 && r1 <= b1)
          vr = -gamma*r1 + ((1 + gamma)*sq(a1) - 1.)/r1;
        else // (0.9 > r || r > b)
          vr = 0;
        u.x[] = cm[]*0.5*vr*r*-y/(sq(x) + sq(y));
        u.y[] = cm[]*0.5*vr*r* x/(sq(x) + sq(y));
      }

    The boundary conditions on the embedded boundary are set:

      u.t[embed] = dirichlet (0.);
      u.n[embed] = dirichlet (0.);
      boundary (all);
    }

    The grid is adaptedively refined and coarsened to properly represent the boundary and the evolution of the flow field. We set \zeta_{u,v}\approx U_{max}/150.

    event adapt (i++)
      adapt_wavelet ({cs, u.x, u.y}, (double[]){0.01, ue, ue}, maxlevel);

    Output

    Movies are generated displaying the vorticity field and the adaptive-grid-cell structure.

    event movie (t += 0.5){
      scalar omega[];
      vorticity (u, omega);
      boundary ({omega});
      view (fov = 8, width = 600, height = 600);
      clear();
      draw_vof ("cs", filled = -1, fc = {1., 1., 1.});
      squares ("omega", min = -0.75, max = 0.75,
    	   map = cool_warm, linear = true);
      draw_vof ("cs", "fs", lw = 2);
      save ("kizner.mp4");
      clear();
      view (fov = 5);
      cells();
      save ("kizner_cells.mp4");
      clear();
      view (fov = 2, width = 1080, height = 1080);
      draw_vof ("cs", filled = -1, fc = {0.6, 0.6, 0.6});
      squares ("omega", min = -0.75, max = 0.75,
    	   map = cool_warm);
      cells();
      save ("kizner_cells_zoom.mp4");
    }

    Also there is this movie:

    A zoom

    We log some solver data:

    event logger (t += 0.1){
      fprintf (stderr, "%d %g %d %d %d %g %g\n",
    	   i, t, mgp.i, mgu.i, mgpf.i, DT, dt);
      int cn = 0;
      foreach(reduction(+:cn))
        cn++;
      if (pid() == 0){
        static FILE * fp = fopen ("data", "w");
        fprintf (fp, "%g\t%d\t%d\t%g\t%g\n", t, i, cn, dt, DT);
        fflush (fp);
      }
    }

    Including the number of grid cells:

    set yr [0 : 25000]
    set xlabel 'time'
    set ylabel 'Cells'
    set key off
    plot 'data' u 1:3 w l lw 2
    These numbers may be compared against the millions of cells that Kizner et al. (2013) employed. (script)

    These numbers may be compared against the millions of cells that Kizner et al. (2013) employed. (script)

    event the_last_event (t = 100);

    Flow direction partitioning

    We can study the radially-averaged absolute velocity in the azimutal and radial direction as a function of time and the distance from the centre. Therefore, we render movies of the radial profiles using profile6.h, gnuplot and ffmpeg.

    A more quantative perspective on the instability. Mind the logaritmic vertical axis

    #include "profile6.h"
    FILE * gnuplotPipe;
    event init (t = 0){
      gnuplotPipe = popen ("gnuplot", "w");
      fprintf(gnuplotPipe,
    	  "set term pngcairo\n"
    	  "set xr [1 : 6]\n"
    	  "set yr [0.001 : 1]\n"
    	  "set logscale y\n"
    	  "set key top right\n"
    	  "set grid\n"
    	  "set xlabel 'r/R'\n"
    	  "set ylabel 'E'\n"
    	  "set size ratio 0.5\n");
    }
    
    int frame = 0;
    event profs(t += 0.5){
      scalar ur[], ua[] ,* list;
      list = {ur, ua};
      foreach(){
        double r = sqrt(sq(x) + sq(y));
        ur[] = fabs(u.x[]*x/r + u.y[]*y/r);
        ua[] = fabs((u.y[]*x/r) - (u.x[]*y/r));
      }
      profile (list, sqrt(sq(x) + sq(y)), "prof.dat"); 
      fprintf (gnuplotPipe, "set output 'plot%d.png'\n", frame);
      fprintf (gnuplotPipe, "set title 't = %d' font ',25'\n",
    	   (int)(t + 0.9));
      fprintf (gnuplotPipe, "plot 'prof.dat' u 1:2 w l lw 5 lt rgb'#11BB11' t 'Radial',"
    	   "'prof.dat' u 1:3 w l lw 5 lt rgb '#BB11BB' t 'Azimutal'\n");
      fflush (gnuplotPipe);
      frame++;
    }
    
    event stop (t = end){
      system("ffmpeg -r 25 -f image2 -i plot%d.png -c:v libx264 -vf format=yuv420p -y mov.mp4 && "
    	 "rm -f plot*");
      return 1;
    }

    Reference

    Kizner, Z., Makarov, V., Kamp, L., & Van Heijst, G. (2013). Instabilities of the flow around a cylinder and emission of vortex dipoles. Journal of Fluid Mechanics, 730, 419-441. doi:10.1017/jfm.2013.345