sandbox/Antoonvh/ring4.c

    Two opposing Gaussian vortex rings

    Two Gaussian vortex rings in a triply-periodic domain.

    Volumetric rendering of the negative \lambda_2 field (via surfdrive)

    #include "grid/octree.h"
    #include "nsf4t.h"
    scalar * tracers = NULL;
    #include "lambda2.h"
    #include "view.h"
    #include "filaments.h"
    #include "bwatch.h"
    
    #define R      (sqrt(sq(x) + sq(y)))
    #define radi(zp)   (R <= 0.01 ? major_rt				\
    		    : (sqrt(sq(x - major_rt*(x/R)) +			\
    			    sq(y - major_rt*(y/R)) + sq(z - zp))))
    
    double ue = 5e-3;
    int maxlevel = 9;
    int segs = 654;
    double major_rt = 3.0; // Ring' major radius (minor = 1)
    double d1 = 10;    // Initial distance
    double muv = 1./3000.;   // Fluid's viscosity
    
    double amp = 0.1;
    int ampn = 7;
    
    int main(int argc, char ** argv) {
      if (argc > 1)
        ue = atof (argv[1]);
      if (argc > 2)
        maxlevel = atoi (argv[2]);
      if (argc > 3)
        segs = atoi (argv[3]);
      if (argc > 4)
         muv = atof (argv[4]);
      if (pid() == 0)
        printf ("# ue = %g, ilev = %d, segs = %d, Re = %g \n",
    	    ue, maxlevel, segs, 1./muv);
      foreach_dimension()
        periodic(left);
      L0 = 40*major_rt;
      origin (-L0/2 + pi, -L0/2 + exp(1), -L0/2 - sqrt(2));
      const scalar muc[] = muv;
      nu = muc;
      run();
    }
    
    coord ring1 (double t) {
      coord C;
      C.x = major_rt*cos(t);
      C.y = major_rt*sin(t);
      C.z = d1 + amp*cos(ampn*t); ;
      return C;
    }
    
    coord ring2 (double t) {
      coord C;
      C.x =  major_rt*cos(t);
      C.y = -major_rt*sin(t);
      C.z = -d1 + amp*sin(ampn*t);
      return C;
    }
    
    event init (t = 0) {
      refine ((radi(-d1) < 12 || radi(d1) < 12) && level < maxlevel - 2);
      refine ((radi(-d1) < 6  || radi(d1) < 6)  && level < maxlevel - 1);
      refine ((radi(-d1) < 3  || radi(d1) < 3)  && level < maxlevel);
     vector A[], omg[], omg2[];
     TOLERANCE = 1e-5;
     get_vor_vector (omg,  ring1, 0, 2*pi, segs, Lamb_Oseen);
     get_vor_vector (omg2, ring2, 0, 2*pi, segs, Lamb_Oseen);
     foreach_dimension()
       A.x.prolongation = refine_4th;
     foreach() {
       foreach_dimension() {
         A.x[] = 0.;
         omg.x[] += omg2.x[];
       }
     }
     foreach_dimension() {
       stats o = statsf (omg.x);
       foreach() 
         omg.x[] -= o.sum/o.volume;
     }
     boundary ((scalar*){A});
     foreach_dimension()
       poisson (A.x, omg.x);
     vector uc[];
     foreach_dimension()
       uc.x.prolongation = refine_4th;
     foreach() { 
       foreach_dimension() {
         uc.x[] = (8.*(A.z[0,1] - A.z[0,-1]) + A.z[0,-2] - A.z[0,2] -
    	       8.*(A.y[0,0,1] - A.y[0,0,-1]) - A.y[0,0,-2] + A.y[0,0,2])/(12*Delta);
       }
     }
     boundary ((scalar*){uc});
     vector_to_face (uc);
     project (u, p);
    }
    
    event dumping (t = {5, 100, 200, 300, 350, 375, 400, 450, 500}) {
      vector uc[];
      face_to_vector (uc);
      char fname[99];
      sprintf (fname, "dump%g", t);
      dump (fname, (scalar*){uc});
    }
    
    event logger (i += 5) {
      double ke2 = 0., vd2 = 0.;
      double ke4 = 0., vd4 = 0.;
      vector uv[];
      scalar dissv[], Ev[];
      face_to_vector(uv);
      foreach(reduction (+:ke2) reduction (+:vd2)) {
        foreach_dimension() {
          ke2 += dv()*sq(uv.x[]);
          vd2 += dv()*(sq(uv.x[1]     - uv.x[-1]) +
    		   sq(uv.x[0,1]   - uv.x[0,-1]) +
    		   sq(uv.x[0,0,1] - uv.x[0,0,-1]))/sq(2.*Delta);
        }
      }
      foreach_dimension() {
        uv.x.prolongation = refine_vert5;
        uv.x.restriction = restriction_vert;
      }
      dissv.prolongation = refine_vert5;
      dissv.restriction = restriction_vert;
      Ev.prolongation = refine_vert5;
      Ev.restriction = restriction_vert;
      foreach() {
        foreach_dimension()
          uv.x[] = FACE_TO_VERTEX_4 (u.x);
      }
      boundary ((scalar*){uv});
      foreach() {
        Ev[] = dissv[] = 0;
        foreach_dimension() {
          Ev[] += sq(u.x[]);
          dissv[] += (sq(8*(u.x[1] - u.x[-1]) + u.x[-2] - u.x[2]) +
    		 sq(8*(u.x[0,1] - u.x[0,-1]) + u.x[0,-2] - u.x[0,2]) +
    		 sq(8*(u.x[0,0,1] - u.x[0,0,-1]) + u.x[0,0,-2] - u.x[0,0,2]))/sq(12*Delta);
        }
      }
      boundary ({dissv, Ev});
      foreach(reduction (+:ke4) reduction (+:vd4)) {
        coord cc = {x, y , z};
        foreach_child() {
          coord ccc = {0};
          foreach_dimension()
    	ccc.x = cc.x + child.x*Delta/sqrt(3);
          ke4 += dv()*interpolate_vertex_4 (Ev,    ccc.x, ccc.y, ccc.z);
          vd4 += dv()*interpolate_vertex_4 (dissv, ccc.x, ccc.y, ccc.z);
        }
      }
      ke2 /= 2.;
      ke4 /= 2.;
      vd2 *= muv;
      vd4 *= muv;
      fprintf (stderr, "%d %g %d %d %d %d %ld %d %g %g %g %g\n",
    	   i, t, mgp.i, mgp.nrelax, mgp2.i, mgp2.nrelax,
    	   grid->tn, grid->maxdepth, ke2, vd2, ke4, vd4);
    }
    
    event adapt (i++) 
      adapt_flow (ue, 99, 1);
    
    event mov (i += 5) {
      scalar l2[];
      vector uc[];
      face_to_vector (uc);
      lambda2 (uc, l2);
      view (fov = 12, phi = 0.5, theta = 0.4);
      isosurface ("l2", -0.001);
      cells (n = {0,1,0});
      char str[99];
      sprintf (str,"t = %3.3g", t);
      draw_string (str, size = 25, pos = 2);
      save ("l2.mp4");
    }
    
    #if BWATCH
    event movb (t += 1) {
      scalar l2[];
      vector uc[];
      face_to_vector (uc);
      lambda2 (uc, l2);
      foreach()
        l2[] = l2[] > 0 ? 0 : -l2[];
      boundary ({l2});
      static FILE * fp = popen ("ppm2mp4 l2b.mp4", "w");
      watch (O = {30, 30., 100} ,
    	 fov = 55, nx = 900, ny = 900); 
      volume (l2, cols = true, sc = 0.005, mval = 0.001,
    	  min = -0.1, max = 0.1, shading = 1);
      store (fp);
      plain();
    }
    #endif
    
    event stop (t = 1000) {
      return 1;
    }