sandbox/acastillo/filaments/old_but_interesting/3d/ellipticity.h

    #include "tag.h"
    #define dA (0.5 * sq(Delta))
    
    trace
    void vorticity3d(vector u, vector omega){
      vector du[], dv[], dw[]; // Would be nice to use a tensor here.
      foreach(){
        du.x[] = (u.x[1] - u.x[-1])/(2.*Delta);
        dv.x[] = (u.y[1] - u.y[-1])/(2.*Delta);
        dw.x[] = (u.z[1] - u.z[-1])/(2.*Delta);
    
        du.y[] = (u.x[0,1] - u.x[0,-1])/(2.*Delta);
        dv.y[] = (u.y[0,1] - u.y[0,-1])/(2.*Delta);
        dw.y[] = (u.z[0,1] - u.z[0,-1])/(2.*Delta);
    
        du.z[] = (u.x[0,0,1] - u.x[0,0,-1])/(2.*Delta);
        dv.z[] = (u.y[0,0,1] - u.y[0,0,-1])/(2.*Delta);
        dw.z[] = (u.z[0,0,1] - u.z[0,0,-1])/(2.*Delta);
      }
    
      foreach(){
        omega.x[] = dw.y[] - dv.z[];
        omega.y[] = du.z[] - dw.x[];
        omega.z[] = dv.x[] - du.y[];
      }
      boundary ((scalar*){omega});
    }
    
    trace
    void vorticity_moments_plane(scalar omega, scalar m, int nm, char * name, coord n, double _alpha){
    
      double circulation, M20, M02, M11, va, vb, vc, ve, omax;
      coord centroids={0.,0.,0.};
    
      for (int nj = 0; nj < nm; nj++){
        // Compute the circulation $\Gamma = \iint \omega dA$ and position of the
        // vortex centroids $\vec{\mu} = \iint \vec{x}\omega dA$
        double var1 = 0., var2 = 0., var3 = 0., var4 = 0.;
        foreach(reduction(+:var1), reduction(+:var2), reduction(+:var3), reduction(+:var4)){
          double alpha = (_alpha - n.x*x - n.y*y - n.z*z)/Delta;
          if (fabs(alpha) > 0.87)
            continue;
          if (is_active(cell) && is_local(cell)) {
            coord p = {x,y,z};
    
            double sval;
            if (n.x == 1)
              sval = 0.5*(val(omega) + val(omega,1,0,0));
            else if (n.y == 1)
              sval = 0.5*(val(omega) + val(omega,0,1,0));
            else
              sval = 0.5*(val(omega) + val(omega,0,0,1));
    
            if (m[] == nj+1){
              var1 += dA * sval;
              var2 += dA * sval * p.x;
              var3 += dA * sval * p.y;
              var4 += dA * sval * p.z;
            }
          }
        }
        circulation = var1;
    
    
        if (circulation != 0) {
          centroids = (coord) {var2/var1, var3/var1, var4/var1};
    
          // For the ellipticity we require the centered vorticity moments
          // $ M_{p,q} = \iint (x - \mu_x)^p (y - \mu_y)^q \omega dA $
    
          var1 = 0., var2 = 0., var3 = 0., var4 = 0.;
          double var5 = 0., var6 = 0.;
    
          foreach(reduction(+:var1), reduction(+:var2), reduction(+:var3), reduction(+:var4), reduction(+:var5), reduction(+:var6)){
            double alpha = (_alpha - n.x*x - n.y*y - n.z*z)/Delta;
            if (fabs(alpha) > 0.87)
              continue;
            if (is_active(cell) && is_local(cell)) {
              coord p = {x,y,z};
    
              double sval;
              if (n.x == 1)
                sval = 0.5*(val(omega) + val(omega,1,0,0));
              else if (n.y == 1)
                sval = 0.5*(val(omega) + val(omega,0,1,0));
              else
                sval = 0.5*(val(omega) + val(omega,0,0,1));
    
              if (m[] == nj+1){
                var1 += dA * sval * sq(p.x - centroids.x);
                var2 += dA * sval * sq(p.y - centroids.y);
                var3 += dA * sval * sq(p.z - centroids.z);
                var4 += dA * sval * (p.x - centroids.x) * (p.y - centroids.y);
                var5 += dA * sval * (p.y - centroids.y) * (p.z - centroids.z);
                var6 += dA * sval * (p.z - centroids.z) * (p.x - centroids.x);
              }
            }
          }
    
          if (n.x == 1){
            M20 = var2/circulation;
            M02 = var3/circulation;
            M11 = var5/circulation;
          }
          else if (n.y == 1){
            M20 = var1/circulation;
            M02 = var3/circulation;
            M11 = var6/circulation;
          }
          else{
            M20 = var1/circulation;
            M02 = var2/circulation;
            M11 = var4/circulation;
          }
    
          /** The mean radius is obtained from $a=\sqrt{M_{2,0} + M_{0,2}}$, whereas
          the major and minos axes of the equivalent ellipse are given by
          $b = \sqrt{M_{2,0} + M_{0,2} + \sqrt{4M_{1,1}^2 + (M_{2,0} - M_{0,2})^2}}$
          and
          $c = \sqrt{M_{2,0} + M_{0,2} - \sqrt{4M_{1,1}^2 + (M_{2,0} - M_{0,2})^2}}$,
          respectively, while the ellipticity reads as $e = \sqrt{1 - c^2/b^2}$.
          */
    
          va = sqrt(M20 + M02);
          vb = sqrt((M20 + M02 + sqrt(4*sq(M11) + sq(M20 - M02))));
          vc = sqrt((M20 + M02 - sqrt(4*sq(M11) + sq(M20 - M02))));
          ve = sqrt(1 - sq(vc)/sq(vb));
        }
        //fprintf (stdout, "%.15g %d %d %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g \n", t, nj, pid(), circulation, centroids.x, centroids.y, centroids.z, M20, M02, M11, va, vb, vc, ve);
    
        omax = interpolate (omega, centroids.x, centroids.y, centroids.z);
        if (pid() == 0){
          @if _MPI
            MPI_Reduce (MPI_IN_PLACE, &omax, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD);
          @endif
        }
        @if _MPI
        else
          MPI_Reduce (&omax, NULL, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD);
        @endif
    
        FILE * fp;
        if ((pid()==0) & (circulation != 0)) {
          fp = fopen(name, "a");
          fprintf (fp, "%.4f %d %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g \n", t, nj, circulation, centroids.x, centroids.y, centroids.z, M20, M02, M11, va, vb, vc, ve, omax);
          fclose(fp);
        }
      }
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    trace
    void vorticity_moments2_plane(vector omega, scalar m, int nm, char * name, coord n, double _alpha){
    
      double circulation, M20, M02, M11, va, vb, vc, ve, omax;
      coord centroids={0.,0.,0.}, tvec={0.,0.,0.};
    
      for (int nj = 0; nj < nm; nj++){
        // Compute the circulation $\Gamma = \iint \omega dA$ and position of the
        // vortex centroids $\vec{\mu} = \iint \vec{x}\omega dA$
        double var1 = 0., var2 = 0., var3 = 0., var4 = 0.;
        foreach(reduction(+:var1), reduction(+:var2), reduction(+:var3), reduction(+:var4)){
          double alpha = (_alpha - n.x*x - n.y*y - n.z*z)/Delta;
          if (fabs(alpha) > 0.87)
            continue;
          if (is_active(cell) && is_local(cell)) {
            coord sval;
            if (n.x == 1){
              sval.x = val(omega.x) + val(omega.x,1,0,0);
              sval.y = val(omega.y) + val(omega.y,1,0,0);
              sval.z = val(omega.z) + val(omega.z,1,0,0);
            }
            else if (n.y == 1){
              sval.x = val(omega.x) + val(omega.x,0,1,0);
              sval.y = val(omega.y) + val(omega.y,0,1,0);
              sval.z = val(omega.z) + val(omega.z,0,1,0);
            }
            else{
              sval.x = val(omega.x) + val(omega.x,0,0,1);
              sval.y = val(omega.y) + val(omega.y,0,0,1);
              sval.z = val(omega.z) + val(omega.z,0,0,1);
            }
    
            if (m[] == nj+1){
              var1 += dA * 0.5 * sval.x;
              var2 += dA * 0.5 * sval.y;
              var3 += dA * 0.5 * sval.z;
              var4 += dA * 0.25 * sqrt(sq(sval.x) + sq(sval.y) + sq(sval.z));
            }
          }
        }
    
        circulation = var4;
    
        double tol = 1e-14;
        if (circulation != 0) {
          tvec=(coord){var1, var2, var3};
          normalize(&tvec);
    
          double var1 = 0., var2 = 0., var3 = 0., var4 = 0.;
          foreach(reduction(+:var1), reduction(+:var2), reduction(+:var3), reduction(+:var4)){
            double alpha = (_alpha - n.x*x - n.y*y - n.z*z)/Delta;
            if (fabs(alpha) > 0.87)
              continue;
            if (is_active(cell) && is_local(cell)) {
              coord p = {x,y,z};
    
              double sval;
              if (n.x == 1)
                sval = 0.5*(val(omega.x) + val(omega.x,1,0,0)) * tvec.x + 0.5*(val(omega.y) + val(omega.y,1,0,0)) * tvec.y + 0.5*(val(omega.z) + val(omega.z,1,0,0)) * tvec.z;
              else if (n.y == 1)
                sval = 0.5*(val(omega.x) + val(omega.x,0,1,0)) * tvec.x + 0.5*(val(omega.y) + val(omega.y,0,1,0)) * tvec.y + 0.5*(val(omega.z) + val(omega.z,0,1,0)) * tvec.z;
              else
                sval = 0.5*(val(omega.x) + val(omega.x,0,0,1)) * tvec.x + 0.5*(val(omega.y) + val(omega.y,0,0,1)) * tvec.y + 0.5*(val(omega.z) + val(omega.z,0,0,1)) * tvec.z;
    
              if (m[] == nj+1){
                var1 += dA * sval;
                var2 += dA * sval * p.x;
                var3 += dA * sval * p.y;
                var4 += dA * sval * p.z;
              }
            }
          }
    
          centroids = (coord) {var2/var1, var3/var1, var4/var1};
    
          // For the ellipticity we require the centered vorticity moments
          // $ M_{p,q} = \iint (x - \mu_x)^p (y - \mu_y)^q \omega dA $
    
          var1 = 0., var2 = 0., var3 = 0., var4 = 0.;
          double var5 = 0., var6 = 0.;
    
          foreach(reduction(+:var1), reduction(+:var2), reduction(+:var3), reduction(+:var4), reduction(+:var5), reduction(+:var6)){
            double alpha = (_alpha - n.x*x - n.y*y - n.z*z)/Delta;
            if (fabs(alpha) > 0.87)
              continue;
            if (is_active(cell) && is_local(cell)) {
              coord p = {x,y,z};
    
              double sval;
              if (n.x == 1)
                sval = 0.5*(val(omega.x) + val(omega.x,1,0,0)) * tvec.x + 0.5*(val(omega.y) + val(omega.y,1,0,0)) * tvec.y + 0.5*(val(omega.z) + val(omega.z,1,0,0)) * tvec.z;
              else if (n.y == 1)
                sval = 0.5*(val(omega.x) + val(omega.x,0,1,0)) * tvec.x + 0.5*(val(omega.y) + val(omega.y,0,1,0)) * tvec.y + 0.5*(val(omega.z) + val(omega.z,0,1,0)) * tvec.z;
              else
                sval = 0.5*(val(omega.x) + val(omega.x,0,0,1)) * tvec.x + 0.5*(val(omega.y) + val(omega.y,0,0,1)) * tvec.y + 0.5*(val(omega.z) + val(omega.z,0,0,1)) * tvec.z;
    
              if (m[] == nj+1){
                var1 += dA * sval * sq(p.x - centroids.x);
                var2 += dA * sval * sq(p.y - centroids.y);
                var3 += dA * sval * sq(p.z - centroids.z);
                var4 += dA * sval * (p.x - centroids.x) * (p.y - centroids.y);
                var5 += dA * sval * (p.y - centroids.y) * (p.z - centroids.z);
                var6 += dA * sval * (p.z - centroids.z) * (p.x - centroids.x);
              }
            }
          }
    
          if (n.x == 1){
            M20 = var2/circulation;
            M02 = var3/circulation;
            M11 = var5/circulation;
          }
          else if (n.y == 1){
            M20 = var1/circulation;
            M02 = var3/circulation;
            M11 = var6/circulation;
          }
          else{
            M20 = var1/circulation;
            M02 = var2/circulation;
            M11 = var4/circulation;
          }
    
          /** The mean radius is obtained from $a=\sqrt{M_{2,0} + M_{0,2}}$, whereas
          the major and minos axes of the equivalent ellipse are given by
          $b = \sqrt{M_{2,0} + M_{0,2} + \sqrt{4M_{1,1}^2 + (M_{2,0} - M_{0,2})^2}}$
          and
          $c = \sqrt{M_{2,0} + M_{0,2} - \sqrt{4M_{1,1}^2 + (M_{2,0} - M_{0,2})^2}}$,
          respectively, while the ellipticity reads as $e = \sqrt{1 - c^2/b^2}$.
          */
    
          va = sqrt(M20 + M02);
          vb = sqrt((M20 + M02 + sqrt(4*sq(M11) + sq(M20 - M02))));
          vc = sqrt((M20 + M02 - sqrt(4*sq(M11) + sq(M20 - M02))));
          ve = sqrt(1 - sq(vc)/sq(vb));
          //fprintf (stdout, "%.15g %d %d %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g \n", t, nj, pid(), circulation, centroids.x, centroids.y, centroids.z, M20, M02, M11, va, vb, vc, ve);
        }
    
        var1 = interpolate (omega.x, centroids.x, centroids.y, centroids.z);
        var2 = interpolate (omega.y, centroids.x, centroids.y, centroids.z);
        var3 = interpolate (omega.z, centroids.x, centroids.y, centroids.z);
        omax = (var1 * tvec.x) + (var2 * tvec.y) + (var3 * tvec.z);
        if (pid() == 0){
          @if _MPI
            MPI_Reduce (MPI_IN_PLACE, &omax, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD);
          @endif
        }
        @if _MPI
        else
          MPI_Reduce (&omax, NULL, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD);
        @endif
    
        FILE * fp;
        if ((pid()==0) & (circulation != 0)) {
          fp = fopen(name, "a");
          fprintf (fp, "%.4f %d %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g %.15g \n", t, nj, circulation, centroids.x, centroids.y, centroids.z, M20, M02, M11, va, vb, vc, ve, omax);
          fclose(fp);
        }
      }
    }