23 template <
typename memoryType>
34 template <
typename memoryType>
37 printf(
"Initializing Navier-Stokes solver ...\n");
42 int numUV = (nx-1)*ny + nx*(ny-1),
46 initialiseArrays(numUV, numP);
54 template <
typename memoryType>
57 printf(
"Initializing common parts ...\n");
58 logger.startTimer(
"initialiseCommon");
64 diffScheme = (*paramDB)[
"simulation"][
"diffTimeScheme"].get<
timeScheme>();
65 intgSchm.initialise(convScheme, diffScheme);
68 timeStep = (*paramDB)[
"simulation"][
"startStep"].get<
int>();
70 std::string folder = (*paramDB)[
"inputs"][
"caseFolder"].get<std::string>();
76 std::stringstream out;
77 out << folder <<
"/iterations";
80 iterationsFile.open(out.str().c_str());
84 iterationsFile.open(out.str().c_str(), std::ofstream::app);
87 logger.stopTimer(
"initialiseCommon");
97 template <
typename memoryType>
100 printf(
"Initializing arrays ...\n");
101 logger.startTimer(
"initialiseArrays");
112 cusp::blas::fill(rn, 0.0);
113 cusp::blas::fill(H, 0.0);
114 cusp::blas::fill(bc1, 0.0);
115 cusp::blas::fill(rhs1, 0.0);
116 cusp::blas::fill(temp1, 0.0);
118 lambda.resize(numLambda);
119 bc2.resize(numLambda);
120 rhs2.resize(numLambda);
121 temp2.resize(numLambda);
123 cusp::blas::fill(lambda, 0.0);
124 cusp::blas::fill(bc2, 0.0);
125 cusp::blas::fill(rhs2, 0.0);
126 cusp::blas::fill(temp2, 0.0);
129 initialiseBoundaryArrays();
132 cusp::blas::scal(H, 1.0/intgSchm.gamma[subStep]);
134 logger.stopTimer(
"initialiseArrays");
147 int nx = domInfo->nx,
149 vecH qHost((nx-1)*ny+nx*(ny-1));
152 real *qHost_r = thrust::raw_pointer_cast(&(qHost[0]));
153 initialiseFluxes(qHost_r);
164 template <
typename memoryType>
170 std::string caseFolder = (*paramDB)[
"inputs"][
"caseFolder"].get<std::string>();
176 int nx = domInfo->nx,
180 real xmin = domInfo->x[0],
181 xmax = domInfo->x[nx],
182 ymin = domInfo->y[0],
183 ymax = domInfo->y[ny];
185 real uInitial = (*paramDB)[
"flow"][
"uInitial"].get<
real>(),
186 uPerturb = (*paramDB)[
"flow"][
"uPerturb"].get<
real>(),
187 vInitial = (*paramDB)[
"flow"][
"vInitial"].get<
real>(),
188 vPerturb = (*paramDB)[
"flow"][
"vPerturb"].get<
real>();
190 for(
int j=0; j<ny; j++)
192 for(
int i=0; i<nx-1; i++)
194 q[j*(nx-1) + i] = ( uInitial + uPerturb * cos( 0.5*M_PI*(2*domInfo->xu[i]-xmax-xmin)/(xmax-xmin) ) * sin( M_PI * (2*domInfo->yu[j]-ymax-ymin)/(ymax-ymin) ) ) * domInfo->dy[j];
197 for(
int j=0; j<ny-1; j++)
199 for(
int i=0; i<nx; i++)
201 q[j*nx + i + numU] = ( vInitial + vPerturb * cos( 0.5*M_PI*(2*domInfo->yv[j]-ymax-ymin)/(ymax-ymin) ) * sin( M_PI * (2*domInfo->xv[i]-xmax-xmin)/(xmax-xmin) ) ) * domInfo->dx[i];
210 template <
typename memoryType>
213 int nx = domInfo->nx,
219 bc[
XMINUS].resize(2*ny-1);
220 bc[
XPLUS].resize(2*ny-1);
221 bc[
YMINUS].resize(2*nx-1);
222 bc[
YPLUS].resize(2*nx-1);
225 for(
int i=0; i<nx-1; i++)
236 for(
int i=0; i<ny-1; i++)
255 template <
typename memoryType>
259 for(subStep=0; subStep < intgSchm.subSteps; subStep++)
267 solveIntermediateVelocity();
285 template <
typename memoryType>
299 template <
typename memoryType>
310 template <
typename memoryType>
321 template <
typename memoryType>
324 int startStep = (*paramDB)[
"simulation"][
"startStep"].get<
int>();
325 int nt = (*paramDB)[
"simulation"][
"nt"].get<
int>();
326 return (timeStep < startStep+nt) ?
false :
true;
337 template <
typename memoryType>
340 printf(
"Initializing matrices ...\n");
341 logger.startTimer(
"assembleMatrices");
345 generateA(intgSchm.alphaImplicit[subStep]);
349 logger.stopTimer(
"assembleMatrices");
354 logger.startTimer(
"preconditioner2");
356 logger.stopTimer(
"preconditioner2");
367 template <
typename memoryType>
394 logger.startTimer(
"generateC");
397 cusp::multiply(QT, BN, temp);
398 cusp::multiply(temp, Q, C);
399 C.values[0] += C.values[0];
401 logger.stopTimer(
"generateC");
412 template <
typename memoryType>
415 logger.startTimer(
"assembleRHS1");
417 cusp::blas::axpby(rn, bc1, rhs1, 1.0, 1.0);
419 logger.stopTimer(
"assembleRHS1");
426 template <
typename memoryType>
429 logger.startTimer(
"assembleRHS2");
431 cusp::multiply(QT, qStar, temp2);
432 cusp::blas::axpby(temp2, bc2, rhs2, 1.0, -1.0);
434 logger.stopTimer(
"assembleRHS2");
445 template <
typename memoryType>
448 logger.startTimer(
"solveIntermediateVel");
450 std::string krylov = (*paramDB)[
"velocitySolve"][
"solver"].get<std::string>();
451 int maxIte = (*paramDB)[
"velocitySolve"][
"maxIterations"].get<
int>();
452 real rTol = (*paramDB)[
"velocitySolve"][
"rTol"].get<
real>();
453 real aTol = (*paramDB)[
"velocitySolve"][
"aTol"].get<
real>();
454 bool monitor = (*paramDB)[
"velocitySolve"][
"monitor"].get<
bool>();
456 cusp::monitor<real> sys1Mon(rhs1, maxIte, rTol, aTol, monitor);
459 cusp::krylov::cg(A, qStar, rhs1, sys1Mon, *PC1);
460 else if (krylov ==
"BICGSTAB")
461 cusp::krylov::bicgstab(A, qStar, rhs1, sys1Mon, *PC1);
462 else if (krylov ==
"GMRES")
464 int restart = (*paramDB)[
"velocitySolve"][
"restart"].get<
int>();
465 cusp::krylov::gmres(A, qStar, rhs1, restart, sys1Mon, *PC1);
469 printf(
"Error: Unknown Krylov solver '%s' for velocity system!\n", krylov.c_str());
473 iterationCount1 = sys1Mon.iteration_count();
474 if (!sys1Mon.converged())
476 std::cout <<
"Error: Solve for q* failed at time step " << timeStep << std::endl;
477 std::cout <<
"Iterations : " << iterationCount1 << std::endl;
478 std::cout <<
"Residual norm: " << sys1Mon.residual_norm() << std::endl;
479 std::cout <<
"Tolerance : " << sys1Mon.tolerance() << std::endl;
483 logger.stopTimer(
"solveIntermediateVel");
490 template <
typename memoryType>
493 logger.startTimer(
"solvePoisson");
495 std::string krylov = (*paramDB)[
"PoissonSolve"][
"solver"].get<std::string>();
496 int maxIte = (*paramDB)[
"PoissonSolve"][
"maxIterations"].get<
int>();
497 real rTol = (*paramDB)[
"PoissonSolve"][
"rTol"].get<
real>();
498 real aTol = (*paramDB)[
"PoissonSolve"][
"aTol"].get<
real>();
499 bool monitor = (*paramDB)[
"PoissonSolve"][
"monitor"].get<
bool>();
501 cusp::monitor<real> sys2Mon(rhs2, maxIte, rTol, aTol, monitor);
504 cusp::krylov::cg(C, lambda, rhs2, sys2Mon, *PC2);
505 else if (krylov ==
"BICGSTAB")
506 cusp::krylov::bicgstab(C, lambda, rhs2, sys2Mon, *PC2);
507 else if (krylov ==
"GMRES")
509 int restart = (*paramDB)[
"PoissonSolve"][
"restart"].get<
int>();
510 cusp::krylov::gmres(C, lambda, rhs2, restart, sys2Mon, *PC2);
514 printf(
"Error: Unknown Krylov solver '%s' for Poisson system!\n", krylov.c_str());
518 iterationCount2 = sys2Mon.iteration_count();
519 if (!sys2Mon.converged())
521 std::cout <<
"Error: Solve for Lambda failed at time step " << timeStep << std::endl;
522 std::cout <<
"Iterations : " << iterationCount2 << std::endl;
523 std::cout <<
"Residual norm: " << sys2Mon.residual_norm() << std::endl;
524 std::cout <<
"Tolerance : " << sys2Mon.tolerance() << std::endl;
528 logger.stopTimer(
"solvePoisson");
535 template <
typename memoryType>
538 logger.startTimer(
"projectionStep");
540 cusp::multiply(Q, lambda, temp1);
541 cusp::multiply(BN, temp1, q);
542 cusp::blas::axpby(qStar, q, q, 1.0, -1.0);
544 logger.stopTimer(
"projectionStep");
556 template <
typename memoryType>
559 int nsave = (*paramDB)[
"simulation"][
"nsave"].get<
int>();
560 std::string folder = (*paramDB)[
"inputs"][
"caseFolder"].get<std::string>();
563 if (timeStep % nsave == 0)
569 iterationsFile << timeStep <<
'\t' << iterationCount1 <<
'\t' << iterationCount2 << std::endl;
576 template <
typename memoryType>
579 logger.startTimer(
"output");
583 logger.stopTimer(
"output");
590 template <
typename memoryType>
594 iterationsFile.close();
bool finished()
Evaluates the condition required to stop the simulation.
Declaration of the class NavierStokesSolver.
NavierStokesSolver(parameterDB *pDB=NULL, domain *dInfo=NULL)
Constructor. Copies the database and information about the computational grid.
Implementation of the methods to generate inhomogeneous boundary conditions from the discrete Laplaci...
double real
Is a float or a double depending on the machine precision.
void stepTime()
Calculates the variables at the next time step.
void readData(std::string &caseFolder, int timeStep, real *x, std::string name)
Reads numerical data at a given time-step.
Stores the preconditioner for a given system.
void initialiseCommon()
Initializes parameters common to all Navier-Stokes solvers.
void generateBN()
Generates approximate inverse of the matrix resulting from implicit velocity terms.
Declaration of the functions of the namespace io.
timeScheme
Specifies the numerical scheme used for time-integration.
Implementation of the methods to generate the mass matrix and its inverse.
preconditionerType
Specifies the type of preconditioner.
std::map< std::string, componentParameter > parameterDB
Map from a string to a componentParameter.
void printTimingInfo(Logger &logger)
Prints the time spent to execute tasks.
cusp::array1d< real, host_memory > vecH
Cusp 1D array stored in the host.
virtual void shutDown()
Prints timing information and closes the different files.
Stores information about the computational grid.
void initialiseArrays(int numQ, int numLambda)
Initializes all arrays required to solve the Navier-Stokes equations.
Implementation of the methods to generate the explicit terms of the momentum equation.
virtual void solvePoisson()
Solves the Poisson system.
__global__ void generateA(int *ARows, int *ACols, real *AVals, real *MVals, int *LRows, int *LCols, real *LVals, int ASize, real alpha)
Generates a block of the matrix resulting from implicit terms in the momentum equation.
virtual void writeCommon()
Writes numerical solution at current time-step, as well as the number of iterations performed in each...
void writeGrid(std::string &caseFolder, domain &D)
Writes grid-points coordinates into the file grid.
cusp::coo_matrix< int, real, device_memory > cooD
COO matrix stored on the device.
virtual void writeData()
Writes data into files.
void initialiseBoundaryArrays()
Initializes boundary velocity arrays with values stored in the database.
virtual void solveIntermediateVelocity()
Solves for the intermediate flux velocity.
void updateBoundaryConditions()
Doing nothing.
virtual void projectionStep()
Projects the flux onto the divergence-free field.
void assembleMatrices()
Assembles matrices of the intermediate flux solver and the Poisson solver.
virtual void assembleRHS1()
Assembles the right hand-side of the system for the intermediate flux.
void generateQT(int *QTRows, int *QTCols, real *QTVals, int nx, int ny)
Generates the divergence matrix (on the host).
void updateQ(real gamma)
Doing nothing.
Solves the Navier-Stokes equations in a rectangular domain.
virtual void updateSolverState()
Doing nothing. Used in immersed boundary methods when the body moves.
void assembleRHS2()
Assembles the right hand-side of the Poisson system.
Stores the type of boundary condition and its value.
virtual void initialise()
Initializes parameters, arrays and matrices required for the simulation.
real value
numerical value associated with the boundary condition
void writeData(std::string &caseFolder, int n, Vector &q, Vector &lambda, domain &D)