/* * Pre-processor to generate signed distance function from segmented data * segmented data should be stored in a raw binary file as 1-byte integer (type char) * will output distance functions for phases */ #include #include #include #include #include #include #include "common/Array.h" #include "common/Domain.h" #include "analysis/distance.h" #include "analysis/morphology.h" //************************************************************************* // Morpohologica pre-processor // Initialize phase distribution using morphological approach // Signed distance function is used to determine fluid configuration //************************************************************************* int main(int argc, char **argv) { // Initialize MPI int rank, nprocs; MPI_Init(&argc,&argv); MPI_Comm comm = MPI_COMM_WORLD; MPI_Comm_rank(comm,&rank); MPI_Comm_size(comm,&nprocs); { //....................................................................... // Reading the domain information file //....................................................................... int n, nx, ny, nz; char LocalRankFilename[40]; string filename; double SW; if (argc > 1){ filename=argv[1]; //Rcrit_new=0.f; //SW=strtod(argv[2],NULL); } else ERROR("No input database provided\n"); // read the input database auto db = std::make_shared( filename ); auto domain_db = db->getDatabase( "Domain" ); // Read domain parameters auto size = domain_db->getVector( "n" ); auto nproc = domain_db->getVector( "nproc" ); auto ReadValues = domain_db->getVector( "ReadValues" ); auto WriteValues = domain_db->getVector( "WriteValues" ); SW = domain_db->getScalar("Sw"); auto READFILE = domain_db->getScalar( "Filename" ); // Generate the NWP configuration //if (rank==0) printf("Initializing morphological distribution with critical radius %f \n", Rcrit); if (rank==0) printf("Performing morphological imbibition with target saturation %f \n", SW); // GenerateResidual(id,nx,ny,nz,Saturation); nx = size[0]; ny = size[1]; nz = size[2]; int N = (nx+2)*(ny+2)*(nz+2); std::shared_ptr Dm (new Domain(domain_db,comm)); std::shared_ptr Mask (new Domain(domain_db,comm)); // std::shared_ptr Dm (new Domain(nx,ny,nz,rank,nprocx,nprocy,nprocz,Lx,Ly,Lz,BC)); for (n=0; nid[n]=1; Dm->CommInit(); signed char *id; id = new signed char [N]; signed char *id_connected; id_connected = new signed char [N]; Mask->Decomp(READFILE); Mask->CommInit(); nx+=2; ny+=2; nz+=2; // Generate the signed distance map // Initialize the domain and communication Array id_solid(nx,ny,nz); Array phase_label(nx,ny,nz); DoubleArray SignDist(nx,ny,nz); DoubleArray phase(nx,ny,nz); for (int k=0; kid[n]; if (id[n] == 1){ phase(i,j,k) = 1.0; } else phase(i,j,k) = -1.0; } } } // Solve for the position of the solid phase for (int k=0;kid[n] > 0){ id_solid(i,j,k) = 1; } else id_solid(i,j,k) = 0; } } } // Initialize the signed distance function for (int k=0;krank_info,phase,SignDist,vF,vS,phase_label,Dm->Comm); MPI_Barrier(Dm->Comm); int count_connected=0; int count_porespace=0; int count_water=0; for (int k=1; k 0){ count_porespace++; } if (id[n] == 2){ count_water++; } } } } count_connected=sumReduce( Dm->Comm, count_connected); count_porespace=sumReduce( Dm->Comm, count_porespace); count_water=sumReduce( Dm->Comm, count_water); for (int k=0; k 0.0) MorphOpen(SignDist, id_connected, Dm, St, water, notwater); else { if(rank==0) printf("Initial condition satisfies condition for saturation target \n"); } // re-label for (int k=0; kComm, count_water); SW = double(count_water) / count_porespace; if(rank==0) printf("Final saturation: %f \n", SW); if (rank==0) printf("Writing ID file \n"); sprintf(LocalRankFilename,"ID.%05i",rank); FILE *ID = fopen(LocalRankFilename,"wb"); fwrite(id,1,N,ID); fclose(ID); // write the geometry to a single file for (int k=0;kid[n] = id[n]; } } } MPI_Barrier(comm); auto filename2 = READFILE + ".morph.raw"; if (rank==0) printf("Writing file to: %s \n", filename2.c_str()); Mask->AggregateLabels(filename2); } MPI_Barrier(comm); MPI_Finalize(); }