#include #include #include #include #include #include "Array.h" #include "PointList.h" //#include "vecLib/clapack.h" using namespace std; //-------------------------------------------------------------------------------------------------------- int ComputeBlob(IntArray &blobs, int &nblobs, int &ncubes, IntArray &indicator, DoubleArray &F, DoubleArray &S, double vf, double vs, int startx, int starty, int startz, IntArray &temp) { // Compute the blob (F>vf|S>vs) starting from (i,j,k) - oil blob // F>vf => oil phase S>vs => in porespace // update the list of blobs, indicator mesh int m = F.m; // maxima for the meshes int n = F.n; int o = F.o; int cubes_in_blob=0; int nrecent = 1; // number of nodes added at most recent sweep temp(0,0) = startx; // Set the initial point as a "seed" for the sweeps temp(1,0) = starty; temp(2,0) = startz; int ntotal = 1; // total number of nodes in blob indicator(startx,starty,startz) = nblobs; int p,s,x,y,z,start,finish,nodx,nody,nodz; int imin=startx,imax=startx,jmin=starty,jmax=starty; // initialize maxima / minima int kmin=startz,kmax=startz; int d[26][3] = {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}, {1,1,0},{1,-1,0},{-1,1,0},{-1,-1,0},{1,0,1},{-1,0,1}, {1,0,-1},{-1,0,-1},{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}, {1,1,1},{1,1,-1},{1,-1,1},{1,-1,-1},{-1,1,1},{-1,1,-1}, {-1,-1,1},{-1,-1,-1}}; // directions to neighbors int cube[8][3] = {{0,0,0},{1,0,0},{0,1,0},{1,1,0},{0,0,1},{1,0,1},{0,1,1},{1,1,1}}; // cube corners bool status = 1; // status == true => continue to look for points while (status == 1){ start = ntotal - nrecent; finish = ntotal; nrecent = 0; // set recent points back to zero for next sweep through for (s=start;s m-1 ){ nodx = 0; } nody=y+d[p][1]; if (nody < 0 ){ nody = n-1; } // Periodic BC for y if (nody > n-1 ){ nody = 0; } nodz=z+d[p][2]; if (nodz < 0 ){ nodz = 0; } // No periodic BC for z if (nodz > o-1 ){ nodz = o-1; } if ( F(nodx,nody,nodz) > vf && S(nodx,nody,nodz) > vs && indicator(nodx,nody,nodz) == -1 ){ // Node is a part of the blob - add it to the list temp(0,ntotal) = nodx; temp(1,ntotal) = nody; temp(2,ntotal) = nodz; ntotal++; nrecent++; // Update the indicator map indicator(nodx,nody,nodz) = nblobs; // Update the min / max for the cube loop if ( nodx < imin ){ imin = nodx; } if ( nodx > imax ){ imax = nodx; } if ( nody < jmin ){ jmin = nody; } if ( nody > jmax ){ jmax = nody; } if ( nodz < kmin ){ kmin = nodz; } if ( nodz > kmax ){ kmax = nodz; } } else if (F(nodx,nody,nodz) > vf && S(nodx,nody,nodz) > vs && indicator(nodx,nody,nodz) > -1 && indicator(nodx,nody,nodz) != nblobs){ // Some kind of error in algorithm printf("Error in blob search algorithm!"); } } } if ( nrecent == 0){ status = 0; } } // Use points in temporary storage array to add cubes to the list of blobs if ( imin > 0) { imin = imin-1; } // if ( imax < m-1) { imax = imax+1; } if ( jmin > 0) { jmin = jmin-1; } // if ( jmax < n-1) { jmax = jmax+1; } if ( kmin > 0) { kmin = kmin-1; } // if ( kmax < o-1) { kmax = kmax+1; } int i,j,k; bool add; for (k=kmin;k -1 && indicator(nodx,nody,nodz) != nblobs){ printf("Overlapping cube!"); cout << i << ", " << j << ", " << k << endl; } } } } } } return cubes_in_blob; } //-------------------------------------------------------------------------------------------------- /* DoubleArray SOLVE( DoubleArray &A, DoubleArray &b) { // solves the system A*x = b exactly DoubleArray AA = A.Copy(); long int n = A.n; long int nrhs =1; IntArray piv(2*n); DoubleArray solution = b.Copy(); long int info = 0; int ret = dgesv_(&n,&nrhs,AA.Pointer(),&n,(long int *)piv.Pointer(),solution.Pointer(),&n,&info); // DTErrorMessage("Computation", string("Error=")+ DTInt2String(ret) + "info = " + DTInt2String(info)); return solution; } //----------------------------------------------------------------------------- Point NEWTON(Point x0, DoubleArray &F, double &v,DoubleArray &S, int i, int j, int k, int &newton_steps) { Point pt; // Performs a Newton iteration to compute the point x from initial guess x0 double tol = 0.001; double dist = 1; // Map x0 into unit coordinates Point X0 = x0; x0.x = x0.x - i; x0.y = x0.y - j; x0.z = x0.z - k; // Compute coefficients for tri-linear approximations to the functions F and S // coefficients for F double Af, Bf, Cf, Df, Ef, Ff, Gf, Hf; Af = F(i,j,k); Bf = F(i+1,j,k)-Af; Cf = F(i,j+1,k)-Af; Df = F(i,j,k+1)-Af; Ef = F(i+1,j+1,k)-Af-Bf-Cf; Ff = F(i+1,j,k+1)-Af-Bf-Df; Gf = F(i,j+1,k+1)-Af-Cf-Df; Hf = F(i+1,j+1,k+1)-Af-Bf-Cf-Df-Ef-Ff-Gf; // coefficients for S double As, Bs, Cs, Ds, Es, Fs, Gs, Hs; As = S(i,j,k); Bs = S(i+1,j,k)-As; Cs = S(i,j+1,k)-As; Ds = S(i,j,k+1)-As; Es = S(i+1,j+1,k)-As-Bs-Cs; Fs = S(i+1,j,k+1)-As-Bs-Ds; Gs = S(i,j+1,k+1)-As-Cs-Ds; Hs = S(i+1,j+1,k+1)-As-Bs-Cs-Ds-Es-Fs-Gs; // Compute coefficients for plane in direction of grad F, grad S at point x0 // Compute grad u = grad F , v = grad S int count; int number; count = 0; number = int(floor(newton_steps)); //number = 2; pt = x0; bool pt_on_cube_leg = 0; // Compute the u = grad F, v = grad S and the normal vector N = u x v double u1, u2, u3, v1, v2, v3; u1 = Bf+Ef*x0.y+Ff*x0.z+Hf*x0.y*x0.z; u2 = Cf+Ef*x0.x+Gf*x0.z+Hf*x0.x*x0.z; u3 = Df+Ff*x0.x+Gf*x0.y+Hf*x0.x*x0.y; v1 = Bs+Es*x0.y+Fs*x0.z+Hs*x0.y*x0.z; v2 = Cs+Es*x0.x+Gs*x0.z+Hs*x0.x*x0.z; v3 = Ds+Fs*x0.x+Gs*x0.y+Hs*x0.x*x0.y; // Compute the normal vector N Point N; if (x0.x == 0 || x0.x == 1){ if (x0.y == 0 || x0.y == 1){ // on a cube leg pt_on_cube_leg = 1; } else if (x0.z == 0 || x0.z == 1){ // on a cube leg pt_on_cube_leg = 1; } else { // use this cube face as the normal N.x = 1; N.y = 0; N.z = 0; } } else if (x0.y == 0 || x0.y == 1){ if (x0.z == 0 || x0.z == 1){ // on a cube leg pt_on_cube_leg = 1; } else { // use this cube face as the normal N.x = 0; N.y = 1; N.z = 0; } } else if (x0.z == 0 || x0.z == 1){ // use this cube face as the normal N.x = 0; N.y = 0; N.z = 1; } else { // Compute N = u x v N.x = u2*v3 - u3*v2; N.y = u3*v1 - u1*v3; N.z = u1*v2 - u2*v1; } if ( pt_on_cube_leg == 1){ // return x0 pt = x0; } else { while (count < number ){ // Construct the Jacobean Matrix J DoubleArray J(3,3); J(0,0) = u1; J(0,1) = u2; J(0,2) = u3; J(1,0) = v1; J(1,1) = v2; J(1,2) = v3; J(2,0) = N.x; J(2,1) = N.y; J(2,2) = N.z; // Evaluate the vector M(x0) DoubleArray M(3); M(0) = -(Af+Bf*x0.x+Cf*x0.y+Df*x0.z+Ef*x0.x*x0.y+Ff*x0.x*x0.z+Gf*x0.y*x0.z+Hf*x0.x*x0.y*x0.z - v); M(1) = -(As+Bs*x0.x+Cs*x0.y+Ds*x0.z+Es*x0.x*x0.y+Fs*x0.x*x0.z+Gs*x0.y*x0.z+Hs*x0.x*x0.y*x0.z); M(2) = 0; // Compute the update to x0 using Newton's method Point dX; DoubleArray d = SOLVE(J,M); dX.x = d(0); dX.y = d(1); dX.z = d(2); if ( dX.x > 0.1 || dX.y > 0.1 || dX.z > 0.1 || dX.x < -0.1 || dX.y < -0.1 || dX.z < -0.1){ count = number; } else { pt = x0+dX; x0 = pt; } M(0) = -(Af+Bf*x0.x+Cf*x0.y+Df*x0.z+Ef*x0.x*x0.y+Ff*x0.x*x0.z+Gf*x0.y*x0.z+Hf*x0.x*x0.y*x0.z - v); M(1) = -(As+Bs*x0.x+Cs*x0.y+Ds*x0.z+Es*x0.x*x0.y+Fs*x0.x*x0.z+Gs*x0.y*x0.z+Hs*x0.x*x0.y*x0.z); M(2) = 0; dist = sqrt(M(0)*M(0)+M(1)*M(1)+M(2)*M(2)); // Compute u, v at new x0 u1 = Bf+Ef*x0.y+Ff*x0.z+Hf*x0.y*x0.z; u2 = Cf+Ef*x0.x+Gf*x0.z+Hf*x0.x*x0.z; u3 = Df+Ff*x0.x+Gf*x0.y+Hf*x0.x*x0.y; v1 = Bs+Es*x0.y+Fs*x0.z+Hs*x0.y*x0.z; v2 = Cs+Es*x0.x+Gs*x0.z+Hs*x0.x*x0.z; v3 = Ds+Fs*x0.x+Gs*x0.y+Hs*x0.x*x0.y; count++; } } // map pt back to original coordinates pt.x = pt.x+i; pt.y = pt.y+j; pt.z = pt.z+k; return pt; } */ //-------------------------------------------------------------------------------------------------- bool vertexcheck(Point &P, int n, int pos, DTMutableList &cellvertices){ // returns true if P is a new vertex (one previously unencountered bool V = 1; int i = pos-n; for (i = pos-n; i < pos; i++){ if ( P == cellvertices(i)){ V = 0; } } return V; } //-------------------------------------------------------------------------------------------------- bool ShareSide( Point &A, Point &B) { // returns true if points A and B share an x,y, or z coordinate bool l = 0; if ( A.x != B.x && A.y != B.y && A.z != B.z){ l=0; } else{ if (floor(A.x)==A.x && floor(B.x)==B.x && A.x==B.x) { l = 1; } if (floor(A.y)==A.y && floor(B.y)==B.y && A.y==B.y) { l = 1; } if (floor(A.z)==A.z && floor(B.z)==B.z && A.z==B.z) { l = 1; } } return l; } //-------------------------------------------------------------------------------------------------- bool Interface( DoubleArray &A, const double v, int i, int j, int k){ // returns true if grid cell i, j, k contains a section of the interface bool Y = 0; if ((A(i,j,k)-v)*(A(i+1,j,k)-v) < 0 ){ Y=1; } // 2 if ((A(i+1,j,k)-v)*(A(i+1,j+1,k)-v) < 0){ Y=1; } //3 if ((A(i+1,j+1,k)-v)*(A(i,j+1,k)-v) < 0){ Y=1; } //4 if ((A(i,j+1,k)-v)*(A(i,j,k)-v) < 0 ){ Y=1; } //5 if ((A(i,j,k)-v)*(A(i,j,k+1)-v) < 0 ){ Y=1; } //6 if ((A(i+1,j,k)-v)*(A(i+1,j,k+1)-v) < 0 ){ Y=1; } //7 if ((A(i+1,j+1,k)-v)*(A(i+1,j+1,k+1)-v) < 0 ){ Y=1; } //8 if ((A(i,j+1,k)-v)*(A(i,j+1,k+1)-v) < 0 ){ Y=1; } //9 if ((A(i,j,k+1)-v)*(A(i+1,j,k+1)-v) < 0 ){ Y=1; } //10 if ((A(i+1,j,k+1)-v)*(A(i+1,j+1,k+1)-v) < 0 ){ Y=1; } //11 if ((A(i+1,j+1,k+1)-v)*(A(i,j+1,k+1)-v) < 0 ){ Y=1; } //12 if ((A(i,j+1,k+1)-v)*(A(i,j,k+1)-v) < 0 ){ Y=1; } return Y; } //-------------------------------------------------------------------------------------------------- bool Fluid_Interface( DoubleArray &A, DoubleArray &S, const double v, int i, int j, int k){ // returns true if grid cell i, j, k contains a section of the interface bool Y = 0; if ((A(i,j,k)-v)*(A(i+1,j,k)-v) < 0 && S(i,j,k) > 0 && S(i+1,j,k) > 0){ Y=1; } // 2 if ((A(i+1,j,k)-v)*(A(i+1,j+1,k)-v) < 0 && S(i+1,j,k) > 0 && S(i+1,j+1,k) > 0){ Y=1; } //3 if ((A(i+1,j+1,k)-v)*(A(i,j+1,k)-v) < 0 && S(i+1,j+1,k) > 0 && S(i,j+1,k) > 0){ Y=1; } //4 if ((A(i,j+1,k)-v)*(A(i,j,k)-v) < 0 && S(i,j,k) > 0 && S(i,j+1,k) > 0){ Y=1; } //5 if ((A(i,j,k)-v)*(A(i,j,k+1)-v) < 0 && S(i,j,k) > 0 && S(i,j,k+1) > 0){ Y=1; } //6 if ((A(i+1,j,k)-v)*(A(i+1,j,k+1)-v) < 0 && S(i+1,j,k) > 0 && S(i+1,j,k+1) > 0){ Y=1; } //7 if ((A(i+1,j+1,k)-v)*(A(i+1,j+1,k+1)-v) < 0 && S(i+1,j+1,k) > 0 && S(i+1,j+1,k+1) > 0){ Y=1; } //8 if ((A(i,j+1,k)-v)*(A(i,j+1,k+1)-v) < 0 && S(i,j+1,k) > 0 && S(i,j+1,k+1) > 0){ Y=1; } //9 if ((A(i,j,k+1)-v)*(A(i+1,j,k+1)-v) < 0 && S(i,j,k+1) > 0 && S(i+1,j,k+1) > 0){ Y=1; } //10 if ((A(i+1,j,k+1)-v)*(A(i+1,j+1,k+1)-v) < 0 && S(i+1,j,k+1) > 0 && S(i+1,j+1,k+1) > 0){ Y=1; } //11 if ((A(i+1,j+1,k+1)-v)*(A(i,j+1,k+1)-v) < 0 && S(i+1,j+1,k+1) > 0 && S(i,j+1,k+1) > 0){ Y=1; } //12 if ((A(i,j+1,k+1)-v)*(A(i,j,k+1)-v) < 0 && S(i,j,k+1) > 0 && S(i,j+1,k+1) > 0){ Y=1; } return Y; } //-------------------------------------------------------------------------------------------------- bool Solid( DoubleArray &A, int i, int j, int k){ bool X = 0; // return 0 if there is no solid phase in grid cell i,j,k if (A(i,j,k) == 0){ X = 1; } if (A(i+1,j,k) == 0){ X = 1; } if (A(i,j+1,k) == 0){ X = 1; } if (A(i,j,k+1) == 0){ X = 1; } if (A(i+1,j+1,k) == 0){ X = 1; } if (A(i+1,j,k+1) == 0){ X = 1; } if (A(i,j+1,k+1) == 0){ X = 1; } if (A(i+1,j+1,k+1) == 0){ X = 1; } return X; } //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- void SOL_SURF(DoubleArray &A, const double &v, DoubleArray &B, const double &isovalue, int i,int j,int k, int m, int n, int o, DTMutableList &cellvertices, int &lengthvertices, IntArray &Tlist, int &nTris, DoubleArray &values){ // THIS SUBROUTINE COMPUTES THE VERTICES FOR THE SOLID PHASE IN // A PARTICULAR GRID CELL, THEN ARRANGES THEM INTO TRIANGLES // ALSO ORGANIZES THE LIST OF VALUES TO CORRESPOND WITH VERTEX LIST int N = 0; Point P; Point PlaceHolder; int pos = lengthvertices; float temp; // int m; int n; int o; int p; int q; // for each leg of the triangle, see if a vertex exists // if so, find the vertex, and perform an extrapolation // Go over each corner -- check to see if the corners are themselves vertices //1 if (A(i,j,k) == v){ P.x = i; P.y = j; P.z = k; values(pos) = B(i,j,k); cellvertices(pos++) = P; N++; } //2 if (A(i+1,j,k) == v){ P.x = i+1; P.y = j; P.z = k; values(pos) = B(i+1,j,k); cellvertices(pos++) = P; N++; } //3 if (A(i+1,j+1,k) == v){ P.x = i+1; P.y = j+1; P.z = k; values(pos) = B(i+1,j+1,k); cellvertices(pos++) = P; N++; } //4 if (A(i,j+1,k) == v){ P.x = i; P.y = j+1; P.z = k; values(pos) = B(i,j+1,k); cellvertices(pos++) = P; N++; } //5 if (A(i,j,k+1) == v){ P.x = i; P.y = j; P.z = k+1; values(pos) = B(i,j,k+1); cellvertices(pos++) = P; N++; } //6 if (A(i+1,j,k+1) == v){ P.x = i+1; P.y = j; P.z = k+1; values(pos) = B(i+1,j,k+1); cellvertices(pos++) = P; N++; } //7 if (A(i+1,j+1,k+1) == v){ P.x = i+1; P.y = j+1; P.z = k+1; values(pos) = B(i+1,j+1,k+1); cellvertices(pos++) = P; N++; } //8 if (A(i,j+1,k+1) == v){ P.x = i; P.y = j+1; P.z = k+1; values(pos) = B(i,j+1,k+1); cellvertices(pos++) = P; N++; } // Go through each side, compute P for sides of box spiraling up if ((A(i,j,k)-v)*(A(i+1,j,k)-v) < 0) { P.x = i + (A(i,j,k)-v)/(A(i,j,k)-A(i+1,j,k)); P.y = j; P.z = k; // compute extrapolated fluid value at P // if ( A(i,j,k) > v){ // values(pos) = EXTRAP(B, isovalue, i,j,k,4, P); // } // else{ // values(pos) = EXTRAP(B,isovalue, i+1,j,k, 1, P); // } // Interpolate value at P using padded mesh B values(pos) = B(i,j,k)*(1-P.x+i)+B(i+1,j,k)*(P.x-i); cellvertices(pos++) = P; N++; } // 2 if ((A(i+1,j,k)-v)*(A(i+1,j+1,k)-v) < 0) { P.x = i+1; P.y = j + (A(i+1,j,k)-v)/(A(i+1,j,k)-A(i+1,j+1,k)); P.z = k; if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice) // compute extrapolated fluid value at P // if ( A(i+1,j,k) > v){ // values(pos) = EXTRAP(B,isovalue, i+1,j,k, 5, P); // } // else{ // values(pos) = EXTRAP(B,isovalue, i+1,j+1,k, 2, P); // } // Interpolate value at P using padded mesh B values(pos) = B(i+1,j,k)*(1-P.y+j)+B(i+1,j+1,k)*(P.y-j); cellvertices(pos++) = P; N++; } } //3 if ((A(i+1,j+1,k)-v)*(A(i,j+1,k)-v) < 0) { P.x = i + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i+1,j+1,k)); P.y = j+1; P.z = k; if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice) // compute extrapolated fluid value at P // if ( A(i+1,j+1,k) > v){ // values(pos) = EXTRAP(B,isovalue, i+1,j+1,k, 1, P); // } // else{ // values(pos) = EXTRAP(B,isovalue, i,j+1,k, 4, P); // } // Interpolate value at P using padded mesh B values(pos) = B(i,j+1,k)*(1-P.x+i)+B(i+1,j+1,k)*(P.x-i); cellvertices(pos++) = P; N++; } } //4 if ((A(i,j+1,k)-v)*(A(i,j,k)-v) < 0) { P.x = i; P.y = j + (A(i,j,k)-v) / (A(i,j,k)-A(i,j+1,k)); P.z = k; if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice) // compute extrapolated fluid value at P // if ( A(i,j,k) > v){ // values(pos) = EXTRAP(B,isovalue, i,j,k, 5, P); // } // else{ // values(pos) = EXTRAP(B,isovalue, i,j+1,k, 2, P); // } // Interpolate value at P using padded mesh B values(pos) = B(i,j,k)*(1-P.y+j)+B(i,j+1,k)*(P.y-j); cellvertices(pos++) = P; N++; } } //5 if ((A(i,j,k)-v)*(A(i,j,k+1)-v) < 0) { P.x = i; P.y = j; P.z = k + (A(i,j,k)-v) / (A(i,j,k)-A(i,j,k+1)); if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice) // compute extrapolated fluid value at P // if ( A(i,j,k) > v){ // values(pos) = EXTRAP(B,isovalue, i,j,k, 6, P); // } // else{ // values(pos) = EXTRAP(B,isovalue, i,j,k+1, 3, P); // } // Interpolate value at P using padded mesh B values(pos) = B(i,j,k)*(1-P.z+k)+B(i,j,k+1)*(P.z-k); cellvertices(pos++) = P; N++; } } //6 if ((A(i+1,j,k)-v)*(A(i+1,j,k+1)-v) < 0) { P.x = i+1; P.y = j; P.z = k + (A(i+1,j,k)-v) / (A(i+1,j,k)-A(i+1,j,k+1)); if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice) // compute extrapolated fluid value at P // if ( A(i+1,j,k) > v){ // values(pos) = EXTRAP(B,isovalue, i+1,j,k, 6, P); // } // else{ // values(pos) = EXTRAP(B,isovalue, i+1,j,k+1, 3, P); // } // Interpolate value at P using padded mesh B values(pos) = B(i+1,j,k)*(1-P.z+k)+B(i+1,j,k+1)*(P.z-k); cellvertices(pos++) = P; N++; } } //7 if ((A(i+1,j+1,k)-v)*(A(i+1,j+1,k+1)-v) < 0) { P.x = i+1; P.y = j+1; P.z = k + (A(i+1,j+1,k)-v) / (A(i+1,j+1,k)-A(i+1,j+1,k+1)); if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice) // compute extrapolated fluid value at P // if ( A(i+1,j+1,k) > v){ // values(pos) = EXTRAP(B,isovalue, i+1,j+1,k, 6, P); // } // else{ // values(pos) = EXTRAP(B,isovalue, i+1,j+1,k+1, 3, P); // } // Interpolate value at P using padded mesh B values(pos) = B(i+1,j+1,k)*(1-P.z+k)+B(i+1,j+1,k+1)*(P.z-k); cellvertices(pos++) = P; N++; } } //8 if ((A(i,j+1,k)-v)*(A(i,j+1,k+1)-v) < 0) { P.x = i; P.y = j+1; P.z = k + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i,j+1,k+1)); if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice) // compute extrapolated fluid value at P // if ( A(i,j+1,k) > v){ // values(pos) = EXTRAP(B,isovalue, i,j+1,k, 6, P); // } // else{ // values(pos) = EXTRAP(B,isovalue, i,j+1,k+1, 3, P); // } // Interpolate value at P using padded mesh B values(pos) = B(i,j+1,k)*(1-P.z+k)+B(i,j+1,k+1)*(P.z-k); cellvertices(pos++) = P; N++; } } //9 if ((A(i,j,k+1)-v)*(A(i+1,j,k+1)-v) < 0) { P.x = i + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i+1,j,k+1)); P.y = j; P.z = k+1; if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice) // compute extrapolated fluid value at P // if ( A(i,j,k+1) > v){ // values(pos) = EXTRAP(B,isovalue, i,j,k+1, 4, P); // } // else{ // values(pos) = EXTRAP(B,isovalue, i+1,j,k+1, 1, P); // } // Interpolate value at P using padded mesh B values(pos) = B(i,j,k+1)*(1-P.x+i)+B(i+1,j,k+1)*(P.x-i); cellvertices(pos++) = P; N++; } } //10 if ((A(i+1,j,k+1)-v)*(A(i+1,j+1,k+1)-v) < 0) { P.x = i+1; P.y = j + (A(i+1,j,k+1)-v) / (A(i+1,j,k+1)-A(i+1,j+1,k+1)); P.z = k+1; if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice) // compute extrapolated fluid value at P // if ( A(i+1,j,k+1) > v){ // values(pos) = EXTRAP(B,isovalue, i+1,j,k+1, 5, P); // } // else{ // values(pos) = EXTRAP(B,isovalue, i+1,j+1,k+1, 2, P); // } // Interpolate value at P using padded mesh B values(pos) = B(i+1,j,k+1)*(1-P.y+j)+B(i+1,j+1,k+1)*(P.y-j); cellvertices(pos++) = P; N++; } } //11 if ((A(i+1,j+1,k+1)-v)*(A(i,j+1,k+1)-v) < 0) { P.x = i+(A(i,j+1,k+1)-v) / (A(i,j+1,k+1)-A(i+1,j+1,k+1)); P.y = j+1; P.z = k+1; if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice) // compute extrapolated fluid value at P // if ( A(i,j+1,k+1) > v){ // values(pos) = EXTRAP(B,isovalue, i,j+1,k+1, 4, P); // } // else{ // values(pos) = EXTRAP(B,isovalue, i+1,j+1,k+1, 1, P); // } // Interpolate value at P using padded mesh B values(pos) = B(i,j+1,k+1)*(1-P.x+i)+B(i+1,j+1,k+1)*(P.x-i); cellvertices(pos++) = P; N++; } } //12 if ((A(i,j+1,k+1)-v)*(A(i,j,k+1)-v) < 0) { P.x = i; P.y = j + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i,j+1,k+1)); P.z = k+1; if (vertexcheck(P, N, pos, cellvertices) == 1){ // P is a new vertex (not counted twice) // compute extrapolated fluid value at P // if ( A(i,j,k+1) > v){ // values(pos) = EXTRAP(B,isovalue, i,j,k+1, 5, P); // } // else{ // values(pos) = EXTRAP(B,isovalue, i,j+1,k+1, 2, P); // } // Interpolate value at P using padded mesh B values(pos) = B(i,j,k+1)*(1-P.y+j)+B(i,j+1,k+1)*(P.y-j); cellvertices(pos++) = P; N++; } } lengthvertices = pos; // * * * ARRANGE VERTICES SO THAT NEIGHBORS SHARE A FACE * * * // * * * PERFORM SAME OPERATIONS TO THE LIST OF VALUES * * * for (q = pos-N; q < pos-2; q++) { for (o = q+2; o < pos-1; o++) { if (ShareSide(cellvertices(q), cellvertices(o)) == 1) { PlaceHolder = cellvertices(q+1); cellvertices(q+1) = cellvertices(o); cellvertices(o) = PlaceHolder; temp = values(q+1); values(q+1) = values(o); values(o) = temp; } } // make sure other neighbor of vertex 1 is in last spot if (q == pos-N){ for (p = q+2; p < pos-1; p++){ if (ShareSide(cellvertices(q), cellvertices(p)) == 1){ PlaceHolder = cellvertices(pos-1); cellvertices(pos-1) = cellvertices(p); cellvertices(p) = PlaceHolder; temp = values(pos-1); values(pos-1) = values(p); values(p) = temp; } } } if ( ShareSide(cellvertices(pos-2), cellvertices(pos-3)) != 1 ){ if (ShareSide( cellvertices(pos-3), cellvertices(pos-1)) == 1 && ShareSide( cellvertices(pos-N), cellvertices(pos-2)) == 1 ){ PlaceHolder = cellvertices(pos-2); cellvertices(pos-2) = cellvertices(pos-1); cellvertices(pos-1) = PlaceHolder; temp = values(pos-2); values(pos-2) = values(pos-1); values(pos-1) = temp; } } if ( ShareSide(cellvertices(pos-1), cellvertices(pos-2)) != 1 ){ if (ShareSide( cellvertices(pos-3), cellvertices(pos-1)) == 1 && ShareSide(cellvertices(pos-4), cellvertices(pos-2)) == 1 ){ PlaceHolder = cellvertices(pos-3); cellvertices(pos-3) = cellvertices(pos-2); cellvertices(pos-2) = PlaceHolder; temp = values(pos-3); values(pos-3) = values(pos-2); values(pos-2) = temp; } if (ShareSide( cellvertices(pos-N+1), cellvertices(pos-3)) == 1 && ShareSide(cellvertices(pos-1), cellvertices(pos-N+1)) == 1 ){ PlaceHolder = cellvertices(pos-2); cellvertices(pos-2) = cellvertices(pos-N+1); cellvertices(pos-N+1) = PlaceHolder; temp = values(pos-2); values(pos-2) = values(pos-N+1); values(pos-N+1) = temp; } } if ( ShareSide(cellvertices(pos-N), cellvertices(pos-N+1)) != 1 ){ if (ShareSide( cellvertices(pos-N), cellvertices(pos-2)) == 1 && ShareSide(cellvertices(pos-1), cellvertices(pos-N+1)) == 1){ PlaceHolder = cellvertices(pos-1); cellvertices(pos-1) = cellvertices(pos-N); cellvertices(pos-N) = PlaceHolder; temp = values(pos-1); values(pos-1) = values(pos-N); values(pos-N) = temp; } } } // * * * ESTABLISH TRIANGLE CONNECTIONS * * * for (p=pos-N+2; p &local_sol_pts, int &n_local_sol_pts, double isovalue, IntArray &local_sol_tris, int &n_local_sol_tris, DTMutableList &ns_pts, int &n_ns_pts, IntArray &ns_tris, int &n_ns_tris, DTMutableList &ws_pts, int &n_ws_pts, IntArray &ws_tris, int &n_ws_tris, DoubleArray &values, DTMutableList &local_nws_pts, int &n_local_nws_pts, DoubleArray &fluid_pad, DoubleArray &S, int &i, int &j, int &k, int &newton_steps){ // Trim the local solid surface int map_ws; int map_ns; int pts_on_tri; int p; int q; int a; int b; int c; Point A; Point B; Point C; Point D; Point E; Point F; Point P; bool all_to_ns = 1; // Check to see if all triangles in the cell are in ns_surface for (q=0; q < n_local_sol_pts; q++){ if ( values(q) <= isovalue && all_to_ns == 1){ all_to_ns = 0; } } bool all_to_ws = 1; // Check to see if all triangles in the cell are in ws surface for (q=0; q < n_local_sol_pts; q++){ if ( values(q) >= isovalue && all_to_ws == 1){ all_to_ws = 0; } } if (all_to_ws == 1){ map_ws = n_ws_pts; for ( p=0; p= isovalue && values(b) >= isovalue && values(c) >= isovalue ){ // Triangle is in ns surface // Add points ns_pts(n_ns_pts++) = A; ns_pts(n_ns_pts++) = B; ns_pts(n_ns_pts++) = C; // Add triangles ns_tris(0,n_ns_tris) = n_ns_pts-3; ns_tris(1,n_ns_tris) = n_ns_pts-2; ns_tris(2,n_ns_tris) = n_ns_pts-1; n_ns_tris++; } else if (values(a) <= isovalue && values(b) <= isovalue && values(c) <= isovalue ){ // Triangle is in ws surface // Add points ws_pts(n_ws_pts++) = A; ws_pts(n_ws_pts++) = B; ws_pts(n_ws_pts++) = C; // Add triangles ws_tris(0,n_ws_tris) = n_ws_pts-3; ws_tris(1,n_ws_tris) = n_ws_pts-2; ws_tris(2,n_ws_tris) = n_ws_pts-1; n_ws_tris++; // If two of values(a), values(b), values(c) --> this tri leg is on common line // Since this leg is part of two triangles, one in ws surface and one in ns surface // we only need to do this procedure one time if (values(a) == isovalue && values(b) == isovalue){ if ( n_local_nws_pts == 0 ){ local_nws_pts(n_local_nws_pts++) = A; local_nws_pts(n_local_nws_pts++) = B; } else if ( A != local_nws_pts(n_local_nws_pts-1) ){ local_nws_pts(n_local_nws_pts++) = A; local_nws_pts(n_local_nws_pts++) = B; } } if (values(a) == isovalue && values(c) == isovalue){ if ( n_local_nws_pts == 0 ){ local_nws_pts(n_local_nws_pts++) = A; local_nws_pts(n_local_nws_pts++) = C; } else if ( A != local_nws_pts(n_local_nws_pts-1) ){ local_nws_pts(n_local_nws_pts++) = A; local_nws_pts(n_local_nws_pts++) = C; } } if (values(b) == isovalue && values(c) == isovalue){ if ( n_local_nws_pts == 0 ){ local_nws_pts(n_local_nws_pts++) = B; local_nws_pts(n_local_nws_pts++) = C; } else if ( A != local_nws_pts(n_local_nws_pts-1) ){ local_nws_pts(n_local_nws_pts++) = B; local_nws_pts(n_local_nws_pts++) = C; } } } else { // Triangle contains common line //////////////////////////////////////// ///////// FIND THE COMMON LINE ///////// //////////////////////////////////////// pts_on_tri = 0; if ( (values(a)-isovalue)*(values(b)-isovalue) < 0){ // compute common line vertex P = A + (values(a) - isovalue)/(values(a)-values(b))*(B-A); if ( n_local_nws_pts == 0 ){ local_nws_pts(n_local_nws_pts++) = P; pts_on_tri++; } else if ( P != local_nws_pts(n_local_nws_pts-1) ){ local_nws_pts(n_local_nws_pts++) = P; pts_on_tri++; } } if ( (values(b)-isovalue)*(values(c)-isovalue) < 0){ // compute common line vertex P = B + (values(b) - isovalue)/(values(b)-values(c))*(C-B); if ( n_local_nws_pts == 0 ){ local_nws_pts(n_local_nws_pts++) = P; pts_on_tri++; } else if ( P != local_nws_pts(n_local_nws_pts-1) ){ local_nws_pts(n_local_nws_pts++) = P; pts_on_tri++; } } if ( (values(a)-isovalue)*(values(c)-isovalue) < 0){ // compute common line vertex P = A + (values(a) - isovalue)/(values(a)-values(c))*(C-A); local_nws_pts(n_local_nws_pts++) = P; pts_on_tri++; } // Also consider case in which common line points may be at vertices if ( values(a) == isovalue ){ if ( n_local_nws_pts == 0 ){ local_nws_pts(n_local_nws_pts++) = A; pts_on_tri++; } else if ( A != local_nws_pts(n_local_nws_pts-1) ){ local_nws_pts(n_local_nws_pts++) = A; pts_on_tri++; } } if ( values(b) == isovalue ){ if ( n_local_nws_pts == 0 ){ local_nws_pts(n_local_nws_pts++) = B; pts_on_tri++; } else if ( B != local_nws_pts(n_local_nws_pts-1) ){ local_nws_pts(n_local_nws_pts++) = B; pts_on_tri++; } } if ( values(c) == isovalue ){ if ( n_local_nws_pts == 0 ){ local_nws_pts(n_local_nws_pts++) = C; pts_on_tri++; } else if ( C != local_nws_pts(n_local_nws_pts-1) ){ local_nws_pts(n_local_nws_pts++) = C; pts_on_tri++; } } // If there is a section of common line found // Use these common line points as an initial guess in Newton iteration D = local_nws_pts(n_local_nws_pts-2); E = local_nws_pts(n_local_nws_pts-1); F = 0.5*(local_nws_pts(n_local_nws_pts-2) + local_nws_pts(n_local_nws_pts-1)); // D = NEWTON(local_nws_pts(n_local_nws_pts-2),fluid_pad,isovalue,S,i,j,k,newton_steps); // E = NEWTON(local_nws_pts(n_local_nws_pts-1),fluid_pad,isovalue,S,i,j,k,newton_steps); // F = NEWTON(F,fluid_pad,isovalue,S,i,j,k,newton_steps); // Write over the initial common line points // Note point F goes in between points D and E local_nws_pts(n_local_nws_pts-2) = D; local_nws_pts(n_local_nws_pts-1) = F; local_nws_pts(n_local_nws_pts++) = E; // Construct the new triangles if ( (values(a)-isovalue)*(values(b)-isovalue) < 0 && (values(b)-isovalue)*(values(c)-isovalue) < 0){ if (values(b) > isovalue){ // Points ns_pts(n_ns_pts++) = B; ns_pts(n_ns_pts++) = D; ns_pts(n_ns_pts++) = E; ns_pts(n_ns_pts++) = F; // Triangles ns_tris(0,n_ns_tris) = n_ns_pts-4; // B ns_tris(1,n_ns_tris) = n_ns_pts-1; // F ns_tris(2,n_ns_tris) = n_ns_pts-3; // D n_ns_tris++; ns_tris(0,n_ns_tris) = n_ns_pts-4; // B ns_tris(1,n_ns_tris) = n_ns_pts-2; // E ns_tris(2,n_ns_tris) = n_ns_pts-1; // F n_ns_tris++; // Points ws_pts(n_ws_pts++) = A; //-5 ws_pts(n_ws_pts++) = C; //-4 ws_pts(n_ws_pts++) = D; //-3 ws_pts(n_ws_pts++) = E; //-2 ws_pts(n_ws_pts++) = F; //-1 // Triangles (A,D,F),(A,C,F),(C,E,F) ws_tris(0,n_ws_tris) = n_ws_pts-5; // A ws_tris(1,n_ws_tris) = n_ws_pts-1; // F ws_tris(2,n_ws_tris) = n_ws_pts-3; // D n_ws_tris++; ws_tris(0,n_ws_tris) = n_ws_pts-5; // A ws_tris(1,n_ws_tris) = n_ws_pts-4; // C ws_tris(2,n_ws_tris) = n_ws_pts-1; // F n_ws_tris++; ws_tris(0,n_ws_tris) = n_ws_pts-4; // C ws_tris(1,n_ws_tris) = n_ws_pts-2; // E ws_tris(2,n_ws_tris) = n_ws_pts-1; // F n_ws_tris++; } else { // Points ws_pts(n_ws_pts++) = B; //-4 ws_pts(n_ws_pts++) = D; //-3 ws_pts(n_ws_pts++) = E; //-2 ws_pts(n_ws_pts++) = F; //-1 // Triangles ws_tris(0,n_ws_tris) = n_ws_pts-4; // B ws_tris(1,n_ws_tris) = n_ws_pts-1; // F ws_tris(2,n_ws_tris) = n_ws_pts-3; // D n_ws_tris++; ws_tris(0,n_ws_tris) = n_ws_pts-4; // B ws_tris(1,n_ws_tris) = n_ws_pts-2; // E ws_tris(2,n_ws_tris) = n_ws_pts-1; // F n_ws_tris++; // Points ns_pts(n_ns_pts++) = A; //-5 ns_pts(n_ns_pts++) = C; //-4 ns_pts(n_ns_pts++) = D; //-3 ns_pts(n_ns_pts++) = E; //-2 ns_pts(n_ns_pts++) = F; //-1 // Triangles (A,D,F),(A,C,F),(C,E,F) ns_tris(0,n_ns_tris) = n_ns_pts-5; // A ns_tris(1,n_ns_tris) = n_ns_pts-1; // F ns_tris(2,n_ns_tris) = n_ns_pts-3; // D n_ns_tris++; ns_tris(0,n_ns_tris) = n_ns_pts-5; // A ns_tris(1,n_ns_tris) = n_ns_pts-4; // C ns_tris(2,n_ns_tris) = n_ns_pts-1; // F n_ns_tris++; ns_tris(0,n_ns_tris) = n_ns_pts-4; // C ns_tris(1,n_ns_tris) = n_ns_pts-2; // E ns_tris(2,n_ns_tris) = n_ns_pts-1; // F n_ns_tris++; } } else if ( (values(a)-isovalue)*(values(b)-isovalue) < 0 && (values(a)-isovalue)*(values(c)-isovalue) < 0){ if (values(a) > isovalue){ // Points ns_pts(n_ns_pts++) = A; //-4 ns_pts(n_ns_pts++) = D; //-3 ns_pts(n_ns_pts++) = E; //-2 ns_pts(n_ns_pts++) = F; //-1 // Triangles ns_tris(0,n_ns_tris) = n_ns_pts-4; // A ns_tris(1,n_ns_tris) = n_ns_pts-1; // F ns_tris(2,n_ns_tris) = n_ns_pts-3; // D n_ns_tris++; ns_tris(0,n_ns_tris) = n_ns_pts-4; // A ns_tris(1,n_ns_tris) = n_ns_pts-2; // E ns_tris(2,n_ns_tris) = n_ns_pts-1; // F n_ns_tris++; // Points ws_pts(n_ws_pts++) = B; //-5 ws_pts(n_ws_pts++) = C; //-4 ws_pts(n_ws_pts++) = D; //-3 ws_pts(n_ws_pts++) = E; //-2 ws_pts(n_ws_pts++) = F; //-1 // Triangles (B,D,F),(B,C,F),(C,E,F) ws_tris(0,n_ws_tris) = n_ws_pts-5; // B ws_tris(1,n_ws_tris) = n_ws_pts-1; // F ws_tris(2,n_ws_tris) = n_ws_pts-3; // D n_ws_tris++; ws_tris(0,n_ws_tris) = n_ws_pts-5; // B ws_tris(1,n_ws_tris) = n_ws_pts-4; // C ws_tris(2,n_ws_tris) = n_ws_pts-1; // F n_ws_tris++; ws_tris(0,n_ws_tris) = n_ws_pts-4; // C ws_tris(1,n_ws_tris) = n_ws_pts-2; // E ws_tris(2,n_ws_tris) = n_ws_pts-1; // F n_ws_tris++; } else { // Points ws_pts(n_ws_pts++) = A; //-4 ws_pts(n_ws_pts++) = D; //-3 ws_pts(n_ws_pts++) = E; //-2 ws_pts(n_ws_pts++) = F; //-1 // Triangles ws_tris(0,n_ws_tris) = n_ws_pts-4; // A ws_tris(1,n_ws_tris) = n_ws_pts-1; // F ws_tris(2,n_ws_tris) = n_ws_pts-3; // D n_ws_tris++; ws_tris(0,n_ws_tris) = n_ws_pts-4; // A ws_tris(1,n_ws_tris) = n_ws_pts-2; // E ws_tris(2,n_ws_tris) = n_ws_pts-1; // F n_ws_tris++; // Points ns_pts(n_ns_pts++) = B; //-5 ns_pts(n_ns_pts++) = C; //-4 ns_pts(n_ns_pts++) = D; //-3 ns_pts(n_ns_pts++) = E; //-2 ns_pts(n_ns_pts++) = F; //-1 // Triangles (B,D,F),(B,C,F),(C,E,F) ns_tris(0,n_ns_tris) = n_ns_pts-5; // B ns_tris(1,n_ns_tris) = n_ns_pts-1; // F ns_tris(2,n_ns_tris) = n_ns_pts-3; // D n_ns_tris++; ns_tris(0,n_ns_tris) = n_ns_pts-5; // B ns_tris(1,n_ns_tris) = n_ns_pts-4; // C ns_tris(2,n_ns_tris) = n_ns_pts-1; // F n_ns_tris++; ns_tris(0,n_ns_tris) = n_ns_pts-4; // C ns_tris(1,n_ns_tris) = n_ns_pts-2; // E ns_tris(2,n_ns_tris) = n_ns_pts-1; // F n_ns_tris++; } } else { if (values(c) > isovalue){ // Points ns_pts(n_ns_pts++) = C; //-4 ns_pts(n_ns_pts++) = D; //-3 ns_pts(n_ns_pts++) = E; //-2 ns_pts(n_ns_pts++) = F; //-1 // Triangles ns_tris(0,n_ns_tris) = n_ns_pts-4; // C ns_tris(1,n_ns_tris) = n_ns_pts-1; // F ns_tris(2,n_ns_tris) = n_ns_pts-3; // D n_ns_tris++; ns_tris(0,n_ns_tris) = n_ns_pts-4; // C ns_tris(1,n_ns_tris) = n_ns_pts-2; // E ns_tris(2,n_ns_tris) = n_ns_pts-1; // F n_ns_tris++; // Points ws_pts(n_ws_pts++) = A; //-5 ws_pts(n_ws_pts++) = B; //-4 ws_pts(n_ws_pts++) = D; //-3 ws_pts(n_ws_pts++) = E; //-2 ws_pts(n_ws_pts++) = F; //-1 // Triangles (A,E,F),(A,B,F),(B,D,F) ws_tris(0,n_ws_tris) = n_ws_pts-5; // A ws_tris(1,n_ws_tris) = n_ws_pts-1; // F ws_tris(2,n_ws_tris) = n_ws_pts-2; // E n_ws_tris++; ws_tris(0,n_ws_tris) = n_ws_pts-5; // A ws_tris(1,n_ws_tris) = n_ws_pts-4; // B ws_tris(2,n_ws_tris) = n_ws_pts-1; // F n_ws_tris++; ws_tris(0,n_ws_tris) = n_ws_pts-4; // B ws_tris(1,n_ws_tris) = n_ws_pts-3; // D ws_tris(2,n_ws_tris) = n_ws_pts-1; // F n_ws_tris++; } else { // Points ws_pts(n_ws_pts++) = C; //-4 ws_pts(n_ws_pts++) = D; //-3 ws_pts(n_ws_pts++) = E; //-2 ws_pts(n_ws_pts++) = F; //-1 // Triangles ws_tris(0,n_ws_tris) = n_ws_pts-4; // C ws_tris(1,n_ws_tris) = n_ws_pts-1; // F ws_tris(2,n_ws_tris) = n_ws_pts-3; // D n_ws_tris++; ws_tris(0,n_ws_tris) = n_ws_pts-4; // C ws_tris(1,n_ws_tris) = n_ws_pts-2; // E ws_tris(2,n_ws_tris) = n_ws_pts-1; // F n_ws_tris++; // Points ns_pts(n_ns_pts++) = A; //-5 ns_pts(n_ns_pts++) = B; //-4 ns_pts(n_ns_pts++) = D; //-3 ns_pts(n_ns_pts++) = E; //-2 ns_pts(n_ns_pts++) = F; //-1 // Triangles (A,E,F),(A,B,F),(B,D,F) ns_tris(0,n_ns_tris) = n_ns_pts-5; // A ns_tris(1,n_ns_tris) = n_ns_pts-1; // F ns_tris(2,n_ns_tris) = n_ns_pts-2; // E n_ns_tris++; ns_tris(0,n_ns_tris) = n_ns_pts-5; // A ns_tris(1,n_ns_tris) = n_ns_pts-4; // B ns_tris(2,n_ns_tris) = n_ns_pts-1; // F n_ns_tris++; ns_tris(0,n_ns_tris) = n_ns_pts-4; // B ns_tris(1,n_ns_tris) = n_ns_pts-3; // D ns_tris(2,n_ns_tris) = n_ns_pts-1; // F n_ns_tris++; } } } } } } //------------------------------------------------------------------------------- void MC( DoubleArray &A, double &v, DoubleArray &solid, int &i, int &j, int &k, DTMutableList &nw_pts, int &n_nw_pts, IntArray &nw_tris, int &n_nw_tris) { int N = 0; // n will be the number of vertices in this grid cell only Point P; Point pt; DoubleArray TEST(3); Point PlaceHolder; int m; int o; int p; // Go over each corner -- check to see if the corners are themselves vertices //1 if (A(i,j,k) == v){ P.x = i; P.y = j; P.z = k; nw_pts(n_nw_pts++) = P; N++; } //2 if (A(i+1,j,k) == v){ P.x = i+1; P.y = j; P.z = k; nw_pts(n_nw_pts++) = P; N++; } //3 if (A(i+1,j+1,k) == v){ P.x = i+1; P.y = j+1; P.z = k; nw_pts(n_nw_pts++) = P; N++; } //4 if (A(i,j+1,k) == v){ P.x = i; P.y = j+1; P.z = k; nw_pts(n_nw_pts++) = P; N++; } //5 if (A(i,j,k+1) == v){ P.x = i; P.y = j; P.z = k+1; nw_pts(n_nw_pts++) = P; N++; } //6 if (A(i+1,j,k+1) == v){ P.x = i+1; P.y = j; P.z = k+1; nw_pts(n_nw_pts++) = P; N++; } //7 if (A(i+1,j+1,k+1) == v){ P.x = i+1; P.y = j+1; P.z = k+1; nw_pts(n_nw_pts++) = P; N++; } //8 if (A(i,j+1,k+1) == v){ P.x = i; P.y = j+1; P.z = k+1; nw_pts(n_nw_pts++) = P; N++; } // Go through each side, compute P for sides of box spiraling up // float val; if ((A(i,j,k)-v)*(A(i+1,j,k)-v) < 0) { // If both points are in the fluid region if (A(i,j,k) != 0 && A(i+1,j,k) != 0){ P.x = i + (A(i,j,k)-v)/(A(i,j,k)-A(i+1,j,k)); P.y = j; P.z = k; // Evaluate the function S at the new point if ( solid(i,j,k)*(1-P.x+i) + solid(i+1,j,k)*(P.x-i) > 0 ){ // This point is in the fluid region nw_pts(n_nw_pts++) = P; N++; } } } // if point A(i,j,k) is in the solid phase // else if ( A(i,j,k) == 0 ){ // pt.x = i; // pt.y = j; // pt.z = k; // val = EXTRAP(A, v, i+1,j,k, 1,pt); // // If extrapolated value gives a vertex // if ( (A(i+1,j,k)- v)*(val-v) < 0 ){ // P.x = i + (val-v)/(val-A(i+1,j,k)); // P.y = j; // P.z = k; // if ( INTERP(solid(i,j,k), solid(i+1,j,k), P.x-i) > 0 ){ // nw_pts(n_nw_pts++) = P; // N++; // } // } // } // // if point A(i+1,j,k) is in the solid phase // else if ( A(i+1,j,k) == 0 ){ // pt.x = i+1; // pt.y = j; // pt.z = k; // val = EXTRAP(A, v, i,j,k, 4,pt); // // If extrapolated value gives a vertex // if ( (A(i,j,k)- v)*(val-v) < 0 ){ // P.x = i + (A(i,j,k)-v)/(A(i,j,k)-val); // P.y = j; // P.z = k; // if ( INTERP(solid(i,j,k), solid(i+1,j,k), P.x-i) > 0 ){ // nw_pts(n_nw_pts++) = P; // N++; // } // } // } // } // 2 if ((A(i+1,j,k)-v)*(A(i+1,j+1,k)-v) < 0) { if ( A(i+1,j,k) != 0 && A(i+1,j+1,k) != 0 ){ P.x = i+1; P.y = j + (A(i+1,j,k)-v)/(A(i+1,j,k)-A(i+1,j+1,k)); P.z = k; // Evaluate the function S at the new point if ( solid(i+1,j,k)*(1-P.y+j) + solid(i+1,j+1,k)*(P.y-j) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } // else if ( A(i+1,j,k) == 0 ){ // pt.x = i+1; // pt.y = j; // pt.z = k; // val = EXTRAP(A, v, i+1,j+1,k, 2,pt); // // If extrapolated value gives a vertex // if ( (A(i+1,j+1,k)- v)*(val-v) < 0 ){ // P.x = i+1; // P.y = j + (val-v)/(val-A(i+1,j+1,k)); // P.z = k; // if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && // INTERP(solid(i+1,j,k), solid(i+1,j+1,k), P.y-j) > 0 ){ // P is a new vertex (not counted twice) // nw_pts(n_nw_pts++) = P; // N++; // } // } // } // else if ( A(i+1,j+1,k) == 0){ // pt.x = i+1; // pt.y = j+1; // pt.z = k; // val = EXTRAP(A, v, i+1,j,k, 5,pt); // // If extrapolated value gives a vertex // if ( (A(i+1,j,k)- v)*(val-v) < 0 ){ // P.x = i+1; // P.y = j + (A(i+1,j,k)-v)/(A(i+1,j,k)-val); // P.z = k; // if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && // INTERP(solid(i+1,j,k), solid(i+1,j+1,k), P.y-j) > 0 ){ // nw_pts(n_nw_pts++) = P; // N++; // } // } // } // } //3 if ((A(i+1,j+1,k)-v)*(A(i,j+1,k)-v) < 0 ) { if ( A(i+1,j+1,k) != 0 && A(i,j+1,k) != 0 ){ P.x = i + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i+1,j+1,k)); P.y = j+1; P.z = k; // Evaluate the function S at the new point if ( solid(i,j+1,k)*(1-P.x+i) + solid(i+1,j+1,k)*(P.x-i) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } /* else if ( A(i,j+1,k) == 0 ){ pt.x = i; pt.y = j+1; pt.z = k; val = EXTRAP(A, v, i+1,j+1,k, 1,pt); // If extrapolated value gives a vertex if ( (A(i+1,j+1,k)- v)*(val-v) < 0 ){ P.x = i + (val-v) / (val-A(i+1,j+1,k)); P.y = j+1; P.z = k; if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i,j+1,k), solid(i+1,j+1,k), P.x-i) > 0 ){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } else if ( A(i+1,j+1,k) == 0){ pt.x = i+1; pt.y = j+1; pt.z = k; val = EXTRAP(A, v, i,j+1,k, 4, pt); // If extrapolated value gives a vertex if ( (A(i,j+1,k)- v)*(val-v) < 0 ){ P.x = i + (A(i,j+1,k)-v) / (A(i,j+1,k)-val); P.y = j+1; P.z = k; if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i,j+1,k), solid(i+1,j+1,k), P.x-i) > 0 ){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } */ //4 if ((A(i,j+1,k)-v)*(A(i,j,k)-v) < 0 ) { if (A(i,j+1,k) != 0 && A(i,j,k) != 0 ){ P.x = i; P.y = j + (A(i,j,k)-v) / (A(i,j,k)-A(i,j+1,k)); P.z = k; // Evaluate the function S at the new point if ( solid(i,j,k)*(1-P.y+j) + solid(i,j+1,k)*(P.y-j) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } /* else if ( A(i,j+1,k) == 0 ){ pt.x = i; pt.y = j+1; pt.z = k; val = EXTRAP(A, v, i,j,k, 5,pt); // If extrapolated value gives a vertex if ( (A(i,j,k)- v)*(val-v) < 0 ){ P.x = i; P.y = j + (A(i,j,k)-v) / (A(i,j,k)-val); P.z = k; if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i,j,k), solid(i,j+1,k), P.y-j) > 0 ){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; } } } else if ( A(i,j,k) == 0){ pt.x = i; pt.y = j; pt.z = k; val = EXTRAP(A, v, i,j+1,k, 2,pt); // If extrapolated value gives a vertex if ( (A(i,j+1,k)- v)*(val-v) < 0 ){ P.x = i; P.y = j + (val-v) / (val-A(i,j+1,k)); P.z = k; if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i,j,k), solid(i,j+1,k), P.y-j) > 0){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } */ //5 if ((A(i,j,k)-v)*(A(i,j,k+1)-v) < 0 ) { if ( A(i,j,k) != 0 && A(i,j,k+1) != 0 ){ P.x = i; P.y = j; P.z = k + (A(i,j,k)-v) / (A(i,j,k)-A(i,j,k+1)); // Evaluate the function S at the new point if ( solid(i,j,k)*(1-P.z+k) + solid(i,j,k+1)*(P.z-k) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } /* else if ( A(i,j,k) == 0 ){ pt.x = i; pt.y = j; pt.z = k; val = EXTRAP(A, v, i,j,k+1, 3,pt); // If extrapolated value gives a vertex if ( (A(i,j,k+1)- v)*(val-v) < 0 ){ P.x = i; P.y = j; P.z = k + (val-v) / (val-A(i,j,k+1)); if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i,j,k), solid(i,j,k+1), P.z-k) > 0){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } else if ( A(i,j,k+1) == 0){ pt.x = i; pt.y = j; pt.z = k+1; val = EXTRAP(A, v, i,j,k, 6,pt); // If extrapolated value gives a vertex if ( (A(i,j,k)- v)*(val-v) < 0 ){ P.x = i; P.y = j; P.z = k + (A(i,j,k)-v) / (A(i,j,k)-val); if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i,j,k), solid(i,j,k+1), P.z-k) > 0){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } */ //6 if ((A(i+1,j,k)-v)*(A(i+1,j,k+1)-v) < 0 ) { if ( A(i+1,j,k) != 0 && A(i+1,j,k+1) != 0 ){ P.x = i+1; P.y = j; P.z = k + (A(i+1,j,k)-v) / (A(i+1,j,k)-A(i+1,j,k+1)); // Evaluate the function S at the new point if ( solid(i+1,j,k)*(1-P.z+k) + solid(i+1,j,k+1)*(P.z-k) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } /* else if ( A(i+1,j,k) == 0 ){ pt.x = i+1; pt.y = j; pt.z = k; val = EXTRAP(A, v, i+1,j,k+1, 3,pt); // If extrapolated value gives a vertex if ( (A(i+1,j,k+1)- v)*(val-v) < 0 ){ P.x = i+1; P.y = j; P.z = k + (val-v) / (val-A(i+1,j,k+1)); if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i+1,j,k), solid(i+1,j,k+1), P.z-k) > 0){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } else if ( A(i+1,j,k+1) == 0){ pt.x = i+1; pt.y = j; pt.z = k+1; val = EXTRAP(A, v, i+1,j,k, 6,pt); // If extrapolated value gives a vertex if ( (A(i+1,j,k)- v)*(val-v) < 0 ){ P.x = i+1; P.y = j; P.z = k + (A(i+1,j,k)-v) / (A(i+1,j,k)-val); if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i+1,j,k), solid(i+1,j,k+1), P.z-k) > 0){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } */ //7 if ((A(i+1,j+1,k)-v)*(A(i+1,j+1,k+1)-v) < 0 ) { if ( A(i+1,j+1,k) != 0 && A(i+1,j+1,k+1) != 0 ){ P.x = i+1; P.y = j+1; P.z = k + (A(i+1,j+1,k)-v) / (A(i+1,j+1,k)-A(i+1,j+1,k+1)); // Evaluate the function S at the new point if ( solid(i+1,j+1,k)*(1-P.z+k) + solid(i+1,j+1,k+1)*(P.z-k) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } /* else if ( A(i+1,j+1,k) == 0 ){ pt.x = i+1; pt.y = j+1; pt.z = k; val = EXTRAP(A, v, i+1,j+1,k+1, 3,pt); // If extrapolated value gives a vertex if ( (A(i+1,j+1,k+1)- v)*(val-v) < 0 ){ P.x = i+1; P.y = j+1; P.z = k + (val-v) / (val-A(i+1,j+1,k+1)); if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i+1,j+1,k), solid(i+1,j+1,k+1), P.z-k) > 0 ){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } else if ( A(i+1,j+1,k+1) == 0){ pt.x = i+1; pt.y = j+1; pt.z = k+1; val = EXTRAP(A, v, i+1,j+1,k, 6,pt); // If extrapolated value gives a vertex if ( (A(i+1,j+1,k)- v)*(val-v) < 0 ){ P.x = i+1; P.y = j+1; P.z = k + (A(i+1,j+1,k)-v) / (A(i+1,j+1,k)-val); if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i+1,j+1,k), solid(i+1,j+1,k+1), P.z-k) > 0 ){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } */ //8 if ((A(i,j+1,k)-v)*(A(i,j+1,k+1)-v) < 0 ) { if ( A(i,j+1,k) != 0 && A(i,j+1,k+1) != 0 ){ P.x = i; P.y = j+1; P.z = k + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i,j+1,k+1)); // Evaluate the function S at the new point if ( solid(i,j+1,k)*(1-P.z+k) + solid(i,j+1,k+1)*(P.z-k) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } /* else if ( A(i,j+1,k) == 0 ){ pt.x = i; pt.y = j+1; pt.z = k; val = EXTRAP(A, v, i,j+1,k+1, 3,pt); // If extrapolated value gives a vertex if ( (A(i,j+1,k+1)- v)*(val-v) < 0 ){ P.x = i; P.y = j+1; P.z = k + (val-v) / (val-A(i,j+1,k+1)); if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i,j+1,k), solid(i,j+1,k+1), P.z-k) > 0 ){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } else if ( A(i,j+1,k+1) == 0){ pt.x = i; pt.y = j+1; pt.z = k+1; val = EXTRAP(A, v, i,j+1,k, 6,pt); // If extrapolated value gives a vertex if ( (A(i,j+1,k)- v)*(val-v) < 0 ){ P.x = i; P.y = j+1; P.z = k + (A(i,j+1,k)-v) / (A(i,j+1,k)-val); if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i,j+1,k), solid(i,j+1,k+1), P.z-k) > 0 ){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } */ //9 if ((A(i,j,k+1)-v)*(A(i+1,j,k+1)-v) < 0 ) { if ( A(i,j,k+1) != 0 && A(i+1,j,k+1) != 0 ){ P.x = i + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i+1,j,k+1)); P.y = j; P.z = k+1; // Evaluate the function S at the new point if ( solid(i,j,k+1)*(1-P.x+i) + solid(i+1,j,k+1)*(P.x-i) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } /* else if ( A(i,j,k+1) == 0 ){ pt.x = i; pt.y = j; pt.z = k+1; val = EXTRAP(A, v, i+1,j,k+1, 1,pt); // If extrapolated value gives a vertex if ( (A(i+1,j,k+1)- v)*(val-v) < 0 ){ P.x = i + (val-v) / (val-A(i+1,j,k+1)); P.y = j; P.z = k+1; if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i,j,k+1), solid(i+1,j,k+1), P.x-i) > 0 ){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } else if ( A(i+1,j,k+1) == 0){ pt.x = i+1; pt.y = j; pt.z = k+1; val = EXTRAP(A, v, i,j,k+1, 4,pt); // If extrapolated value gives a vertex if ( (A(i,j,k+1)- v)*(val-v) < 0 ){ P.x = i + (A(i,j,k+1)-v) / (A(i,j,k+1)-val); P.y = j; P.z = k+1; if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i,j,k+1), solid(i+1,j,k+1), P.x-i) > 0){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } */ //10 if ((A(i+1,j,k+1)-v)*(A(i+1,j+1,k+1)-v) < 0 ) { if ( A(i+1,j,k+1) != 0 && A(i+1,j+1,k+1) != 0 ){ P.x = i+1; P.y = j + (A(i+1,j,k+1)-v) / (A(i+1,j,k+1)-A(i+1,j+1,k+1)); P.z = k+1; // Evaluate the function S at the new point if ( solid(i+1,j,k+1)*(1-P.y+j) + solid(i+1,j+1,k+1)*(P.y-j) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } /* else if ( A(i+1,j,k+1) == 0 ){ pt.x = i+1; pt.y = j; pt.z = k+1; val = EXTRAP(A, v, i+1,j+1,k+1, 2,pt); // If extrapolated value gives a vertex if ( (A(i+1,j+1,k+1)- v)*(val-v) < 0 ){ P.x = i+1; P.y = j + (val-v) / (val-A(i+1,j+1,k+1)); P.z = k+1; if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i+1,j,k+1), solid(i+1,j+1,k+1), P.y-j) > 0){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } else if ( A(i+1,j+1,k+1) == 0){ pt.x = i+1; pt.y = j+1; pt.z = k+1; val = EXTRAP(A, v, i+1,j,k+1, 5,pt); // If extrapolated value gives a vertex if ( (A(i+1,j,k+1)- v)*(val-v) < 0 ){ P.x = i+1; P.y = j + (A(i+1,j,k+1)-v) / (A(i+1,j,k+1)-val); P.z = k+1; if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i+1,j,k+1), solid(i+1,j+1,k+1), P.y-j) > 0){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } */ //11 if ((A(i+1,j+1,k+1)-v)*(A(i,j+1,k+1)-v) < 0 ) { if ( A(i+1,j+1,k+1) != 0 && A(i,j+1,k+1) != 0 ){ P.x = i+(A(i,j+1,k+1)-v) / (A(i,j+1,k+1)-A(i+1,j+1,k+1)); P.y = j+1; P.z = k+1; // Evaluate the function S at the new point if ( solid(i,j+1,k+1)*(1-P.x+i) + solid(i+1,j+1,k+1)*(P.x-i) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } /* else if ( A(i+1,j+1,k+1) == 0 ){ pt.x = i+1; pt.y = j+1; pt.z = k+1; val = EXTRAP(A, v, i,j+1,k+1, 4,pt); // If extrapolated value gives a vertex if ( (A(i,j+1,k+1)- v)*(val-v) < 0 ){ P.x = i+(A(i,j+1,k+1)-v) / (A(i,j+1,k+1)-val); P.y = j+1; P.z = k+1; if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i,j+1,k+1), solid(i+1,j+1,k+1), P.x-i) > 0){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } else if ( A(i,j+1,k+1) == 0){ pt.x = i; pt.y = j+1; pt.z = k+1; val = EXTRAP(A, v, i+1,j+1,k+1, 1,pt); // If extrapolated value gives a vertex if ( (A(i+1,j+1,k+1)- v)*(val-v) < 0 ){ P.x = i+(val-v) / (val-A(i+1,j+1,k+1)); P.y = j+1; P.z = k+1; if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1 && INTERP(solid(i,j+1,k+1), solid(i+1,j+1,k+1), P.x-i) > 0){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } */ //12 if ((A(i,j+1,k+1)-v)*(A(i,j,k+1)-v) < 0 ) { if ( A(i,j+1,k+1) != 0 && A(i,j,k+1) != 0 ){ P.x = i; P.y = j + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i,j+1,k+1)); P.z = k+1; // Evaluate the function S at the new point if ( solid(i,j,k+1)*(1-P.y+j) + solid(i,j+1,k+1)*(P.y-j) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } // sort vertices so that they are connected to "neighbors" // DTMatlabDataFile("/tmp/Dump.mat",DTFile::NewReadWrite); // n_nw_pts = number of vertices in total (location n_nw_pts is first unfilled position) // n = number of vertices in this grid cell for (m = n_nw_pts-N; m < n_nw_pts-2; m++) { for (o = m+2; o < n_nw_pts-1; o++) { if (ShareSide(nw_pts(m), nw_pts(o)) == 1) { PlaceHolder = nw_pts(m+1); nw_pts(m+1) = nw_pts(o); nw_pts(o) = PlaceHolder; } } // make sure other neighbor of vertex 1 is in last spot if (m == n_nw_pts-N){ for (p = m+2; p < n_nw_pts-1; p++){ if (ShareSide(nw_pts(m), nw_pts(p)) == 1){ PlaceHolder = nw_pts(n_nw_pts-1); nw_pts(n_nw_pts-1) = nw_pts(p); nw_pts(p) = PlaceHolder; } } } if ( ShareSide(nw_pts(n_nw_pts-2), nw_pts(n_nw_pts-3)) != 1 ){ if (ShareSide( nw_pts(n_nw_pts-3), nw_pts(n_nw_pts-1)) == 1 && ShareSide( nw_pts(n_nw_pts-N),nw_pts(n_nw_pts-2)) == 1 ){ PlaceHolder = nw_pts(n_nw_pts-2); nw_pts(n_nw_pts-2) = nw_pts(n_nw_pts-1); nw_pts(n_nw_pts-1) = PlaceHolder; } } if ( ShareSide(nw_pts(n_nw_pts-1), nw_pts(n_nw_pts-2)) != 1 ){ if (ShareSide( nw_pts(n_nw_pts-3), nw_pts(n_nw_pts-1)) == 1 && ShareSide(nw_pts(n_nw_pts-4),nw_pts(n_nw_pts-2)) == 1 ){ PlaceHolder = nw_pts(n_nw_pts-3); nw_pts(n_nw_pts-3) = nw_pts(n_nw_pts-2); nw_pts(n_nw_pts-2) = PlaceHolder; } if (ShareSide( nw_pts(n_nw_pts-N+1), nw_pts(n_nw_pts-3)) == 1 && ShareSide(nw_pts(n_nw_pts-1),nw_pts(n_nw_pts-N+1)) == 1 ){ PlaceHolder = nw_pts(n_nw_pts-2); nw_pts(n_nw_pts-2) = nw_pts(n_nw_pts-N+1); nw_pts(n_nw_pts-N+1) = PlaceHolder; } } if ( ShareSide(nw_pts(n_nw_pts-N), nw_pts(n_nw_pts-N+1)) != 1 ){ if (ShareSide( nw_pts(n_nw_pts-N), nw_pts(n_nw_pts-2)) == 1 && ShareSide(nw_pts(n_nw_pts-1), nw_pts(n_nw_pts-N+1)) == 1){ PlaceHolder = nw_pts(n_nw_pts-1); nw_pts(n_nw_pts-1) = nw_pts(n_nw_pts-N); nw_pts(n_nw_pts-N) = PlaceHolder; } } } // * * * ESTABLISH TRIANGLE CONNECTIONS * * * for (p=n_nw_pts-N+2; p &nw_pts, int &n_nw_pts, IntArray &nw_tris, int &n_nw_tris, DTMutableList &local_nws_pts, int &n_local_nws_pts) { // FIND THE POINTS ON THE nw SURFACE THAT ARE ON THE EDGE (COMMON LINE WITH SOLID PHASE) // function A is the fluid data padded (so that it has values inside the solid phase) int N = 0; // n will be the number of vertices in this grid cell only Point P; Point temp; int p; int q; int r; // Add common line points to nw_pts for (p=0;p 0 ){ // This point is in the fluid region nw_pts(n_nw_pts++) = P; N++; } } } // 2 if ((A(i+1,j,k)-v)*(A(i+1,j+1,k)-v) < 0) { if ( A(i+1,j,k) != 0 && A(i+1,j+1,k) != 0 ){ P.x = i+1; P.y = j + (A(i+1,j,k)-v)/(A(i+1,j,k)-A(i+1,j+1,k)); P.z = k; // Evaluate the function S at the new point if ( solid(i+1,j,k)*(1-P.y+j) + solid(i+1,j+1,k)*(P.y-j) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } //3 if ((A(i+1,j+1,k)-v)*(A(i,j+1,k)-v) < 0 ) { if ( A(i+1,j+1,k) != 0 && A(i,j+1,k) != 0 ){ P.x = i + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i+1,j+1,k)); P.y = j+1; P.z = k; // Evaluate the function S at the new point if ( solid(i,j+1,k)*(1-P.x+i) + solid(i+1,j+1,k)*(P.x-i) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } //4 if ((A(i,j+1,k)-v)*(A(i,j,k)-v) < 0 ) { if (A(i,j+1,k) != 0 && A(i,j,k) != 0 ){ P.x = i; P.y = j + (A(i,j,k)-v) / (A(i,j,k)-A(i,j+1,k)); P.z = k; // Evaluate the function S at the new point if ( solid(i,j,k)*(1-P.y+j) + solid(i,j+1,k)*(P.y-j) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } //5 if ((A(i,j,k)-v)*(A(i,j,k+1)-v) < 0 ) { if ( A(i,j,k) != 0 && A(i,j,k+1) != 0 ){ P.x = i; P.y = j; P.z = k + (A(i,j,k)-v) / (A(i,j,k)-A(i,j,k+1)); // Evaluate the function S at the new point if ( solid(i,j,k)*(1-P.z+k) + solid(i,j,k+1)*(P.z-k) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ // P is a new vertex (not counted twice) nw_pts(n_nw_pts++) = P; N++; } } } } //6 if ((A(i+1,j,k)-v)*(A(i+1,j,k+1)-v) < 0 ) { if ( A(i+1,j,k) != 0 && A(i+1,j,k+1) != 0 ){ P.x = i+1; P.y = j; P.z = k + (A(i+1,j,k)-v) / (A(i+1,j,k)-A(i+1,j,k+1)); // Evaluate the function S at the new point if ( solid(i+1,j,k)*(1-P.z+k) + solid(i+1,j,k+1)*(P.z-k) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } //7 if ((A(i+1,j+1,k)-v)*(A(i+1,j+1,k+1)-v) < 0 ) { if ( A(i+1,j+1,k) != 0 && A(i+1,j+1,k+1) != 0 ){ P.x = i+1; P.y = j+1; P.z = k + (A(i+1,j+1,k)-v) / (A(i+1,j+1,k)-A(i+1,j+1,k+1)); // Evaluate the function S at the new point if ( solid(i+1,j+1,k)*(1-P.z+k) + solid(i+1,j+1,k+1)*(P.z-k) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } //8 if ((A(i,j+1,k)-v)*(A(i,j+1,k+1)-v) < 0 ) { if ( A(i,j+1,k) != 0 && A(i,j+1,k+1) != 0 ){ P.x = i; P.y = j+1; P.z = k + (A(i,j+1,k)-v) / (A(i,j+1,k)-A(i,j+1,k+1)); // Evaluate the function S at the new point if ( solid(i,j+1,k)*(1-P.z+k) + solid(i,j+1,k+1)*(P.z-k) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } //9 if ((A(i,j,k+1)-v)*(A(i+1,j,k+1)-v) < 0 ) { if ( A(i,j,k+1) != 0 && A(i+1,j,k+1) != 0 ){ P.x = i + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i+1,j,k+1)); P.y = j; P.z = k+1; // Evaluate the function S at the new point if ( solid(i,j,k+1)*(1-P.x+i) + solid(i+1,j,k+1)*(P.x-i) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } //10 if ((A(i+1,j,k+1)-v)*(A(i+1,j+1,k+1)-v) < 0 ) { if ( A(i+1,j,k+1) != 0 && A(i+1,j+1,k+1) != 0 ){ P.x = i+1; P.y = j + (A(i+1,j,k+1)-v) / (A(i+1,j,k+1)-A(i+1,j+1,k+1)); P.z = k+1; // Evaluate the function S at the new point if ( solid(i+1,j,k+1)*(1-P.y+j) + solid(i+1,j+1,k+1)*(P.y-j) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } //11 if ((A(i+1,j+1,k+1)-v)*(A(i,j+1,k+1)-v) < 0 ) { if ( A(i+1,j+1,k+1) != 0 && A(i,j+1,k+1) != 0 ){ P.x = i+(A(i,j+1,k+1)-v) / (A(i,j+1,k+1)-A(i+1,j+1,k+1)); P.y = j+1; P.z = k+1; // Evaluate the function S at the new point if ( solid(i,j+1,k+1)*(1-P.x+i) + solid(i+1,j+1,k+1)*(P.x-i) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } //12 if ((A(i,j+1,k+1)-v)*(A(i,j,k+1)-v) < 0 ) { if ( A(i,j+1,k+1) != 0 && A(i,j,k+1) != 0 ){ P.x = i; P.y = j + (A(i,j,k+1)-v) / (A(i,j,k+1)-A(i,j+1,k+1)); P.z = k+1; // Evaluate the function S at the new point if ( solid(i,j,k+1)*(1-P.y+j) + solid(i,j+1,k+1)*(P.y-j) > 0 ){ // This point is in the fluid region if (vertexcheck(P, N, n_nw_pts, nw_pts) == 1){ nw_pts(n_nw_pts++) = P; N++; } } } } //////////////////////////////////////////////// ////// SORT VERTICES SO THAT THEY CONNECT ////// ////// TO ALL "NEIGHBORS" ////// //////////////////////////////////////////////// // First common line point should connect to last MC point for (q=n_nw_pts-N; q vF) int cube[8][3] = {{0,0,0},{1,0,0},{0,1,0},{1,1,0},{0,0,1},{1,0,1},{0,1,1},{1,1,1}}; // cube corners // int count_in=0,count_out=0; // int nodx,nody,nodz; // initialize lists for vertices for surfaces, common line DTMutableList nw_pts(20); DTMutableList ns_pts(20); DTMutableList ws_pts(20); DTMutableList nws_pts(20); // initialize triangle lists for surfaces IntArray nw_tris(3,20); IntArray ns_tris(3,20); IntArray ws_tris(3,20); // initialize list for line segments IntArray nws_seg(2,20); DTMutableList tmp(20); // IntArray store; int i,j,k,p,q,r; int n_nw_pts=0,n_ns_pts=0,n_ws_pts=0,n_nws_pts=0, map=0; int n_nw_tris=0, n_ns_tris=0, n_ws_tris=0, n_nws_seg=0; double s,s1,s2,s3; // Triangle sides (lengths) Point A,B,C,P; // double area; // Initialize arrays for local solid surface DTMutableList local_sol_pts(20); int n_local_sol_pts = 0; IntArray local_sol_tris(3,18); int n_local_sol_tris; DoubleArray values(20); DTMutableList local_nws_pts(20); int n_local_nws_pts; int n_nw_tris_beg, n_ns_tris_beg, n_ws_tris_beg; int c; int newton_steps = 0; // double blob_volume; /* **************************************************************** RUN PMMC ON EACH BLOB ****************************************************************** */ // printf("Running the PMMC Algorithm \n"); // printf("The number of blobs is %i \n",nblobs); // Store beginning points for surfaces for blob p n_nw_tris_beg = n_nw_tris; n_ns_tris_beg = n_ns_tris; n_ws_tris_beg = n_ws_tris; // n_nws_seg_beg = n_nws_seg; // Loop over all cubes blob_volume = 0; // Initialize the volume for blob a to zero for (c=start;c -1){ blob_volume += 0.125; } } */ for (p=0;p<8;p++){ if ( F(i+cube[p][0],j+cube[p][1],k+cube[p][2]) > 0 && S(i+cube[p][0],j+cube[p][1],k+cube[p][2]) > 0 ){ blob_volume += 0.125; } } // Run PMMC n_local_sol_tris = 0; n_local_sol_pts = 0; n_local_nws_pts = 0; // if there is a solid phase interface in the grid cell if (Interface(S,vS,i,j,k) == 1){ ///////////////////////////////////////// /// CONSTRUCT THE LOCAL SOLID SURFACE /// ///////////////////////////////////////// // find the local solid surface SOL_SURF(S,0,F,vF,i,j,k, Nx,Ny,Nz,local_sol_pts,n_local_sol_pts, local_sol_tris,n_local_sol_tris,values); ///////////////////////////////////////// //////// TRIM THE SOLID SURFACE ///////// ///////////////////////////////////////// TRIM(local_sol_pts, n_local_sol_pts, vF,local_sol_tris, n_local_sol_tris, ns_pts, n_ns_pts, ns_tris, n_ns_tris, ws_pts, n_ws_pts, ws_tris, n_ws_tris, values, local_nws_pts, n_local_nws_pts, F, S, i, j, k, newton_steps); ///////////////////////////////////////// //////// WRITE COMMON LINE POINTS /////// //////// TO MAIN ARRAYS /////// ///////////////////////////////////////// map = n_nws_pts; for (p=0; p < n_local_nws_pts; p++){ nws_pts(n_nws_pts++) = local_nws_pts(p); } for (q=0; q < n_local_nws_pts-1; q++){ nws_seg(0,n_nws_seg) = map+q; nws_seg(1,n_nws_seg) = map+q+1; n_nws_seg++; } ///////////////////////////////////////// ////// CONSTRUCT THE nw SURFACE ///////// ///////////////////////////////////////// if ( n_local_nws_pts > 0){ EDGE(F, vF, S, i,j,k, Nx, Ny, Nz, nw_pts, n_nw_pts, nw_tris, n_nw_tris, local_nws_pts, n_local_nws_pts); } else { MC(F, vF, S, i,j,k, nw_pts, n_nw_pts, nw_tris, n_nw_tris); } } ///////////////////////////////////////// ////// CONSTRUCT THE nw SURFACE ///////// ///////////////////////////////////////// else if (Fluid_Interface(F,S,vF,i,j,k) == 1){ MC(F, vF, S, i,j,k, nw_pts, n_nw_pts, nw_tris, n_nw_tris); } //******END OF BLOB PMMC********************************************* //******************************************************************* // Compute the Interfacial Areas, Common Line length for blob p // nw surface for (r=n_nw_tris_beg;r