diff --git a/common/Domain.cpp b/common/Domain.cpp index ab457f33..fbf9c324 100644 --- a/common/Domain.cpp +++ b/common/Domain.cpp @@ -263,6 +263,7 @@ void Domain::Decomp( const std::string& Filename ) int64_t i,j,k,n; int64_t xStart,yStart,zStart; int checkerSize; + bool USE_CHECKER = false; //int inlet_layers_x, inlet_layers_y, inlet_layers_z; //int outlet_layers_x, outlet_layers_y, outlet_layers_z; xStart=yStart=zStart=0; @@ -272,8 +273,8 @@ void Domain::Decomp( const std::string& Filename ) outlet_layers_x = 0; outlet_layers_y = 0; outlet_layers_z = 0; - inlet_layers_phase=1; - outlet_layers_phase=2; + inlet_layers_phase=1; + outlet_layers_phase=2; checkerSize = 32; // Read domain parameters @@ -302,6 +303,7 @@ void Domain::Decomp( const std::string& Filename ) } if (database->keyExists( "checkerSize" )){ checkerSize = database->getScalar( "checkerSize" ); + USE_CHECKER = true; } else { checkerSize = SIZE[0]; @@ -324,7 +326,6 @@ void Domain::Decomp( const std::string& Filename ) //printf("INPUT ERROR: Valid ReadType are 8bit, 16bit \n"); ReadType = "8bit"; } - nx = size[0]; ny = size[1]; nz = size[2]; @@ -335,7 +336,7 @@ void Domain::Decomp( const std::string& Filename ) global_Ny = SIZE[1]; global_Nz = SIZE[2]; nprocs=nprocx*nprocy*nprocz; - char *SegData = nullptr; + char *SegData = NULL; if (RANK==0){ printf("Input media: %s\n",Filename.c_str()); @@ -353,7 +354,7 @@ void Domain::Decomp( const std::string& Filename ) if (ReadType == "8bit"){ printf("Reading 8-bit input data \n"); FILE *SEGDAT = fopen(Filename.c_str(),"rb"); - if (!SEGDAT) ERROR("Domain.cpp: Error reading segmented data"); + if (SEGDAT==NULL) ERROR("Domain.cpp: Error reading segmented data"); size_t ReadSeg; ReadSeg=fread(SegData,1,SIZE,SEGDAT); if (ReadSeg != size_t(SIZE)) printf("Domain.cpp: Error reading segmented data \n"); @@ -364,7 +365,7 @@ void Domain::Decomp( const std::string& Filename ) short int *InputData; InputData = new short int[SIZE]; FILE *SEGDAT = fopen(Filename.c_str(),"rb"); - if (!SEGDAT) ERROR("Domain.cpp: Error reading segmented data"); + if (SEGDAT==NULL) ERROR("Domain.cpp: Error reading segmented data"); size_t ReadSeg; ReadSeg=fread(InputData,2,SIZE,SEGDAT); if (ReadSeg != size_t(SIZE)) printf("Domain.cpp: Error reading segmented data \n"); @@ -374,7 +375,7 @@ void Domain::Decomp( const std::string& Filename ) } } printf("Read segmented data from %s \n",Filename.c_str()); - + // relabel the data std::vector LabelCount(ReadValues.size(),0); for (int k = 0; k 0){ - // use checkerboard pattern - printf("Checkerboard pattern at x inlet for %i layers \n",inlet_layers_x); - for (int k = 0; k 0){ + // use checkerboard pattern + printf("Checkerboard pattern at x inlet for %i layers \n",inlet_layers_x); + for (int k = 0; k 0){ + printf("Checkerboard pattern at y inlet for %i layers \n",inlet_layers_y); + // use checkerboard pattern + for (int k = 0; k 0){ + printf("Checkerboard pattern at z inlet for %i layers, saturated with phase label=%i \n",inlet_layers_z,inlet_layers_phase); + // use checkerboard pattern + for (int k = zStart; k < zStart+inlet_layers_z; k++){ + for (int j = 0; j 0){ + // use checkerboard pattern + printf("Checkerboard pattern at x outlet for %i layers \n",outlet_layers_x); + for (int k = 0; k 0){ + printf("Checkerboard pattern at y outlet for %i layers \n",outlet_layers_y); + // use checkerboard pattern + for (int k = 0; k 0){ + printf("Checkerboard pattern at z outlet for %i layers, saturated with phase label=%i \n",outlet_layers_z,outlet_layers_phase); + // use checkerboard pattern + for (int k = zStart + nz*nprocz - outlet_layers_z; k < zStart + nz*nprocz; k++){ + for (int j = 0; j 0){ - printf("Checkerboard pattern at y inlet for %i layers \n",inlet_layers_y); - // use checkerboard pattern - for (int k = 0; k 0){ + printf("Mixed reflection pattern at z inlet for %i layers, saturated with phase label=%i \n",inlet_layers_z,inlet_layers_phase); + for (int k = zStart; k < zStart+inlet_layers_z; k++){ + for (int j = 0; j 0){ + SegData[k*global_Nx*global_Ny+j*global_Nx+i] = reflection_id; + } } } } } - } - - if (inlet_layers_z > 0){ - printf("Checkerboard pattern at z inlet for %i layers \n",inlet_layers_z); - // use checkerboard pattern - for (int k = zStart; k < zStart+inlet_layers_z; k++){ - for (int j = 0; j 0){ - // use checkerboard pattern - printf("Checkerboard pattern at x outlet for %i layers \n",outlet_layers_x); - for (int k = 0; k 0){ - printf("Checkerboard pattern at y outlet for %i layers \n",outlet_layers_y); - // use checkerboard pattern - for (int k = 0; k 0){ - printf("Checkerboard pattern at z outlet for %i layers \n",outlet_layers_z); - // use checkerboard pattern - for (int k = zStart + nz*nprocz - outlet_layers_z; k < zStart + nz*nprocz; k++){ - for (int j = 0; j 0){ + printf("Mixed reflection pattern at z outlet for %i layers, saturated with phase label=%i \n",outlet_layers_z,outlet_layers_phase); + for (int k = zStart + nz*nprocz - outlet_layers_z; k < zStart + nz*nprocz; k++){ + for (int j = 0; j 0){ + SegData[k*global_Nx*global_Ny+j*global_Nx+i] = reflection_id; + } } } } @@ -523,7 +553,7 @@ void Domain::Decomp( const std::string& Filename ) // Get the rank info int64_t N = (nx+2)*(ny+2)*(nz+2); - + // number of sites to use for periodic boundary condition transition zone int64_t z_transition_size = (nprocz*nz - (global_Nz - zStart))/2; if (z_transition_size < 0) z_transition_size=0; @@ -594,6 +624,27 @@ void Domain::Decomp( const std::string& Filename ) Comm.recv(id.data(),N,0,15); } Comm.barrier(); + + // Compute the porosity + double sum; + double sum_local=0.0; + double iVol_global = 1.0/(1.0*(Nx-2)*(Ny-2)*(Nz-2)*nprocs); + if (BoundaryCondition > 0 && BoundaryCondition !=5) iVol_global = 1.0/(1.0*(Nx-2)*nprocx*(Ny-2)*nprocy*((Nz-2)*nprocz-6)); + //......................................................... + for (int k=inlet_layers_z+1; k 0){ + sum_local+=1.0; + } + } + } + } + sum = Comm.sumReduce(sum_local); + porosity = sum*iVol_global; + if (rank()==0) printf("Media porosity = %f \n",porosity); + //......................................................... } void Domain::AggregateLabels( const std::string& filename ){ @@ -1170,3 +1221,239 @@ void ReadBinaryFile(char *FILENAME, double *Data, size_t N) File.close(); } +void Domain::ReadFromFile(const std::string& Filename,const std::string& Datatype, double *UserData) +{ + //........................................................................................ + // Reading the user-defined input file + // NOTE: so far it only supports BC=0 (periodic) and BC=5 (mixed reflection) + // because if checkerboard or inlet/outlet buffer layers are added, the + // value of the void space is undefined. + // NOTE: if BC=5 is used, where the inlet and outlet layers of the domain are modified, + // user needs to modify the input file accordingly before LBPM simulator read + // the input file. + //........................................................................................ + int rank_offset = 0; + int RANK = rank(); + int nprocs, nprocx, nprocy, nprocz, nx, ny, nz; + int64_t global_Nx,global_Ny,global_Nz; + int64_t i,j,k,n; + //TODO These offset we may still need them + int64_t xStart,yStart,zStart; + xStart=yStart=zStart=0; + + // Read domain parameters + // TODO currently the size of the data is still read from Domain{}; + // but user may have a user-specified size + auto size = database->getVector( "n" ); + auto SIZE = database->getVector( "N" ); + auto nproc = database->getVector( "nproc" ); + //TODO currently the funcationality "offset" is disabled as the user-defined input data may have a different size from that of the input domain + if (database->keyExists( "offset" )){ + auto offset = database->getVector( "offset" ); + xStart = offset[0]; + yStart = offset[1]; + zStart = offset[2]; + } + + nx = size[0]; + ny = size[1]; + nz = size[2]; + nprocx = nproc[0]; + nprocy = nproc[1]; + nprocz = nproc[2]; + global_Nx = SIZE[0]; + global_Ny = SIZE[1]; + global_Nz = SIZE[2]; + nprocs=nprocx*nprocy*nprocz; + + double *SegData = NULL; + if (RANK==0){ + printf("User-defined input file: %s (data type: %s)\n",Filename.c_str(),Datatype.c_str()); + printf("NOTE: currently only BC=0 or 5 supports user-defined input file!\n"); + // Rank=0 reads the entire segmented data and distributes to worker processes + printf("Dimensions of the user-defined input file: %ld x %ld x %ld \n",global_Nx,global_Ny,global_Nz); + int64_t SIZE = global_Nx*global_Ny*global_Nz; + + if (Datatype == "double"){ + printf("Reading input data as double precision floating number\n"); + SegData = new double[SIZE]; + FILE *SEGDAT = fopen(Filename.c_str(),"rb"); + if (SEGDAT==NULL) ERROR("Domain.cpp: Error reading user-defined file!\n"); + size_t ReadSeg; + ReadSeg=fread(SegData,8,SIZE,SEGDAT); + if (ReadSeg != size_t(SIZE)) printf("Domain.cpp: Error reading file: %s\n",Filename.c_str()); + fclose(SEGDAT); + } + else{ + ERROR("Error: User-defined input file only supports double-precision floating number!\n"); + } + printf("Read file successfully from %s \n",Filename.c_str()); + } + + // Get the rank info + int64_t N = (nx+2)*(ny+2)*(nz+2); + + // number of sites to use for periodic boundary condition transition zone + //int64_t z_transition_size = (nprocz*nz - (global_Nz - zStart))/2; + //if (z_transition_size < 0) z_transition_size=0; + int64_t z_transition_size = 0; + + //char LocalRankFilename[1000];//just for debug + double *loc_id; + loc_id = new double [(nx+2)*(ny+2)*(nz+2)]; + + // Set up the sub-domains + if (RANK==0){ + printf("Decomposing user-defined input file\n"); + printf("Distributing subdomains across %i processors \n",nprocs); + printf("Process grid: %i x %i x %i \n",nprocx,nprocy,nprocz); + printf("Subdomain size: %i x %i x %i \n",nx,ny,nz); + printf("Size of transition region: %ld \n", z_transition_size); + + for (int kp=0; kp