diff --git a/common/Domain.cpp b/common/Domain.cpp index d75ec4a5..fc797a8e 100644 --- a/common/Domain.cpp +++ b/common/Domain.cpp @@ -1286,3 +1286,150 @@ 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>>(dist,Den,Np); + + cudaError_t err = cudaGetLastError(); + if (cudaSuccess != err){ + printf("CUDA error in ScaLBL_D3Q7_Ion_Init_FromFile: %s \n",cudaGetErrorString(err)); + } + //cudaProfilerStop(); +} + extern "C" void ScaLBL_D3Q7_Ion_ChargeDensity(double *Den, double *ChargeDensity, int IonValence, int ion_component, int start, int finish, int Np){ //cudaProfilerStart(); diff --git a/models/IonModel.cpp b/models/IonModel.cpp index 7366c0b4..ac53d5cc 100644 --- a/models/IonModel.cpp +++ b/models/IonModel.cpp @@ -136,7 +136,7 @@ void ScaLBL_IonModel::ReadParams(string filename,vector &num_iter){ } //read initial ion concentration list; INPUT unit [mol/m^3] //it must be converted to LB unit [mol/lu^3] - if (ion_db->keyExists("IonConcentrationList")){ + if (ion_db->keyExists("IonConcentrationList")){ IonConcentration.clear(); IonConcentration = ion_db->getVector( "IonConcentrationList" ); if (IonConcentration.size()!=number_ion_species){ @@ -544,6 +544,35 @@ void ScaLBL_IonModel::AssignSolidBoundary(double *ion_solid) } } +void ScaLBL_IonModel::AssignIonConcentration_FromFile(double *Ci,const vector &File_ion) +{ + double *Ci_host; + Ci_host = new double[N]; + double VALUE=0.f; + + Mask->ReadFromFile(File_ion[0],File_ion[1],Ci_host); + + for (int k=0;kkeyExists("IonConcentrationFile")){ + //TODO: Need to figure out how to deal with multi-species concentration initialization + //NOTE: "IonConcentrationFile" is a vector, including "file_name, datatype" + auto File_ion = ion_db->getVector( "IonConcentrationFile" ); + double *Ci_host; + Ci_host = new double[number_ion_species*Np]; + for (int ic=0; ic db0); void AssignSolidBoundary(double *ion_solid); + void AssignIonConcentration_FromFile(double *Ci,const vector &File_ion); void IonConcentration_LB_to_Phys(DoubleArray &Den_reg); };