// 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 "common/pmmc.h" #include "common/Communication.h" #include "analysis/analysis.h" #include "IO/MeshDatabase.h" #include "IO/Reader.h" #include "IO/Writer.h" #include "ProfilerApp.h" // Get a random number in [0 1] inline double rand2() { return static_cast(rand())/static_cast(RAND_MAX); } struct bubble_struct { Point center; double radius; // Get the distance to the bubble double dist( const Point& p, double Lx, double Ly, double Lz ) { double x = std::min(fabs(p.x-center.x),std::min(fabs(p.x-center.x-Lx),fabs(p.x-center.x+Lx))); double y = std::min(fabs(p.y-center.y),std::min(fabs(p.y-center.y-Ly),fabs(p.y-center.y+Ly))); double z = std::min(fabs(p.z-center.z),std::min(fabs(p.z-center.z-Lz),fabs(p.z-center.z+Lz))); return sqrt(x*x+y*y+z*z)-radius; } // Check if this bubble overlaps with rhs bool overlap( const bubble_struct& rhs, double Lx, double Ly, double Lz ) { return dist(rhs.center,Lx,Ly,Lz) <= radius+rhs.radius; } // Create a random bubble static bubble_struct rand( double Lx, double Ly, double Lz, double R0 ) { bubble_struct bubble; bubble.center.x = Lx*rand2(); bubble.center.y = Ly*rand2(); bubble.center.z = Lz*rand2(); bubble.radius = R0; bubble.radius *= 1 + 0.4*(1.0-2.0*rand2()); return bubble; } }; // Create a random set of bubles std::vector create_bubbles( int N_bubbles, double Lx, double Ly, double Lz ) { int rank; MPI_Comm_rank(MPI_COMM_WORLD,&rank); std::vector bubbles(N_bubbles); if ( rank == 0 ) { double R0 = 0.2*Lx*Ly*Lz/pow((double)N_bubbles,0.333); for (int i=0; i factors = Utilities::factor(nprocs); int nproc[3]={1,1,1}; for (size_t i=0; i bubbles = create_bubbles(20,Lx,Ly,Lz); for (int k=0; k fillData(rank_info,nx,ny,nz,1,1,1,0,1); fillData.fill(Phase); fillData.fill(SignDist); // Find blob domains if ( rank==0 ) { printf("Finding blob domains\n"); } double vF=0.0; double vS=0.0; IntArray GlobalBlobID; int nblobs = ComputeGlobalBlobIDs(nx,ny,nz,rank_info, Phase,SignDist,vF,vS,GlobalBlobID); if ( rank==0 ) { printf("Identified %i blobs\n",nblobs); } // Create the MeshDataStruct std::vector meshData(1); meshData[0].meshName = "domain"; meshData[0].mesh = std::shared_ptr( new IO::DomainMesh(rank_info,nx,ny,nz,Lx,Ly,Lz) ); std::shared_ptr PhaseVar( new IO::Variable() ); std::shared_ptr SignDistVar( new IO::Variable() ); std::shared_ptr BlobIDVar( new IO::Variable() ); PhaseVar->name = "phase"; PhaseVar->type = IO::VolumeVariable; PhaseVar->dim = 1; PhaseVar->data.resize(nx,ny,nz); meshData[0].vars.push_back(PhaseVar); SignDistVar->name = "SignDist"; SignDistVar->type = IO::VolumeVariable; SignDistVar->dim = 1; SignDistVar->data.resize(nx,ny,nz); meshData[0].vars.push_back(SignDistVar); BlobIDVar->name = "BlobID"; BlobIDVar->type = IO::VolumeVariable; BlobIDVar->dim = 1; BlobIDVar->data.resize(nx,ny,nz); meshData[0].vars.push_back(BlobIDVar); // Save the results fillData.copy(Phase,PhaseVar->data); fillData.copy(SignDist,SignDistVar->data); fillData.copy(GlobalBlobID,BlobIDVar->data); IO::writeData( 0, meshData, 2 ); // Check the results int N_errors = 0; if ( nblobs != (int) bubbles.size() ) { printf("Error, detected number of bubbles %i does not match expected %i\n",nblobs,(int)bubbles.size()); N_errors++; } // Finished #ifdef USE_TIMER PROFILE_STOP("main"); PROFILE_SAVE("TestBlobIdentify",false); #endif MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); return 0; }