// Sequential blob analysis // Reads parallel simulation data and performs connectivity analysis // and averaging on a blob-by-blob basis // James E. McClure 2014 #include #include #include "pmmc.h" //#include "Domain.h" #define NUM_AVERAGES 30 using namespace std; inline void ReadCheckpoint(char *FILENAME, double *cDen, double *cDistEven, double *cDistOdd, int N) { int q,n; double value; ifstream File(FILENAME,ios::binary); for (n=0; n> nprocx; domain >> nprocy; domain >> nprocz; domain >> nx; domain >> ny; domain >> nz; domain >> nspheres; domain >> Lx; domain >> Ly; domain >> Lz; //....................................................................... nx+=2; ny+=2; nz+=2; nprocs = nprocx*nprocy*nprocz; printf("Number of MPI ranks: %i \n", nprocs); Nx = (nx-2)*nprocx+2; Ny = (ny-2)*nprocy+2; Nz = (nz-2)*nprocz+2; printf("Full domain size: %i x %i x %i \n", Nx,Ny,Nz); DoubleArray Phase(Nx,Ny,Nz); DoubleArray SignDist(Nx,Ny,Nz); DoubleArray Press(Nx,Ny,Nz); DoubleArray Vel_x(Nx,Ny,Nz); // Velocity DoubleArray Vel_y(Nx,Ny,Nz); DoubleArray Vel_z(Nx,Ny,Nz); DoubleArray dPdt(Nx,Ny,Nz); // Filenames used char LocalRankString[8]; char LocalRankFilename[40]; char LocalRestartFile[40]; char BaseFilename[20]; char tmpstr[10]; sprintf(BaseFilename,"%s","dPdt."); int proc,iglobal,kglobal,jglobal; double * Temp; Temp = new double[nx*ny*nz]; for (k=0; k 0.0){ Press(i,j,k) = 0.34; } else { Press(i,j,k) = 0.32; } } } } #else // read the files and populate main arrays for ( kproc=0; kproc fluid_isovalue) 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; 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); // 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; DoubleArray CubeValues(2,2,2); DoubleArray Values(20); DoubleArray ContactAngle(20); DoubleArray Curvature(20); DoubleArray DistValues(20); DoubleArray InterfaceSpeed(20); DoubleArray NormalVector(60); DoubleArray van(3); DoubleArray vaw(3); DoubleArray vawn(3); DoubleArray Gwn(6); DoubleArray Gns(6); DoubleArray Gws(6); //........................................................................... printf("Execute blob identification algorithm... \n"); /* **************************************************************** IDENTIFY ALL BLOBS: F > vF, S > vS ****************************************************************** */ // Find blob domains, number of blobs int nblobs = 0; // number of blobs int ncubes = 0; // total number of nodes in any blob int N = (Nx-1)*(Ny-1)*(Nz-1); // total number of nodes IntArray blobs(3,N); // store indices for blobs (cubes) IntArray temp(3,N); // temporary storage array IntArray b(50); // number of nodes in each blob /* std::vector BlobList; BlobList.reserve[10000]; std::vector TempBlobList; TempBlobList.reserve[10000]; */ double vF=0.0; double vS=0.0; double trimdist=1.0; // Loop over z=0 first -> blobs attached to this end considered "connected" for LB simulation i=0; int number=0; for (k=0;k<1;k++){ for (j=0;j vF ){ if ( SignDist(i,j,k) > vS ){ // node i,j,k is in the porespace number = number+ComputeBlob(blobs,nblobs,ncubes,LocalBlobID,Phase,SignDist,vF,vS,i,j,k,temp); } } } } // Specify the blob on the z axis if (ncubes > 0){ b(nblobs) = number; // BlobList.push_back[number]; printf("Number of non-wetting phase blobs is: %i \n",nblobs-1); nblobs++; } for (k=0;k vF ){ if ( SignDist(i,j,k) > vS ){ // node i,j,k is in the porespace b(nblobs) = ComputeBlob(blobs,nblobs,ncubes,LocalBlobID,Phase,SignDist,vF,vS,i,j,k,temp); nblobs++; } } } // Otherwise, this point has already been assigned - ignore // Make sure list blob_nodes is large enough if ( nblobs > b.Length-1){ printf("Increasing size of blob list \n"); b = IncreaseSize(b,b.Length); } } } } // Go over all cubes again -> add any that do not contain nw phase bool add=1; // Set to false if any corners contain nw-phase ( F > 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; for (k=0;k -1 ){ // corner occupied by nw-phase -> do not add add = 0; } } if ( add == 1 ){ blobs(0,ncubes) = i; blobs(1,ncubes) = j; blobs(2,ncubes) = k; ncubes++; count_in++; } else { count_out++; } } } } b(nblobs) = count_in; nblobs++; DoubleArray BlobAverages(NUM_AVERAGES,nblobs); /* **************************************************************** RUN TCAT AVERAGING ON EACH BLOB ****************************************************************** */ int n_nw_tris_beg, n_ns_tris_beg, n_ws_tris_beg, n_nws_seg_beg; int start=0,finish; int a,c; int newton_steps = 0; double blob_volume; printf("-----------------------------------------------\n"); printf("Computing TCAT averages based on connectivity \n"); printf("The number of non-wetting phase features is %i \n",nblobs-1); printf("-----------------------------------------------\n"); // Wetting phase averages assume global connectivity vol_w = 0.0; aws = 0.0; vaw(0) = vaw(1) = vaw(2) = 0.0; Gws(0) = Gws(1) = Gws(2) = 0.0; Gws(3) = Gws(4) = Gws(5) = 0.0; // Don't compute the last blob unless specified // the last blob is the entire wetting phase nblobs -=1; #ifdef WP nblobs+=1; #endif for (a=0;a 0 ){ // 1-D index for this cube corner n = i+cube[p][0] + (j+cube[p][1])*Nx + (k+cube[p][2])*Nx*Ny; // Compute the non-wetting phase volume contribution if ( Phase(i+cube[p][0],j+cube[p][1],k+cube[p][2]) > 0 ) nwp_volume += 0.125; // volume averages over the non-wetting phase if ( Phase(i+cube[p][0],j+cube[p][1],k+cube[p][2]) > 0.99 ){ // volume the excludes the interfacial region vol_n += 0.125; // pressure pan += 0.125*Press.data[n]; // velocity van(0) += 0.125*Vel_x.data[n]; van(1) += 0.125*Vel_y.data[n]; van(2) += 0.125*Vel_z.data[n]; } // volume averages over the wetting phase if ( Phase(i+cube[p][0],j+cube[p][1],k+cube[p][2]) < -0.99 ){ // volume the excludes the interfacial region vol_w += 0.125; // pressure paw += 0.125*Press.data[n]; // velocity vaw(0) += 0.125*Vel_x.data[n]; vaw(1) += 0.125*Vel_y.data[n]; vaw(2) += 0.125*Vel_z.data[n]; } } } // Interface and common curve averages n_local_sol_tris = 0; n_local_sol_pts = 0; n_local_nws_pts = 0; //........................................................................... // Construct the interfaces and common curve pmmc_ConstructLocalCube(SignDist, Phase, vS, vF, nw_pts, nw_tris, values, ns_pts, ns_tris, ws_pts, ws_tris, local_nws_pts, nws_pts, nws_seg, local_sol_pts, local_sol_tris, n_local_sol_tris, n_local_sol_pts, n_nw_pts, n_nw_tris, n_ws_pts, n_ws_tris, n_ns_tris, n_ns_pts, n_local_nws_pts, n_nws_pts, n_nws_seg, i, j, k, Nx, Ny, Nz); // Integrate the contact angle efawns += pmmc_CubeContactAngle(CubeValues,Values,Phase_x,Phase_y,Phase_z,SignDist_x,SignDist_y,SignDist_z, local_nws_pts,i,j,k,n_local_nws_pts); // Integrate the mean curvature Jwn += pmmc_CubeSurfaceInterpValue(CubeValues,MeanCurvature,nw_pts,nw_tris,Values,i,j,k,n_nw_pts,n_nw_tris); Kwn += pmmc_CubeSurfaceInterpValue(CubeValues,GaussCurvature,nw_pts,nw_tris,Values,i,j,k,n_nw_pts,n_nw_tris); // Integrate the trimmed mean curvature (hard-coded to use a distance of 4 pixels) pmmc_CubeTrimSurfaceInterpValues(CubeValues,MeanCurvature,SignDist,nw_pts,nw_tris,Values,DistValues, i,j,k,n_nw_pts,n_nw_tris,trimdist,trawn,trJwn); pmmc_CubeTrimSurfaceInterpInverseValues(CubeValues,MeanCurvature,SignDist,nw_pts,nw_tris,Values,DistValues, i,j,k,n_nw_pts,n_nw_tris,trimdist,dummy,trRwn); // Compute the normal speed of the interface pmmc_InterfaceSpeed(dPdt, Phase_x, Phase_y, Phase_z, CubeValues, nw_pts, nw_tris, NormalVector, InterfaceSpeed, vawn, i, j, k, n_nw_pts, n_nw_tris); As += pmmc_CubeSurfaceArea(local_sol_pts,local_sol_tris,n_local_sol_tris); // Compute the surface orientation and the interfacial area awn += pmmc_CubeSurfaceOrientation(Gwn,nw_pts,nw_tris,n_nw_tris); ans += pmmc_CubeSurfaceOrientation(Gns,ns_pts,ns_tris,n_ns_tris); aws += pmmc_CubeSurfaceOrientation(Gws,ws_pts,ws_tris,n_ws_tris); lwns += pmmc_CubeCurveLength(local_nws_pts,n_local_nws_pts); //........................................................................... //******************************************************************* // Reset the triangle counts to zero n_nw_pts=0,n_ns_pts=0,n_ws_pts=0,n_nws_pts=0, map=0; n_nw_tris=0, n_ns_tris=0, n_ws_tris=0, n_nws_seg=0; 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; //******************************************************************* } start = finish; if (vol_n > 0.0){ pan /= vol_n; for (i=0;i<3;i++) van(i) /= vol_n; } if (awn > 0.0){ Jwn /= awn; Kwn /= awn; for (i=0;i<3;i++) vawn(i) /= awn; for (i=0;i<6;i++) Gwn(i) /= awn; } // if (lwns > 0.0){ // efawns /= lwns; // } if (ans > 0.0){ for (i=0;i<6;i++) Gns(i) /= ans; } if (trawn > 0.0){ trJwn /= trawn; } BlobAverages(0,a) = nwp_volume; BlobAverages(1,a) = pan; BlobAverages(2,a) = awn; BlobAverages(3,a) = ans; BlobAverages(4,a) = Jwn; BlobAverages(5,a) = Kwn; BlobAverages(6,a) = lwns; BlobAverages(7,a) = efawns; BlobAverages(8,a) = van(0); BlobAverages(9,a) = van(1); BlobAverages(10,a) = van(2); BlobAverages(11,a) = vawn(0); BlobAverages(12,a) = vawn(1); BlobAverages(13,a) = vawn(2); BlobAverages(14,a) = Gwn(0); BlobAverages(15,a) = Gwn(1); BlobAverages(16,a) = Gwn(2); BlobAverages(17,a) = Gwn(3); BlobAverages(18,a) = Gwn(4); BlobAverages(19,a) = Gwn(5); BlobAverages(20,a) = Gns(0); BlobAverages(21,a) = Gns(1); BlobAverages(22,a) = Gns(2); BlobAverages(23,a) = Gns(3); BlobAverages(24,a) = Gns(4); BlobAverages(25,a) = Gns(5); BlobAverages(26,a) = trawn; BlobAverages(27,a) = trJwn; BlobAverages(28,a) = trRwn; printf("Computed TCAT averages for feature = %i \n", a); } // End of the blob loop printf("-----------------------------------------------\n"); printf("Sorting the blobs based on volume \n"); printf("-----------------------------------------------\n"); int TempLabel,aa,bb; double TempValue; IntArray OldLabel(nblobs); for (a=0; a -1){ TempLabel = NewLabel(LocalBlobID(i,j,k)); LocalBlobID(i,j,k) = TempLabel; } } } } printf("-----------------------------------------------\n"); FILE *BLOBLOG= fopen("blobs.tcat","a"); for (a=0; a