sandbox/kaitaotang/docoll3d.c

    #include "grid/octree.h"
    #include "navier-stokes/centered.h"
    #include "two-phase.h"
    #include "navier-stokes/conserving.h"
    #include "tension.h"
    #include "tag.h"
    #include "view.h"

    Include profiling information.

    #include "navier-stokes/perfs.h"
    #include "profiling.h"
    
    #include <math.h>
    #include <gsl/gsl_errno.h>
    #include <gsl/gsl_fft_real.h>
    #include <gsl/gsl_fft_halfcomplex.h>
    
    
    #include <sys/stat.h>
    #include <sys/types.h>
    
    #define LEVEL 11
    #define MINLEVEL 7
    #define MAXTIME 0.03
    //#define R0 0.05 // Initial bubble radius
    #define R0 0.05
    #define WE 280. //Weber number
    //#define OH 0.14 //Ohnesorge number
    #define OH 0.01 // Try this
    #define OFFSET 0.95
    #define ETA 0.06
    #define RATIO 1./833.
    //#define MURATIO 17.4e-6/8.9e-4 //dynamic viscosity ratio, water to air
    #define MURATIO 1./55. //viscosity ratio water to air, not chosen according to Pierson but to previous bubble-in-turbulence studies; expect it will not have much effect, especially for values below 0.1
    #define ADDNOISE 1 //boolean noise 
    #define CONSTANT 0.01 // noise scaling
    
    double raw_series_l[4096]; double raw_series_r[4096]; 
    double raw_series_l_old[4096]; double raw_series_r_old[4096]; 
    int series_len;
    
    u.n[top] = neumann(0.);
    u.t[top] = neumann(0.);
    u.r[top] = neumann(0.);
    
    FILE * fk = NULL;
    FILE * fe = NULL;
    
    
    //----------------------MAIN-----------------------//
    //Begin main function
    int main() {
      L0 = 2.;
      periodic(front);
      origin (-L0/2., 0., 0.);
      rho1 = 1.0;
      rho2 = RATIO;

    For calculating viscosities, interpret Reynolds number as defined at depth of unity.

      f.sigma = 1.; //0.01 is very stable
      mu1 = OH*sqrt(rho1*f.sigma*2*R0); //double check this definition
      mu2 = mu1*MURATIO;

    Use depth length scale for Bond number as well.

      //TOLERANCE = HUGE;
      //NITERMIN = 20;
      
      mkdir("./interface", 0777);
      mkdir("./frag_stats", 0777);
      
      char name[80];
      sprintf (name, "3Denergy-%d.dat", LEVEL);
      fe = fopen (name, "w");
    
      sprintf (name, "3Dkinetics-%d.dat", LEVEL);
      fk = fopen (name, "w");
      
      series_len = (1 << LEVEL); 
      
      init_grid(1 << (MINLEVEL+1));
      run();
      
      fclose (fe); fclose (fk);
    }
    
    //---------------------INITIALIZATION------------------------//
    void set_noise_signal() {
      gsl_fft_real_wavetable * real;
      gsl_fft_halfcomplex_wavetable * hc;
      gsl_fft_real_workspace * work;
    
      if (pid() == 0) {
        srand(time(NULL));
        for (int i=0; i<series_len; i++) {
          raw_series_l[i] = (double)rand() / (double)RAND_MAX - 0.5;
          raw_series_r[i] = (double)rand() / (double)RAND_MAX - 0.5;
          raw_series_l_old[i] = raw_series_l[i]; raw_series_r_old[i] = raw_series_r[i]; 
        }
        
        work = gsl_fft_real_workspace_alloc(series_len);
        real = gsl_fft_real_wavetable_alloc(series_len);
    
        gsl_fft_real_transform (raw_series_l, 1, series_len, real, work);
        gsl_fft_real_transform (raw_series_r, 1, series_len, real, work);
        gsl_fft_real_wavetable_free (real);
    
        for (int i = 121; i<series_len; i++) {raw_series_l[i] = 0; raw_series_r[i] = 0;}
        for (int i = 1; i<120; i++) if (i % 2 == 1) {raw_series_l[i] = 0; raw_series_r[i] = 0;}
    
        hc = gsl_fft_halfcomplex_wavetable_alloc (series_len);
    
        gsl_fft_halfcomplex_inverse (raw_series_l, 1, series_len, hc, work);
        gsl_fft_halfcomplex_inverse (raw_series_r, 1, series_len, hc, work);
        gsl_fft_halfcomplex_wavetable_free (hc);
        gsl_fft_real_workspace_free (work);
      
      
        double series_ave_l = 0., series_var_l = 0., series_ave_r = 0., series_var_r = 0.;
        for (int i=0; i<series_len; i++) {
          series_ave_l += raw_series_l[i]/(double)(series_len); series_var_l += sq(raw_series_l[i])/(double)(series_len);
          series_ave_r += raw_series_r[i]/(double)(series_len); series_var_r += sq(raw_series_r[i])/(double)(series_len);
        }
      
        series_var_l -= sq(series_ave_l); series_var_r -= sq(series_ave_r);
        
        for (int i=0; i<series_len; i++) {
          raw_series_l[i] = (raw_series_l[i] - series_ave_l) / sqrt(series_var_l);
          raw_series_r[i] = (raw_series_r[i] - series_ave_r) / sqrt(series_var_r);
        }
      }
      
      MPI_Bcast (&(raw_series_l[0]), series_len, MPI_DOUBLE, 0, MPI_COMM_WORLD);
      MPI_Bcast (&(raw_series_r[0]), series_len, MPI_DOUBLE, 0, MPI_COMM_WORLD);
      
      char resultname[100];
      sprintf (resultname, "perturbation_series.dat");
      
      if (pid() == 0) {
        FILE * fseries = fopen(resultname, "w");
        
        for (int i=0; i<series_len; i++) {
          fprintf(fseries, "%d %g %g %g %g\n", i, raw_series_l_old[i], raw_series_l[i], raw_series_r_old[i], raw_series_r[i]);
          fflush(fseries);
        }
        
        fclose(fseries);
      }
    }
    
    
    
    double dropletValue(double x, double y, double z, double amp){
    //  double sgn = -1.;
    //  double sum = 0.; // initializing summation
    
      // wavenumber for loop
      // for (int k_i = 0; k_i < 25; k_i++) {
        //double a_i = forcing_const/k_i;
        //sum = sum + noise_sig_coeff[k_i] * sin(2*pi/L0 * (k_i+1)*z);
      //}
      //double amp = sum; // assigning the amplitude to the summation
      double stp = L0/(double)(series_len);
      int index = (int)((z - stp/2. - Z0)/stp);
      if (index < 0) index = 0; if (index > series_len) index = series_len;
      
      if (x < 0.) return -sq(x + R0*OFFSET) - sq(y) + sq(R0 + amp*R0*raw_series_l[index]);
        else return -sq(x - R0*OFFSET) - sq(y) + sq(R0 + amp*R0*raw_series_r[index]);
    }
    
    //
    /*Write initialization event*/
    event init (i = 0)
    {
      if (!restore("restart")){
        set_noise_signal();
    //    int jdx = 0;
        double dropvel = sqrt(WE*f.sigma/(2.*R0)/rho1)/2.;
    //    double femax = 2e-4;
    //    double uemax = 2e-2;
    //    do {
    //      jdx += 1;
    //      fprintf(ferr, "Initializing, %d\n", jdx );
          //fraction (f, -sq(x - R0*OFFSET) - sq(y) + sq(R0));
          refine (fabs(x) < 2.2*R0 && fabs(y) < 1.1*R0 && level < (LEVEL-1));
          fraction (f, dropletValue(x, y, z, ETA));
          boundary ((scalar *){f,u});
          foreach()
            u.x[] = -f[]*dropvel*sign(x);
    //    }
    //    while (adapt_wavelet ({f,u}, (double[]){femax,uemax, uemax, uemax}, LEVEL, MINLEVEL).nf);
      }
    }
    
    //-------------------ADAPTIVITY---------------------//
    /*Adapt once on error in volume fraction, velocity field, and beach fraction*/
    event adapt(i++) {
      double femax = 1e-2;
      double uemax = 5e-2;
      adapt_wavelet ({f,u.x,u.y,u.z}, (double[]){femax,uemax,uemax,uemax}, LEVEL, 5);
    }
    
    //------------------------IMAGING--------------------------
    /*
    event intoutput(t += 0.0001) {
      char resultname[100];
      char tmpname[100];
      sprintf( tmpname, "interface/_res-%d.dat", pid() );
      if (pid() == 0)
        sprintf (resultname, "interface/results%4.4f.dat", t );
      
      FILE * fp = fopen(tmpname, "w");
      scalar xpos[];
      scalar ypos[];
      scalar zpos[];
      
      position (f, xpos, {1, 0, 0});
      position (f, ypos, {0, 1, 0});
      position (f, zpos, {0, 0, 1});
      
      foreach()
        if (xpos[] != nodata)
          fprintf (fp, "%g %g %g\n", xpos[], ypos[], zpos[]);
      fclose (fp);
      
      char copycat[200];
      if (pid() == 0){
        sprintf (copycat, "cat interface/_res-*.dat > %s", resultname);
        system (copycat);
        system ("rm interface/_res-*.dat");
      }   
    }
    */
    
    
    
    int dissipation_rate (vector u, double* rates)
    {
      double rateWater = 0.0;
      double rateAir = 0.0;
      foreach (reduction (+:rateWater) reduction (+:rateAir)) {
        double dudx = (u.x[1] - u.x[-1])/(2.0*Delta);
        double dudy = (u.x[0,1] - u.x[0,-1])/(2.*Delta);
        double dudz = (u.x[0,0,1] - u.x[0,0,-1])/(2.*Delta);
        double dvdx = (u.y[1]   - u.y[-1]  )/(2.*Delta);
        double dvdy = (u.y[0,1] - u.y[0,-1])/(2.0*Delta);
        double dvdz = (u.y[0,0,1] - u.y[0,0,-1])/(2.*Delta);
        double dwdx = (u.z[1]     - u.z[-1]    )/(2.*Delta);
        double dwdy = (u.z[0,1]   - u.z[0,-1]  )/(2.*Delta);
        double dwdz = (u.z[0,0,1] - u.z[0,0,-1])/(2.0*Delta);
        double SDeformxx = dudx;
        double SDeformxy = 0.5*(dudy + dvdx);
        double SDeformxz = 0.5*(dudz + dwdx);
        double SDeformyx = SDeformxy;
        double SDeformyy = dvdy;
        double SDeformyz = 0.5*(dvdz + dwdy);
        double SDeformzx = SDeformxz;
        double SDeformzy = SDeformyz;
        double SDeformzz = dwdz; 
        double sqterm = 2.0*dv()*(sq(SDeformxx) + sq(SDeformxy) + sq(SDeformxz) +
    			      sq(SDeformyx) + sq(SDeformyy) + sq(SDeformyz) +
    			      sq(SDeformzx) + sq(SDeformzy) + sq(SDeformzz));
        
        rateWater += mu1*f[]*sqterm; //water
        rateAir   += mu2*(1. - f[])*sqterm; //air
      }
    
      rates[0] = rateWater;
      rates[1] = rateAir;
      return 0;
    }
    
    
    
    event logfile (t = 1e-6; t <= MAXTIME; t += 2e-5) {
      double ke_d = 0., ke_a = 0., area = 0.;
    
      foreach(reduction(+:ke_d) reduction(+:ke_a)) {
        // Kinetic energy of the droplet and ambient airflow
        ke_d += 0.5*dv()*(sq(u.x[]) + sq(u.y[]) + sq(u.z[])) * rho1*f[];
        ke_a += 0.5*dv()*(sq(u.x[]) + sq(u.y[]) + sq(u.z[])) * rho2*(1-f[]);
      }
    
      // Droplet surface area
      area = interface_area(f);
    
    
    
      // Viscous dissipation rate
      double rates[2];
      dissipation_rate(u, rates);
      double diss_w = rates[0], diss_a = rates[1];
      
      
      
      double delta = L0 / (double)(1 << LEVEL);
      double h_contact_ave = 0.0; int n_contact = 0;
      double h_contact_max = 0.0;
      
      foreach(reduction(+:h_contact_ave) reduction(+:n_contact) reduction(max:h_contact_max))
        if (f[] > 1e-6 && f[] < 1.-1e-6 && -0.5*delta <= x && x <= 0.5*delta) {
          h_contact_ave += y; h_contact_max = fmax(h_contact_max, y);
          n_contact++;
        }
      h_contact_ave /= n_contact;
    
      fprintf (fk, "%.8f %.8f %.8f %.8f\n", t, h_contact_ave, h_contact_max, area);
      fflush (fk);
    
      fprintf (fe, "%.8f %.8f %.8f %.8f %.8f\n", t, ke_d, ke_a, diss_w, diss_a);
      fflush (fe);
    }
    
    
    
    event count_droplets (t = 0; t <= MAXTIME; t += 2e-5) {
      scalar m_cd[];
      foreach() m_cd[] = f[] > 0.5;
      int n = tag (m_cd);
    
      double v[n], ux_drop[n], uy_drop[n], uz_drop[n], area[n], ke[n];
      coord b[n];
    
      for (int j = 0; j < n; j++)
        v[j] = b[j].x = b[j].y = b[j].z = ux_drop[j] = uy_drop[j] = uz_drop[j] = area[j] = ke[j] = 0.;
    
      foreach_leaf()
        if (m_cd[] > 0) {
          int j = m_cd[] - 1;
          v[j] += dv()*f[];
    
          coord p = {x,y,z};
          foreach_dimension()
    	    b[j].x += dv()*f[]*p.x;
    
          ux_drop[j] += dv()*f[]*u.x[];
    	  uy_drop[j] += dv()*f[]*u.y[];
    	  uz_drop[j] += dv()*f[]*u.z[];
    	  
          ke[j] += 0.5 * rho1*dv()*f[] * (sq(u.x[]) + sq(u.y[]) + sq(u.z[]));
    	  
          // interfacial area
          if (f[] > 1e-4 && f[] < 1. - 1e-4) {
            coord m = mycs (point, f);
            double alpha = plane_alpha (f[], m);
            coord p;
            area[j] += sq(Delta) * plane_area_center(m, alpha, &p);
          }
        }
    
    #if _MPI
      MPI_Allreduce (MPI_IN_PLACE, v, n, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      MPI_Allreduce (MPI_IN_PLACE, area, n, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      MPI_Allreduce (MPI_IN_PLACE, ke, n, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      MPI_Allreduce (MPI_IN_PLACE, b, 3*n, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      MPI_Allreduce (MPI_IN_PLACE, ux_drop, n, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      MPI_Allreduce (MPI_IN_PLACE, uy_drop, n, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
      MPI_Allreduce (MPI_IN_PLACE, uz_drop, n, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
    #endif
    
      if (n > 1 && pid() == 0) {
        char resultname[100];
        sprintf(resultname, "./frag_stats/frag_stat_%4.4f.dat", t);
        FILE * fdrop = fopen(resultname, "w");
      
        for (int j=0; j<n; j++) {
          fprintf (fdrop, "%g %d %g %g %g %g %g %g %g %g %g\n", t, j, v[j], b[j].x/v[j], b[j].y/v[j], b[j].z/v[j], ux_drop[j]/v[j], uy_drop[j]/v[j], uz_drop[j]/v[j], ke[j], f.sigma*area[j]);
        }
        
        fclose(fdrop);
      }
    }
    
    
    
    #define POPEN(name, mode) fopen (name ".ppm", mode)
    
    event movie (t = 1e-6; t += 2e-5) {
    #if TREE
      scalar l[];
      foreach()
        l[] = level;
    #endif
    #if dimension == 2
      static FILE * fp = POPEN ("f", "w");
      output_ppm (f, fp, n=1024);
      static FILE * fp4 = POPEN ("l", "w");
      output_ppm (l, fp4, min=1, max=LEVEL);
    #else //dimension == 3
    //  view (width = 800, height = 600, tx=-0.5, ty=-0.5, theta=-pi/4., phi=-pi/6., fov=10);
      view (camera = "iso");
      view (tx = 0.4, ty=0.3, fov=20);
      clear();
      box();
      draw_vof("f");
      //squares("l", n = {1,0,0}, alpha=0.);
      static FILE *fp = POPEN ("movie", "w");
      save (fp = fp);
      //view (theta=pi/4., phi=pi/6., tx = 0.5, ty=0.5);
      clear();
      view (tx = 0.0001, ty=0.0001);
      view (camera = "right");
      view (tx = 0.5, ty = -0.5);
      draw_vof("f");
      static FILE *fpr = POPEN ("right", "w");
      save (fp = fpr);
    #endif //dimension
    }
    
    event snapshot (t += 0.002) { // dump files
      char dname[100];
      sprintf(dname, "dump%g", t);
      dump(dname);
    }
    
    event snapshot_restart (t += 1e-4) { // dump files
      char dname[100];
      sprintf(dname, "restart");
      dump(dname);
    }
    
    
    event end (t=MAXTIME) { 
      printf ("i = %d t=%g\n", i, t);
      dump ("end");
    }