#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); } } }