//************************************************************************* // Lattice Boltzmann Simulator for Single Phase Flow in Porous Media // James E. McCLure //************************************************************************* #include #include #include #include "common/ScaLBL.h" #include "common/MPI_Helpers.h" using namespace std; std::shared_ptr loadInputs( int nprocs ) { auto db = std::make_shared(); const int dim = 8; db->putScalar( "BC", 0 ); if ( nprocs == 1 ){ db->putVector( "nproc", { 1, 1, 1 } ); db->putVector( "n", { 3, 1, 1 } ); db->putScalar( "nspheres", 0 ); db->putVector( "L", { 1, 1, 1 } ); } else if ( nprocs == 2 ) { db->putVector( "nproc", { 2, 1, 1 } ); db->putVector( "n", { dim, dim, dim } ); db->putScalar( "nspheres", 0 ); db->putVector( "L", { 1, 1, 1 } ); } else if ( nprocs == 4 ) { db->putVector( "nproc", { 2, 2, 1 } ); db->putVector( "n", { dim, dim, dim } ); db->putScalar( "nspheres", 0 ); db->putVector( "L", { 1, 1, 1 } ); } else if (nprocs==8){ db->putVector( "nproc", { 2, 2, 2 } ); db->putVector( "n", { dim, dim, dim } ); db->putScalar( "nspheres", 0 ); db->putVector( "L", { 1, 1, 1 } ); } return db; } extern void GlobalFlipScaLBL_D3Q19_Init(double *dist, IntArray Map, int Np, int Nx, int Ny, int Nz, int iproc, int jproc, int kproc, int nprocx, int nprocy, int nprocz) { // Set of Discrete velocities for the D3Q19 Model static int D3Q19[18][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}}; int q,i,j,k; int Cqx,Cqy,Cqz; // Discrete velocity int x,y,z; // Global indices int xn,yn,zn; // Global indices of neighbor int X,Y,Z; // Global size int idx; X = Nx*nprocx; Y = Ny*nprocy; Z = Nz*nprocz; NULL_USE(Z); for (k=0; k 0){ // Get the 'global' index x = iproc*Nx+i; y = jproc*Ny+j; z = kproc*Nz+k; for (q=0; q<18; q++){ // Odd distribution Cqx = D3Q19[q][0]; Cqy = D3Q19[q][1]; Cqz = D3Q19[q][2]; xn = x - Cqx; yn = y - Cqy; zn = z - Cqz; xn=x; yn=y;zn=z; if (xn < 0) xn += nprocx*Nx; if (yn < 0) yn += nprocy*Ny; if (zn < 0) zn += nprocz*Nz; if (!(xn < nprocx*Nx)) xn -= nprocx*Nx; if (!(yn < nprocy*Ny)) yn -= nprocy*Ny; if (!(zn < nprocz*Nz)) zn -= nprocz*Nz; dist[(q+1)*Np+idx] = (zn*X*Y+yn*X+xn) + (q+1)*0.01; } } } } } } extern int GlobalCheckDebugDist(double *dist, IntArray Map, int Np, int Nx, int Ny, int Nz, int iproc, int jproc, int kproc, int nprocx, int nprocy, int nprocz, int start, int finish) { int returnValue = 0; int q,i,j,k,idx; int x,y,z; // Global indices int X,Y,Z; // Global size X = Nx*nprocx; Y = Ny*nprocy; Z = Nz*nprocz; NULL_USE(Z); for (k=0; k start && idx< finish){ // Get the 'global' index x = iproc*Nx+i; y = jproc*Ny+j; z = kproc*Nz+k; for (q=0; q<18; q++){ if (dist[(q+1)*Np+idx] != (z*X*Y+y*X+x) + (q+1)*0.01){ printf("******************************************\n"); printf("error in distribution q = %i \n", (q+1)); printf("i,j,k= %i, %i, %i \n", x,y,z); printf("dist = %5.2f \n", dist[(q+1)*Np+idx]); printf("n= %i \n",z*X*Y+y*X+x); returnValue++; } } } } } } return returnValue; } inline void PackID(int *list, int count, char *sendbuf, char *ID){ // Fill in the phase ID values from neighboring processors // This packs up the values that need to be sent from one processor to another int idx,n; for (idx=0; idx( filename ); auto db = input_db->getDatabase( "Domain" ); */ int Nx = db->getVector( "n" )[0]; int Ny = db->getVector( "n" )[1]; int Nz = db->getVector( "n" )[2]; auto Dm = std::shared_ptr(new Domain(db,comm)); // full domain for analysis Nx += 2; Ny += 2; Nz += 2; int N = Nx*Ny*Nz; int dist_mem_size = N*sizeof(double); //....................................................................... // Assign the phase ID field //....................................................................... char LocalRankString[8]; sprintf(LocalRankString,"%05d",rank); char LocalRankFilename[40]; sprintf(LocalRankFilename,"ID.%05i",rank); auto id = new char[Nx*Ny*Nz]; /* if (rank==0) printf("Assigning phase ID from file \n"); if (rank==0) printf("Initialize from segmented data: solid=0, NWP=1, WP=2 \n"); FILE *IDFILE = fopen(LocalRankFilename,"rb"); if (IDFILE==NULL) ERROR("Error opening file: ID.xxxxx"); fread(id,1,N,IDFILE); fclose(IDFILE); */ // Setup the domain for (k=0;kid[n] = id[n]; } } } Dm->CommInit(); int iproc,jproc,kproc; int nprocx,nprocy,nprocz; iproc = Dm->iproc(); jproc = Dm->jproc(); kproc = Dm->kproc(); nprocx = Dm->nprocx(); nprocy = Dm->nprocy(); nprocz = Dm->nprocz(); if (rank==0){ printf("********************************************************\n"); printf("Sub-domain size = %i x %i x %i\n",Nz,Nz,Nz); printf("Parallel domain size = %i x %i x %i\n",Dm->nprocx(),Dm->nprocy(),Dm->nprocz()); printf("********************************************************\n"); } //....................................................................... // Compute the media porosity //....................................................................... double sum; double sum_local=0.0, porosity; char component = 0; // solid phase int Np=0; for (k=1;kid,Np); MPI_Barrier(comm); int neighborSize=18*Np*sizeof(int); //......................device distributions................................. dist_mem_size = Np*sizeof(double); if (rank==0) printf ("Allocating distributions \n"); int *NeighborList; int *dvcMap; double *fq; //........................................................................... ScaLBL_AllocateDeviceMemory((void **) &NeighborList, neighborSize); ScaLBL_AllocateDeviceMemory((void **) &dvcMap, sizeof(int)*Np); ScaLBL_AllocateDeviceMemory((void **) &fq, 19*dist_mem_size); //........................................................................... double *fq_host; fq_host = new double [19*Np]; // Update GPU data structures if (rank==0) printf ("Setting up device map and neighbor list \n"); int *TmpMap; TmpMap=new int[Np]; for (k=1; k