cuIBM
A GPU-based Immersed Boundary Method code
io.cu
Go to the documentation of this file.
1 
7 #include <sys/stat.h>
8 
9 #include "io.h"
10 #include "utilities/types.h"
12 
13 
21 template <typename T>
22 T toNumber(std::string str)
23 {
24  T num;
25  std::stringstream ss(str); //turn the string into a stream
26  ss >> num; //convert
27  return num;
28 } // toNumber
29 
30 
35 namespace io
36 {
37 
47 std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
48 {
49  std::stringstream ss(s);
50  std::string item;
51  while (std::getline(ss, item, delim))
52  {
53  elems.push_back(item);
54  }
55  return elems;
56 } // split
57 
58 
67 std::vector<std::string> split(const std::string &s, char delim)
68 {
69  std::vector<std::string> elems;
70  split(s, delim, elems);
71  return elems;
72 } // split
73 
74 
83 void readInputs(int argc, char **argv, parameterDB &DB, domain &D)
84 {
85  // get a default database
87 
88  // first pass of command line arguments
89  commandLineParse1(argc, argv, DB);
90 
91  // case folder
92  std::string folder = DB["inputs"]["caseFolder"].get<std::string>();
93  std::string fname;
94 
95  // read the simulation file
96  fname = folder + "/simParams.yaml";
97  parseSimulationFile(fname, DB);
98 
99  // read the flow file
100  fname = folder + "/flow.yaml";
101  parseFlowFile(fname, DB);
102 
103  // read the domain file
104  fname = folder + "/domain.yaml";
105  parseDomainFile(fname, D);
106 
107  // read the body file
108  fname = folder + "/bodies.yaml";
109  parseBodiesFile(fname, DB);
110 
111  // second pass of command line -- overwrite values in DB
112  commandLineParse2(argc, argv, DB);
113 } // readInputs
114 
115 
122 {
123  DB["inputs"] = componentParameter();
124  DB["flow"] = componentParameter();
125  DB["simulation"] = componentParameter();
126  DB["velocitySolve"] = componentParameter();
127  DB["PoissonSolve"] = componentParameter();
128 
129  // default input files
130  std::string inputs = "inputs";
131  DB[inputs]["caseFolder"].set<std::string>(".");
132  DB[inputs]["deviceNumber"].set<int>(0);
133 
134  // flow parameters
135  std::string flow = "flow";
136  DB[flow]["nu"].set<real>(0.01);
137  DB[flow]["uInitial"].set<real>(1.0);
138  DB[flow]["vInitial"].set<real>(0.0);
139  DB[flow]["numBodies"].set<int>(0);
140  std::vector<body> *bodyVec = new std::vector<body>;
141  DB[flow]["bodies"].set<std::vector<body> *>(bodyVec);
142 
143  // boundary conditions
144  boundaryCondition **bc = new boundaryCondition*[4];
145  for (int i=0; i<4; i++)
146  bc[i] = new boundaryCondition[2];
147  DB[flow]["boundaryConditions"].set<boundaryCondition **>(bc);
148 
149  // simulation parameters
150  std::string sim = "simulation";
151  DB[sim]["dt"].set<real>(0.02);
152  DB[sim]["nt"].set<int>(100);
153  DB[sim]["nsave"].set<int>(100);
154  DB[sim]["startStep"].set<bool>(0);
155  DB[sim]["convTimeScheme"].set<timeScheme>(EULER_EXPLICIT);
156  DB[sim]["diffTimeScheme"].set<timeScheme>(EULER_IMPLICIT);
157  DB[sim]["ibmScheme"].set<ibmScheme>(TAIRA_COLONIUS);
158  DB[sim]["interpolationType"].set<interpolationType>(LINEAR);
159 
160  // velocity solver
161  std::string solver = "velocitySolve";
162  DB[solver]["solver"].set<std::string>("CG");
163  DB[solver]["preconditioner"].set<preconditionerType>(DIAGONAL);
164  DB[solver]["rTol"].set<real>(1.0E-05);
165  DB[solver]["aTol"].set<real>(1.0E-50);
166  DB[solver]["maxIterations"].set<int>(10000);
167 
168  // Poisson solver
169  solver = "PoissonSolve";
170  DB[solver]["solver"].set<std::string>("CG");
171  DB[solver]["preconditioner"].set<preconditionerType>(DIAGONAL);
172  DB[solver]["rTol"].set<real>(1.0E-05);
173  DB[solver]["aTol"].set<real>(1.0E-50);
174  DB[solver]["maxIterations"].set<int>(20000);
175 } // initialiseDefaultDB
176 
177 
186 void commandLineParse1(int argc, char **argv, parameterDB &DB)
187 {
188  for (int i=1; i<argc; i++)
189  {
190  if (strcmp(argv[i],"-directory")==0)
191  {
192  i++;
193  DB["inputs"]["caseFolder"].set<std::string>(std::string(argv[i]));
194  }
195  else if (strcmp(argv[i],"-deviceNumber")==0)
196  {
197  i++;
198  int devNum = toNumber<int>(std::string(argv[i]));
199  DB["inputs"]["deviceNumber"].set<int>(devNum);
200  // sets devNum as the current device for the calling host thread
201  cudaSetDevice(devNum);
202  }
203  }
204 } // commandLineParse1
205 
206 
214 void commandLineParse2(int argc, char **argv, parameterDB &DB)
215 {
216  for (int i=1; i<argc; i++)
217  {
218  // kinematic viscosity
219  if ( strcmp(argv[i],"-nu")==0 )
220  {
221  i++;
222  DB["flow"]["nu"].set<real>(toNumber<real>(std::string(argv[i])));
223  }
224  // perturbation in the x-velocity
225  if ( strcmp(argv[i],"-uPerturb")==0 )
226  {
227  i++;
228  DB["flow"]["uPerturb"].set<real>(toNumber<real>(std::string(argv[i])));
229  }
230  // perturbation in the y-velocity
231  if ( strcmp(argv[i],"-vPerturb")==0 )
232  {
233  i++;
234  DB["flow"]["vPerturb"].set<real>(toNumber<real>(std::string(argv[i])));
235  }
236  // scale the CV with respect to the body
237  if ( strcmp(argv[i],"-scaleCV")==0 )
238  {
239  i++;
240  DB["simulation"]["scaleCV"].set<real>(toNumber<real>(std::string(argv[i])));
241  }
242  // frequency of saving the data
243  if ( strcmp(argv[i],"-nsave")==0 )
244  {
245  i++;
246  DB["simulation"]["nsave"].set<int>(toNumber<int>(std::string(argv[i])));
247  }
248  // total number of time steps
249  if ( strcmp(argv[i],"-nt")==0 )
250  {
251  i++;
252  DB["simulation"]["nt"].set<int>(toNumber<int>(std::string(argv[i])));
253  }
254  // size of time increment
255  if ( strcmp(argv[i],"-dt")==0 )
256  {
257  i++;
258  DB["simulation"]["dt"].set<real>(toNumber<real>(std::string(argv[i])));
259  }
260  // relative tolerance for the velocity solve
261  if ( strcmp(argv[i],"-velocity-rtol")==0 )
262  {
263  i++;
264  DB["velocitySolve"]["rTol"].set<real>(toNumber<real>(std::string(argv[i])));
265  }
266  // absolute tolerance for the velocity solve
267  if ( strcmp(argv[i],"-velocity-atol")==0 )
268  {
269  i++;
270  DB["velocitySolve"]["aTol"].set<real>(toNumber<real>(std::string(argv[i])));
271  }
272  // relative tolerance for the Poisson solve
273  if ( strcmp(argv[i],"-poisson-rtol")==0 )
274  {
275  i++;
276  DB["PoissonSolve"]["rTol"].set<real>(toNumber<real>(std::string(argv[i])));
277  }
278  // absolute tolerance for the Poisson solve
279  if ( strcmp(argv[i],"-poisson-atol")==0 )
280  {
281  i++;
282  DB["PoissonSolve"]["aTol"].set<real>(toNumber<real>(std::string(argv[i])));
283  }
284  // IBM Scheme
285  if ( strcmp(argv[i],"-ibmScheme")==0 )
286  {
287  i++;
288  if ( strcmp(argv[i],"NavierStokes")==0 )
289  DB["simulation"]["ibmScheme"].set<ibmScheme>(NAVIER_STOKES);
290  else
291  if ( strcmp(argv[i],"TairaColonius")==0 )
292  DB["simulation"]["ibmScheme"].set<ibmScheme>(TAIRA_COLONIUS);
293  else
294  if ( strcmp(argv[i],"DirectForcing")==0 )
295  DB["simulation"]["ibmScheme"].set<ibmScheme>(DIRECT_FORCING);
296  else
297  if ( strcmp(argv[i],"FadlunEtAl")==0 )
298  DB["simulation"]["ibmScheme"].set<ibmScheme>(FADLUN_ET_AL);
299  else
300  if ( strcmp(argv[i],"Diffusion")==0 )
301  DB["simulation"]["ibmScheme"].set<ibmScheme>(DIFFUSION);
302  else
303  if ( strcmp(argv[i],"DFModified")==0 )
304  DB["simulation"]["ibmScheme"].set<ibmScheme>(DF_MODIFIED);
305  else
306  if ( strcmp(argv[i],"FEAModified")==0 )
307  DB["simulation"]["ibmScheme"].set<ibmScheme>(FEA_MODIFIED);
308  else
309  if ( strcmp(argv[i],"DFImproved")==0 )
310  DB["simulation"]["ibmScheme"].set<ibmScheme>(DF_IMPROVED);
311  }
312  // interpolation type for Eulerian direct forcing methods
313  if ( strcmp(argv[i],"-interpolationType")==0 )
314  {
315  i++;
316  if ( strcmp(argv[i],"constant")==0 )
317  DB["simulation"]["interpolationType"].set<interpolationType>(CONSTANT);
318  else
319  if ( strcmp(argv[i],"linear")==0 )
320  DB["simulation"]["interpolationType"].set<interpolationType>(LINEAR);
321  else
322  if ( strcmp(argv[i],"quadratic")==0 )
323  DB["simulation"]["interpolationType"].set<interpolationType>(QUADRATIC);
324  }
325  }
326 } // commandLineParse2
327 
328 
337 {
338  if (s == NONE)
339  return "None";
340  else if (s == DIAGONAL)
341  return "Diagonal";
342  else if (s == SMOOTHED_AGGREGATION)
343  return "Smoothed Aggregation";
344  else if (s == AINV)
345  return "Approximate Inverse";
346  else
347  {
348  printf("Error: Unknown preconditionerType.\n");
349  exit(-1);
350  }
351 } // stringFromPreconditionerType
352 
353 
362 {
363  if (s == EULER_EXPLICIT)
364  return "Explicit Euler Method";
365  else if (s == EULER_IMPLICIT)
366  return "Implicit Euler Method";
367  else if (s == ADAMS_BASHFORTH_2)
368  return "2nd Order Adams-Bashforth";
369  else if (s == CRANK_NICOLSON)
370  return "Crank-Nicolson";
371  else
372  {
373  printf("Error: Unknown timeScheme!\n");
374  exit(-1);
375  }
376 } // stringFromTimeScheme
377 
378 
386 {
387  real dt = DB["simulation"]["dt"].get<real>(),
388  scaleCV = DB["simulation"]["scaleCV"].get<real>();
389  int nt = DB["simulation"]["nt"].get<int>(),
390  nsave = DB["simulation"]["nsave"].get<int>(),
391  startStep = DB["simulation"]["startStep"].get<int>();
392  interpolationType interpType = DB["simulation"]["interpolationType"].get<interpolationType>();
393  ibmScheme ibmSchm = DB["simulation"]["ibmScheme"].get<ibmScheme>();
394 
395 
396  std::cout << '\n';
397 
398  std::cout << "\nFlow parameters" << '\n';
399  std::cout << "---------------" << '\n';
400  std::cout << "nu = " << DB["flow"]["nu"].get<real>() << '\n';
401 
402  std::cout << "\nDomain" << '\n';
403  std::cout << "------" << '\n';
404  std::cout << D.nx << " x " << D.ny << '\n';
405 
406  std::cout << "\nSimulation parameters" << '\n';
407  std::cout << "---------------------" << '\n';
408  std::cout << "dt = " << dt << '\n';
409  std::cout << "scaleCV = " << scaleCV << '\n';
410  std::cout << "startStep = " << startStep << '\n';
411  std::cout << "nt = " << nt << '\n';
412  std::cout << "nsave = " << nsave << '\n';
413  std::cout << "Convection time scheme = " << stringFromTimeScheme(DB["simulation"]["convTimeScheme"].get<timeScheme>()) << '\n';
414  std::cout << "Diffusion time scheme = " << stringFromTimeScheme(DB["simulation"]["diffTimeScheme"].get<timeScheme>()) << '\n';
415  if (ibmSchm == FADLUN_ET_AL ||
416  ibmSchm == DIRECT_FORCING ||
417  ibmSchm == DIFFUSION ||
418  ibmSchm == DF_IMPROVED ||
419  ibmSchm == DF_MODIFIED ||
420  ibmSchm == FEA_MODIFIED)
421  {
422  std::cout << "Interpolation type: ";
423  switch(interpType)
424  {
425  case CONSTANT : std::cout << "Constant\n"; break;
426  case LINEAR : std::cout << "Linear\n"; break;
427  case QUADRATIC: std::cout << "Quadratic\n"; break;
428  default : std::cout << "Unknown\n"; break;
429  }
430  }
431 
432  std::cout << "\nVelocity Solve" << '\n';
433  std::cout << "--------------" << '\n';
434  std::cout << "Solver = " << DB["velocitySolve"]["solver"].get<std::string>() << '\n';
435  std::cout << "Preconditioner = " << stringFromPreconditionerType(DB["velocitySolve"]["preconditioner"].get<preconditionerType>()) << '\n';
436  std::cout << "Relative tolerance = " << DB["velocitySolve"]["rTol"].get<real>() << '\n';
437  std::cout << "Absolute tolerance = " << DB["velocitySolve"]["aTol"].get<real>() << '\n';
438 
439  std::cout << "\nPoisson Solve" << '\n';
440  std::cout << "-------------" << '\n';
441  std::cout << "Solver = " << DB["PoissonSolve"]["solver"].get<std::string>() << '\n';
442  std::cout << "Preconditioner = " << stringFromPreconditionerType(DB["PoissonSolve"]["preconditioner"].get<preconditionerType>()) << '\n';
443  std::cout << "Relative tolerance = " << DB["PoissonSolve"]["rTol"].get<real>() << '\n';
444  std::cout << "Absolute tolerance = " << DB["PoissonSolve"]["aTol"].get<real>() << '\n';
445 
446  std::cout << "\nOutput parameters" << '\n';
447  std::cout << "-----------------" << '\n';
448  std::cout << "Output folder = " << DB["inputs"]["caseFolder"].get<std::string>() << '\n';
449  std::cout << "nsave = " << DB["simulation"]["nsave"].get<int>() << '\n';
450 
451  cudaDeviceProp deviceProp;
452  int gpu = DB["inputs"]["deviceNumber"].get<int>();
453  cudaGetDeviceProperties(&deviceProp, gpu);
454  std::cout << "\nDevice Properties" << '\n';
455  std::cout << "-----------------" << '\n';
456  std::cout << "Name = " << deviceProp.name << '\n';
457  std::cout << "Number = " << gpu << '\n';
458  std::string ecc = deviceProp.ECCEnabled ? "yes" : "no";
459  std::cout << "Compute capability = " << deviceProp.major << "." << deviceProp.minor << '\n';
460  std::cout << "ECC Enabled = " << ecc << std::endl;
461 } // printSimulationInfo
462 
463 
469 void printTimingInfo(Logger &logger)
470 {
471  logger.printAllTime();
472  std::cout << std::endl;
473 } // printTimingInfo
474 
475 
482 void writeGrid(std::string &caseFolder, domain &D)
483 {
484  std::stringstream out;
485  out << caseFolder << "/grid";
486  std::ofstream file(out.str().c_str(), std::ios::binary);
487  file.write((char*)(&D.nx), sizeof(int));
488  file.write((char*)(&D.x[0]), (D.nx+1)*sizeof(real));
489  file.write((char*)(&D.ny), sizeof(int));
490  file.write((char*)(&D.y[0]), (D.ny+1)*sizeof(real));
491  file.close();
492 } // writeGrid
493 
494 
508 template <>
509 void writeData<vecH>(std::string &caseFolder, int n, vecH &q, vecH &lambda, domain &D)//, bodies &B)
510 {
511  std::string path;
512  std::stringstream out;
513  int N;
514 
515  out << caseFolder << '/' << std::setfill('0') << std::setw(7) << n;
516  path = out.str();
517 
518  mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
519 
520  out.str("");
521  out << path << "/q";
522  std::ofstream file(out.str().c_str(), std::ios::binary);
523  N = q.size();
524  file.write((char*)(&N), sizeof(int));
525  file.write((char*)(&q[0]), N*sizeof(real));
526  file.close();
527 
528  out.str("");
529  out << path << "/lambda";
530  file.open(out.str().c_str(), std::ios::binary);
531  N = lambda.size();
532  file.write((char*)(&N), sizeof(int));
533  file.write((char*)(&lambda[0]), N*sizeof(real));
534  file.close();
535 
536  std::cout << "Data saved to folder " << path << std::endl;
537 } // writeData
538 
539 
553 template <>
554 void writeData<vecD>(std::string &caseFolder, int n, vecD &q, vecD &lambda, domain &D)//, bodies &B)
555 {
556  vecH qH = q,
557  lambdaH = lambda;
558 
559  writeData(caseFolder, n, qH, lambdaH, D);
560 } // writeData
561 
562 
571 void readData(std::string &caseFolder, int timeStep, real *x, std::string name)
572 {
573  std::stringstream in;
574  std::string inFilePath;
575  int n;
576 
577  in << caseFolder << "/" << std::setfill('0') << std::setw(7) << timeStep << "/" << name;
578  inFilePath = in.str();
579  std::cout << "Reading fluxes from " << inFilePath << " ... ";
580  std::ifstream inFile(inFilePath.c_str(), std::ifstream::binary);
581  inFile.read((char*)(&n), sizeof(int));
582  inFile.read((char*)(&x[0]), n*sizeof(real));
583  inFile.close();
584  std::cout << "done" << std::endl;
585 } // readData
586 
587 
593 void printDeviceMemoryUsage(std::string label)
594 {
595  size_t _free, _total;
596  cudaMemGetInfo(&_free, &_total);
597  std::cout << label << ": Memory Usage " << std::setprecision(3) << (_total-_free)/(1024.0*1024*1024) \
598  << " / " << std::setprecision(3) << _total/(1024.0*1024*1024) << " GB" << std::setprecision(6) << '\n' << std::endl;
599 } // printDeviceMemoryUsage
600 
601 } // End of namespace io
Monitors the time spent to achieve a certain task.
Definition: logger.h:33
vecH x
x-coordinates of the nodes
Definition: domain.h:22
void readInputs(int argc, char **argv, parameterDB &DB, domain &D)
Reads data inputs from the command-line and the simulation files.
Definition: io.cu:83
Fadlun et al. modified.
Definition: types.h:83
Definition of custom types required by the code.
void writeData< vecH >(std::string &caseFolder, int n, vecH &q, vecH &lambda, domain &D)
Writes numerical data at a given time-step (on the host).
Definition: io.cu:509
constant
Definition: types.h:94
void parseFlowFile(std::string &flowFile, parameterDB &DB)
Parses the flow file and stores the parameters in the database.
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
Splits a string given a delimiter.
Definition: io.cu:47
void printAllTime()
Prints time spent for each event as well as the total time.
Definition: logger.h:185
Definition of the class boundaryCondition.
double real
Is a float or a double depending on the machine precision.
Definition: types.h:116
void readData(std::string &caseFolder, int timeStep, real *x, std::string name)
Reads numerical data at a given time-step.
Definition: io.cu:571
fully discrete direct forcing method
Definition: types.h:78
std::string stringFromTimeScheme(timeScheme s)
Converts a timeScheme to a std::string.
Definition: io.cu:361
void commandLineParse1(int argc, char **argv, parameterDB &DB)
Parses the command-line to get the case folder name and the device number.
Definition: io.cu:186
ibmScheme
Specifies the immersed boundary method used to solve the flow.
Definition: types.h:74
implicit Euler method (first order)
Definition: types.h:63
Declaration of the functions of the namespace io.
timeScheme
Specifies the numerical scheme used for time-integration.
Definition: types.h:60
void parseSimulationFile(std::string &simFile, parameterDB &DB)
Parses simParams.yaml and stores the simulation parameters.
preconditionerType
Specifies the type of preconditioner.
Definition: types.h:104
std::map< std::string, componentParameter > parameterDB
Map from a string to a componentParameter.
Definition: parameterDB.h:64
T toNumber(std::string str)
Converts a string to a number.
Definition: io.cu:22
smoothed aggregation preconditioner
Definition: types.h:108
void printTimingInfo(Logger &logger)
Prints the time spent to execute tasks.
Definition: io.cu:469
cusp::array1d< real, host_memory > vecH
Cusp 1D array stored in the host.
Definition: types.h:154
Contains functions related to I/O tasks.
Stores information about the computational grid.
Definition: domain.h:16
no immersed bodies - Perot (1993)
Definition: types.h:76
Direct Forcing Improved.
Definition: types.h:84
Fadlun et al (2000)
Definition: types.h:79
void writeData< vecD >(std::string &caseFolder, int n, vecD &q, vecD &lambda, domain &D)
Writes numerical data at a given time-step (on the device).
Definition: io.cu:554
quadratic
Definition: types.h:96
std::string stringFromPreconditionerType(preconditionerType s)
Converts a preconditionerType to a std::string.
Definition: io.cu:336
interpolationType
Specifies the type of interpolation.
Definition: types.h:92
void writeGrid(std::string &caseFolder, domain &D)
Writes grid-points coordinates into the file grid.
Definition: io.cu:482
Taira & Colonius (2007)
Definition: types.h:80
int ny
number of cells in the y-direction
Definition: domain.h:19
void initialiseDefaultDB(parameterDB &DB)
Initializes the database with default values.
Definition: io.cu:121
no preconditioner
Definition: types.h:106
int nx
number of cells in the x-direction
Definition: domain.h:19
void parseBodiesFile(std::string &bodiesFile, parameterDB &DB)
Parses the bodies.yaml file and stores information about the immersed bodies.
approximate inverse preconditioner
Definition: types.h:109
void printSimulationInfo(parameterDB &DB, domain &D)
Prints the parameters of the simulation.
Definition: io.cu:385
void printDeviceMemoryUsage(std::string label)
Prints device memory usage.
Definition: io.cu:593
second-order Adams-Bashforth scheme
Definition: types.h:64
Crank-Nicolson scheme (second order)
Definition: types.h:66
linear
Definition: types.h:95
diagonal preconditioner
Definition: types.h:107
std::map< std::string, property > componentParameter
Map from a string to a property object.
Definition: parameterDB.h:57
Diffusion.
Definition: types.h:81
void parseDomainFile(std::string &domFile, domain &D)
Parses the domain file and generates the computational grid.
vecH y
y-coordinates of the nodes
Definition: domain.h:22
explicit Euler method (first order)
Definition: types.h:62
Stores the type of boundary condition and its value.
Direct Forcing modified.
Definition: types.h:82
void commandLineParse2(int argc, char **argv, parameterDB &DB)
Overwrites parameters with additional arguments of the command-line.
Definition: io.cu:214
void writeData(std::string &caseFolder, int n, Vector &q, Vector &lambda, domain &D)
cusp::array1d< real, device_memory > vecD
Cusp 1D array stored in the device.
Definition: types.h:161