sandbox/popinet/collapse.c

    Collapse of a bubble

    A movie of the gradient of density is here. Higher-resolution (LEVEL = 11) movies are here.

    ////////////////////////////////////////////////////////////
    
    #include "all-mach.h"
    #include "vof.h"
    
    scalar f[], rhov[], rho1[], rho2[], * interfaces = {f};
    
    face vector alphav[];
    
    scalar rhoc2v[];
    
    double CFLacous = 0.5, rhomin = 1e-6;
    
    event defaults (i = 0) {
      alpha = alphav;
      rho = rhov;
      rhoc2 = rhoc2v;
      
      foreach()
        rho1[] = rho2[] = f[] = 1.;
      boundary ({rho1,rho2,f});
    }
    
    static scalar * interfaces1 = NULL;
    
    event vof (i++) {
      vector q1 = q, q2[];
      foreach()
        foreach_dimension() {
          double u = q.x[]/rho[];
          q1.x[] = rho1[]*u;
          q2.x[] = rho2[]*u;
        }
      boundary ((scalar *){q1,q2});
      theta = 1.; // strict minmod limiter
      foreach_dimension() {
        q2.x.inverse = true;
        q1.x.gradient = q2.x.gradient = minmod2;
      }
      rho2.inverse = true;
      rho1.gradient = rho2.gradient = minmod2;
      f.tracers = {rho1,rho2,q1,q2};
      vof_advection ({f}, i);
      foreach() {
        foreach_dimension()
          q.x[] = q1.x[] + q2.x[];
        if (rho1[] < rhomin*f[])
          rho1[] = rhomin*f[];
        if (rho2[] < rhomin*(1. - f[]))
          rho2[] = rhomin*(1. - f[]);
      }
      boundary ((scalar *){q,rho1,rho2});
      interfaces1 = interfaces, interfaces = NULL;
    }
    
    event tracer_advection (i++) {
      interfaces = interfaces1;
    }
    
    double pstate (double rho, double rhoref, double pref,
    	       double B, double gamma) {
      return pref*((1. + B)*pow(rho/rhoref, gamma) - B);
    }
    
    double cstate (double rho, double rhoref, double pref,
    	       double B, double gamma) {
      return (1. + B)*pref/rhoref*gamma*pow(rho/rhoref, gamma - 1.);
    }
    
    event stability (i++) {
      foreach() {
        double dt = f[] > 0.5 ?
          Delta/sqrt(cstate (rho1[]/f[], 1., 1., 3000., 4.)) :
          Delta/sqrt(cstate (rho2[]/(1. - f[]), 0.001, 1., 0., 1.4));
        dt *= CFLacous;
        if (dt < dtmax)
          dtmax = dt;
      }
    }
    
    event properties (i++) {
      foreach() {
        rhov[] = rho1[] + rho2[];
        if (f[] > 0.5) {
          double r = rho1[]/f[];
          ps[] = pstate (r, 1., 1., 3000., 4.);
          rhoc2v[] = rhov[]*cstate (r, 1., 1., 3000., 4.);
        }
        else {
          double r = rho2[]/(1. - f[]);
          ps[] = pstate (r, 0.001, 1., 0., 1.4);
          rhoc2v[] = rhov[]*cstate (r, 0.001, 1., 0., 1.4);
        }
      }
      boundary ({rhov});
      
      foreach_face()
        alphav.x[] = 2./(rho[] + rho[-1]);
    }
    
    ////////////////////////////////////////////////////////////
    
    #include "tension.h"
    
    #define LEVEL 7
    
    int main() {
      X0 = Y0 = -L0/2.;
      f.sigma = 1.;
      run();
    }
    
    event init (i = 0) {
      if (!restore (file = "dump"))
        do {
          fraction (f, - (sq(0.25) - sq(x) - sq(y + 0.2)));
          foreach() {
    	rho1[] = f[]*1.15;
    	rho2[] = (1. - f[])/1000.;
    	rhov[] = rho1[] + rho2[];
          }
          boundary ({rho1,rho2,rhov});
        } while (adapt_wavelet ({f,rho}, (double[]){5e-3,5e-4}, LEVEL).nf);
    }
    
    event logfile (i++) {
      stats s1 = statsf(rho1), s2 = statsf(rho2);
      scalar rhot[];
      foreach()
        rhot[] = rho1[] + rho2[];
      stats st = statsf(rhot);
      if (i == 0)
        fprintf (stderr,"t f.sum s1.min s1.sum s1.max "
    	     "s2.min s2.sum s2.max st.min st.sum st.max\n");
      fprintf (stderr, "%g %.12f %.12f %.12f %.12f %.12f"
    	   " %.12f %.12f %.12f %.12f %.12f\n",
    	   t, statsf(f).sum,
    	   s1.min, s1.sum, s1.max,
    	   s2.min, s2.sum, s2.max,
    	   st.min, st.sum, st.max);
    }
    
    #if 1
    event gfsview (i += 10)
    {
      static FILE * fp = popen ("gfsview2D -s collapse.gfv", "w");
      output_gfs (fp, t = t);
    }
    #endif
    
    #if 0
    event snapshot (i = 3184) {
      dump (file = "dump");
    }
    
    event snapshots (i++) {
      char name[80];
      sprintf (name, "snapshot-%d.gfs", i);
      output_gfs (file = name);
    }
    #endif
    
    event movies (t += 5e-5; t <= 0.05)
    {
      output_ppm (rho, linear = true, spread = 2);
      static FILE * fp1 = popen("ppm2mpeg > p.mpg", "w");
      output_ppm (p, fp1, linear = true, spread = 2);
      scalar dr[];
      foreach() {
        dr[] = 0.;
        foreach_dimension()
          dr[] += sq(rho[1] - rho[-1]);
        dr[] = sqrt(dr[])/(2.*Delta);
      }
      boundary({dr});
      static FILE * fp2 = popen("ppm2mpeg > dr.mpg", "w");
      output_ppm (dr, fp2, map = gray, min = 0, max = 2, n = 512, linear = true);
    
      foreach()
        dr[] = (rho[0,1] - rho[0,-1])/(2.*Delta);
      boundary({dr});
      static FILE * fp3 = popen("ppm2mpeg > dy.mpg", "w");
      output_ppm (dr, fp3, map = gray, min = -2, max = 2, n = 512, linear = true);
    
      foreach()
        dr[] = (rho[0,1] + rho[0,-1] - 2.*rho[])/sq(Delta);
      boundary({dr});
      static FILE * fp4 = popen("ppm2mpeg > d2y.mpg", "w");
      output_ppm (dr, fp4, map = gray, min = -10, max = 10, n = 512, linear = true);
    
      foreach()
        dr[] = level;
      boundary({dr});
      static FILE * fp5 = popen("ppm2mpeg > level.mpg", "w");
      output_ppm (dr, fp5, min = 0, max = LEVEL, n = 512);
    }
    
    #if TREE
    event adapt (i++) {
      adapt_wavelet ({f,rho}, (double[]){5e-3,5e-4}, LEVEL);
    }
    #endif

    See also