sandbox/cselcuk/kizner-dlmfd.c

    Vortex Ejection from a mode 3 instability with dlmfd (distributed Lagrange multipliers/Fictitious domain method)

    This page is the fictitious-domain version of Antoon’s simulation with embeded geometry. It is copy/pasted here and adapted for the fictitious domain method. 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 the fictitious-domain method and the Navier-Stokes solver (without the double-projection scheme). Furthermore, we will view our results.

    /* Physical parameters */
    # define rhoval (1.) // fluid density
    # define radi (1.) // particle radius
    # define Re 30000.
    # define tval (1./Re)
    # define MAXLEVEL 12
    # define mydt 0.04
    # define maxtime  100.
    
    /* Criteria for adaptivity */
    # define adaptive 1
    # define UxAdaptCrit (4.E-3)
    # define UyAdaptCrit (4.E-3)
    
    # include "dlmfd.h"
    # include "view.h"

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

    int main() {
      L0 = 40.;
      init_grid(64);

    Rather than choosing stress-free outer-domain boundaries, periodic boundaries are used. This markably increased the congergence properties of the iterative Multigrid strategy applied to the advection and viscous problems.

      foreach_dimension()
        periodic(left);
        /*
          Since the perturbed initialized solution is slightly inconsistent, the
          Poisson solver is tuned to be extra robust for the first ten
          timesteps.
        */
      CFL = 0.6;
      DT = mydt;
      TOLERANCE = 1E-4;
      NITERMIN = 5;
      run();
    }

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

    #define RAD (pow(sq(x-0.5*L0) + sq(y-0.5*L0), 0.5))
    #define THETA(M) (M*asin((x-0.5*L0)/RAD))
    #define RADP(P, M) ((1 + P*sin(THETA(M)))/(pow(1 + 0.5*sq(P), 0.5)))
    
    
    event init(t = 0) {
       origin (0., 0.);
      
      double a1 = 1.5 , b1 = 2.25 ;
      double P = 0.005, m = 3;
      double gamma = (sq(a1) - 1.)/(sq(b1) - sq(a1));
      refine (RAD < b1  && level < (MAXLEVEL-1));
      refine (RAD < 1.05 && RAD > 0.95  && level < MAXLEVEL);
      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-L0/2.)/(sq((x-L0/2.)) + sq((y-L0/2.)));
        u.y[] = cm[]*0.5*vr*r* (x-L0/2.)/(sq((x-L0/2.)) + sq((y-L0/2.)));
      }
      
      
      /* initial condition: particles/fictitious-domains positions */
      particle * p = particles;
     
      for (int k = 0; k < NPARTICLES; k++) {
        GeomParameter gp = {0};
        gp.center.x = L0/2; 
        gp.center.y = L0/2;
        gp.radius = radi;
        p[k].g = gp;
    
      }
    }
    
    event relax_a_little (i = 10) {
      NITERMIN = 1;
    }

    Ouput and Results

    Movies are generated that display the vorticity dynamics and the grid-cell structure.

    event movie (t += 0.4; t <= maxtime) {
      p.nodump = false;
      
      scalar omega[];
      vorticity (u, omega);
      boundary ({omega});
      dump("dump");
      view (fov = 5, quat = {0,0,0,1}, tx = -0.5*radi, ty = -0.5*radi, bg = {1,1,1}, width = 600, height = 600, samples = 1);
      
      clear();
      squares ("omega", min = -0.75, max = 0.75,
    	   map = cool_warm, linear = true);
      save ("kizner12.mp4");
      clear();
      cells();
      save("kizner_cells12.mp4");
      clear();
      view (fov = 2, quat = {0,0,0,1}, tx = -0.5*radi, ty = -0.5*radi, bg = {1,1,1}, width = 1080, height = 1080, samples = 1);
      cells();
      squares ("omega", min = -0.75, max = 0.75,
    	   map = cool_warm, linear = true);
      save ("kizner_cells_zoom.mp4");
    }

    Also there is this movie:

    A zoom

    event lastdump (t = end) {
      dump (file="dump");
      particle * p = particles;
      dump_particle(p);
      
      /* performances display/output */
      output_dlmfd_perf (dlmfd_globaltiming, i, p);
    }
    set yr [0 : 25000]
    set xlabel 'time iteration'
    set ylabel 'number of Cells or Lagrange multipliers'
    plot "dlmfd-cells" u 1:3 w l lw 2 title "Constrained cells","dlmfd-cells" u 1:2 w l lw 2 title "Lagrange multpliers", "dlmfd-cells" u 1:4 w l lw 2 title "Total cells"
    Number of constrained cells, Lagrange multipliers, total cells. (script)
    reset
    set xlabel 'time iteration'
    set ylabel 'number of iterations'
    plot "converge-uzawa" u 1:2 w l lw 2 title "dlmfd-solver"
    Number of iterations for the fictitious domain solver. (script)
    reset
    set yr [0 : 0.000012]
    set xlabel 'time iteration'
    set ylabel 'dlmfd-solver error'
    f(x) = 0.00001
    plot "converge-uzawa" u 1:3 w l lw 2 title "||u_dlmfd - u_particle||_2",f(x) w l lw 2 title "convergence-criterion"
    error ||u_dlmfd - u_particle||_2 vs time iteration (here u_particle = 0 as the cylinder is immobile) (script)

    The performances of the dlmfd-solver is stored in the “dlmfd-perf” file.

    ##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