PetIBM 0.5.4
Toolbox and applications of the immersed-boundary method for distributed-memory architectures
navierstokes.cpp
Go to the documentation of this file.
1
10#include <iomanip>
11
12#include <petscviewerhdf5.h>
13
14#include <petibm/io.h>
15
16#include "navierstokes.h"
17
19 const YAML::Node &node)
20{
21 init(world, node);
22} // NavierStokesSolver
23
25{
26 PetscErrorCode ierr;
27 PetscBool finalized;
28
29 PetscFunctionBeginUser;
30
31 ierr = PetscFinalized(&finalized); CHKERRV(ierr);
32 if (finalized) return;
33
34 ierr = destroy(); CHKERRV(ierr);
35} // ~NavierStokesSolver
36
37// destroy objects of the NavierStokesSolver class
39{
40 PetscErrorCode ierr;
41
42 PetscFunctionBeginUser;
43
44 comm = MPI_COMM_NULL;
45 commSize = commRank = 0;
46
47 // destroy vectors of the solver (PETSc Vec objects)
48 ierr = VecDestroy(&dP); CHKERRQ(ierr);
49 ierr = VecDestroy(&bc1); CHKERRQ(ierr);
50 ierr = VecDestroy(&rhs1); CHKERRQ(ierr);
51 ierr = VecDestroy(&rhs2); CHKERRQ(ierr);
52 for (unsigned int i = 0; i < conv.size(); ++i)
53 {
54 ierr = VecDestroy(&conv[i]); CHKERRQ(ierr);
55 }
56 for (unsigned int i = 0; i < diff.size(); ++i)
57 {
58 ierr = VecDestroy(&diff[i]); CHKERRQ(ierr);
59 }
60
61 // destroy operators of the solver (PETSc Mat objects)
62 ierr = MatDestroy(&A); CHKERRQ(ierr);
63 ierr = MatDestroy(&DBNG); CHKERRQ(ierr);
64 ierr = MatDestroy(&BNG); CHKERRQ(ierr);
65 ierr = MatDestroy(&N); CHKERRQ(ierr);
66 ierr = MatDestroy(&G); CHKERRQ(ierr);
67 ierr = MatDestroy(&D); CHKERRQ(ierr);
68 ierr = MatDestroy(&DCorrection); CHKERRQ(ierr);
69 ierr = MatDestroy(&L); CHKERRQ(ierr);
70 ierr = MatDestroy(&LCorrection); CHKERRQ(ierr);
71
72 // destroy the probes
73 for (auto probe : probes)
74 {
75 ierr = probe->destroy(); CHKERRQ(ierr);
76 }
77
78 // decrease reference count or destroy
79 vSolver.reset();
80 pSolver.reset();
81 config.reset();
82 convCoeffs.reset();
83 diffCoeffs.reset();
84 solution.reset();
85 bc.reset();
86 mesh.reset();
87
88 ierr = PetscViewerDestroy(&solversViewer); CHKERRQ(ierr);
89
90 PetscFunctionReturn(0);
91} // destroy
92
93PetscErrorCode NavierStokesSolver::init(const MPI_Comm &world, const YAML::Node &node)
94{
95 PetscErrorCode ierr;
96
97 PetscFunctionBeginUser;
98
99 ierr = PetscLogStageRegister(
100 "initialize", &stageInitialize); CHKERRQ(ierr);
101 ierr = PetscLogStagePush(stageInitialize); CHKERRQ(ierr);
102
103 // record the MPI communicator, size, and process rank
104 comm = world;
105 ierr = MPI_Comm_size(comm, &commSize); CHKERRQ(ierr);
106 ierr = MPI_Comm_rank(comm, &commRank); CHKERRQ(ierr);
107
108 // record the YAML configuration settings
109 config = node;
110
111 // get the time-step size
112 dt = config["parameters"]["dt"].as<PetscReal>();
113 // get the starting time step and time value
114 nstart = config["parameters"]["startStep"].as<PetscInt>(0);
115 ite = nstart;
116 t = config["parameters"]["t"].as<PetscReal>(0.0);
117 // get the number of time steps to compute
118 nt = config["parameters"]["nt"].as<PetscInt>();
119 // get the saving frequencies
120 nsave = config["parameters"]["nsave"].as<PetscInt>();
121 nrestart = config["parameters"]["nrestart"].as<PetscInt>();
122 // get the viscous diffusion coefficient
123 nu = config["flow"]["nu"].as<PetscReal>();
124
125 // create the Cartesian mesh
126 ierr = petibm::mesh::createMesh(comm, config, mesh); CHKERRQ(ierr);
127 // write the grid points into a HDF5 file
128 std::string filePath = config["output"].as<std::string>() + "/grid.h5";
129 ierr = mesh->write(filePath); CHKERRQ(ierr);
130
131 // create the data object for the boundary conditions
132 ierr = petibm::boundary::createBoundary(mesh, config, bc); CHKERRQ(ierr);
133
134 // create the solution object
135 ierr = petibm::solution::createSolution(mesh, solution); CHKERRQ(ierr);
136
137 // set the initial conditions
138 ierr = solution->setInitialConditions(config); CHKERRQ(ierr);
139
140 // initialize ghost-point values and equations;
141 // must be done before creating the operators
142 ierr = bc->setGhostICs(solution); CHKERRQ(ierr);
143
144 // create the time-scheme objects
146 "convection", config, convCoeffs); CHKERRQ(ierr);
148 "diffusion", config, diffCoeffs); CHKERRQ(ierr);
149
150 // create the linear solver objects
152 "velocity", config, vSolver); CHKERRQ(ierr);
154 "poisson", config, pSolver); CHKERRQ(ierr);
155
156 // create operators (PETSc Mat objects)
157 ierr = createOperators(); CHKERRQ(ierr);
158
159 // create PETSc Vec objects
160 ierr = createVectors(); CHKERRQ(ierr);
161
162 // set coefficient matrix of the linear solvers
163 ierr = vSolver->setMatrix(A); CHKERRQ(ierr);
164 ierr = pSolver->setMatrix(DBNG); CHKERRQ(ierr);
165
166 // create probes to monitor the solution in some regions of the domain
167 probes.resize(config["probes"].size());
168 for (unsigned int i = 0; i < probes.size(); ++i)
169 {
170 // Prepend relative path with output directory.
171 config["probes"][i]["path"] =
172 config["output"].as<std::string>() + "/" +
173 config["probes"][i]["path"].as<std::string>();
174 // Create the probe.
175 ierr = petibm::misc::createProbe(mesh->comm, config["probes"][i],
176 mesh, probes[i]); CHKERRQ(ierr);
177 }
178
179 // create an ASCII PetscViewer to output linear solvers info
181 config["output"].as<std::string>() +
182 "/iterations-" + std::to_string(ite) + ".txt",
183 FILE_MODE_WRITE, solversViewer); CHKERRQ(ierr);
184
185 // register logging stages
186 ierr = PetscLogStageRegister(
187 "rhsVelocity", &stageRHSVelocity); CHKERRQ(ierr);
188 ierr = PetscLogStageRegister(
189 "solveVelocity", &stageSolveVelocity); CHKERRQ(ierr);
190 ierr = PetscLogStageRegister(
191 "rhsPoisson", &stageRHSPoisson); CHKERRQ(ierr);
192 ierr = PetscLogStageRegister(
193 "solvePoisson", &stageSolvePoisson); CHKERRQ(ierr);
194 ierr = PetscLogStageRegister(
195 "update", &stageUpdate); CHKERRQ(ierr);
196 ierr = PetscLogStageRegister(
197 "write", &stageWrite); CHKERRQ(ierr);
198 ierr = PetscLogStageRegister(
199 "monitor", &stageMonitor); CHKERRQ(ierr);
200
201 ierr = PetscLogStagePop(); CHKERRQ(ierr); // end of stageInitialize
202
203 PetscFunctionReturn(0);
204} // init
205
206// read or write initial data
208{
209 PetscErrorCode ierr;
210
211 PetscFunctionBeginUser;
212
213 if (ite == 0) // write the initial solution fields to a HDF5 file
214 {
215 std::stringstream ss;
216 std::string filePath;
217 ss << std::setfill('0') << std::setw(7) << ite;
218 filePath = config["output"].as<std::string>() + "/" + ss.str() + ".h5";
219 ierr = PetscPrintf(comm, "[time step %d] Writing solution data... ",
220 ite); CHKERRQ(ierr);
221 ierr = writeSolutionHDF5(filePath); CHKERRQ(ierr);
222 ierr = PetscPrintf(comm, "done\n"); CHKERRQ(ierr);
223 }
224 else // read restart data from HDF5 file
225 {
226 std::stringstream ss;
227 std::string filePath;
228 ss << std::setfill('0') << std::setw(7) << ite;
229 filePath = config["output"].as<std::string>() + "/" + ss.str() + ".h5";
230 ierr = PetscPrintf(comm, "[time step %d] Reading restart data... ",
231 ite); CHKERRQ(ierr);
232 ierr = readRestartDataHDF5(filePath); CHKERRQ(ierr);
233 ierr = PetscPrintf(comm, "done\n"); CHKERRQ(ierr);
234 }
235
236 PetscFunctionReturn(0);
237} // ioInitialData
238
239// advance the flow solver by one time-step
241{
242 PetscErrorCode ierr;
243
244 PetscFunctionBeginUser;
245
246 t += dt;
247 ite++;
248
249 // prepare velocity system and solve it
250 ierr = assembleRHSVelocity(); CHKERRQ(ierr);
251 ierr = solveVelocity(); CHKERRQ(ierr);
252
253 // prepare Poisson system and solve it
254 ierr = assembleRHSPoisson(); CHKERRQ(ierr);
255 ierr = solvePoisson(); CHKERRQ(ierr);
256
257 // project velocity field onto divergence-free space
258 ierr = applyDivergenceFreeVelocity(); CHKERRQ(ierr);
259 // update pressure field
260 ierr = updatePressure(); CHKERRQ(ierr);
261
262 // update ghost-point values
263 ierr = bc->updateGhostValues(solution); CHKERRQ(ierr);
264
265 PetscFunctionReturn(0);
266} // advance
267
268// write solutions fields and linear solvers info to files
270{
271 PetscErrorCode ierr;
272
273 PetscFunctionBeginUser;
274
275 // write linear solvers info
276 ierr = writeLinSolversInfo(); CHKERRQ(ierr);
277
278 if (ite % nsave == 0) // write solution fields
279 {
280 std::stringstream ss;
281 std::string filePath;
282 ss << std::setfill('0') << std::setw(7) << ite;
283 filePath = config["output"].as<std::string>() + "/" + ss.str() + ".h5";
284 ierr = PetscPrintf(comm, "[time step %d] Writing solution data... ",
285 ite); CHKERRQ(ierr);
286 ierr = writeSolutionHDF5(filePath); CHKERRQ(ierr);
287 ierr = PetscPrintf(comm, "done\n"); CHKERRQ(ierr);
288 // output the PETSc log to an ASCII file
289 filePath = config["logs"].as<std::string>() + "/" + ss.str() + ".log";
290 ierr = petibm::io::writePetscLog(comm, filePath); CHKERRQ(ierr);
291 }
292 if (ite % nrestart == 0) // write restart data
293 {
294 std::string filePath;
295 std::stringstream ss;
296 ss << std::setfill('0') << std::setw(7) << ite;
297 filePath = config["output"].as<std::string>() + "/" + ss.str() + ".h5";
298 ierr = PetscPrintf(comm, "[time step %d] Writing restart data... ",
299 ite); CHKERRQ(ierr);
300 ierr = writeRestartDataHDF5(filePath); CHKERRQ(ierr);
301 ierr = PetscPrintf(comm, "done\n"); CHKERRQ(ierr);
302 }
303
304 // monitor probes and write to files
305 ierr = monitorProbes(); CHKERRQ(ierr);
306
307 PetscFunctionReturn(0);
308} // write
309
310// evaluate if the simulation is finished
312{
313 return ite >= nstart + nt;
314} // finished
315
316// create the linear operators of the solver (PETSc Mat objects)
318{
319 PetscErrorCode ierr;
320
321 PetscFunctionBeginUser;
322
323 Mat BN; // a temporary operator
324
325 // create the divergence operator: D
327 mesh, bc, D, DCorrection, PETSC_FALSE); CHKERRQ(ierr);
328
329 // create the gradient operator: G
331 mesh, G, PETSC_FALSE); CHKERRQ(ierr);
332
333 // create the Laplacian operator: L
335 mesh, bc, L, LCorrection); CHKERRQ(ierr);
336
337 // create the operator for the convective terms: N
339 mesh, bc, N); CHKERRQ(ierr);
340
341 // create the implicit operator of the velocity system: A
342 ierr = MatDuplicate(L, MAT_COPY_VALUES, &A); CHKERRQ(ierr);
343 ierr = MatScale(A, -diffCoeffs->implicitCoeff * nu); CHKERRQ(ierr);
344 ierr = MatShift(A, 1.0 / dt); CHKERRQ(ierr);
345
346 // create the projection operator: BNG
347 PetscInt N; // order of the truncate Taylor series expansion
348 N = config["parameters"]["BN"].as<PetscInt>(1);
350 L, dt, diffCoeffs->implicitCoeff * nu, N, BN); CHKERRQ(ierr);
351 ierr = MatMatMult(
352 BN, G, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &BNG); CHKERRQ(ierr);
353
354 // create the Poisson operator: DBNG
355 ierr = MatMatMult(
356 D, BNG, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &DBNG); CHKERRQ(ierr);
357
358 // set the nullspace of the Poisson system
359 ierr = setNullSpace(); CHKERRQ(ierr);
360
361 // destroy the temporary operator
362 ierr = MatDestroy(&BN); CHKERRQ(ierr);
363
364 PetscFunctionReturn(0);
365} // createOperators
366
367// create the vectors of the solver (PETSc Vec objects)
369{
370 PetscErrorCode ierr;
371
372 PetscFunctionBeginUser;
373
374 ierr = VecDuplicate(solution->pGlobal, &dP); CHKERRQ(ierr);
375 ierr = VecDuplicate(solution->UGlobal, &bc1); CHKERRQ(ierr);
376 ierr = VecDuplicate(solution->UGlobal, &rhs1); CHKERRQ(ierr);
377 ierr = VecDuplicate(solution->pGlobal, &rhs2); CHKERRQ(ierr);
378
379 conv.resize(convCoeffs->nExplicit);
380 for (unsigned int i = 0; i < conv.size(); ++i)
381 {
382 ierr = VecDuplicate(solution->UGlobal, &conv[i]); CHKERRQ(ierr);
383 }
384
385 diff.resize(diffCoeffs->nExplicit);
386 for (unsigned int i = 0; i < diff.size(); ++i)
387 {
388 ierr = VecDuplicate(solution->UGlobal, &diff[i]); CHKERRQ(ierr);
389 }
390
391 PetscFunctionReturn(0);
392} // createVectors
393
394// set the nullspace of the Poisson system
396{
397 PetscErrorCode ierr;
398
399 PetscFunctionBeginUser;
400
401 std::string type;
402 ierr = pSolver->getType(type); CHKERRQ(ierr);
403
404 if (type == "PETSc KSP")
405 {
406 MatNullSpace nsp;
407 ierr = MatNullSpaceCreate(
408 comm, PETSC_TRUE, 0, nullptr, &nsp); CHKERRQ(ierr);
409 ierr = MatSetNullSpace(DBNG, nsp); CHKERRQ(ierr);
410 ierr = MatSetNearNullSpace(DBNG, nsp); CHKERRQ(ierr);
411 ierr = MatNullSpaceDestroy(&nsp); CHKERRQ(ierr);
412 isRefP = PETSC_FALSE;
413 }
414 else if (type == "NVIDIA AmgX")
415 {
416 PetscInt row[1] = {0};
417 ierr = MatZeroRowsColumns(
418 DBNG, 1, row, 1.0, nullptr, nullptr); CHKERRQ(ierr);
419 isRefP = PETSC_TRUE;
420 }
421 else
422 {
423 SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
424 "Could not recognize the type of linear solver: %s\n",
425 type.c_str());
426 }
427
428 PetscFunctionReturn(0);
429} // setNullSpace
430
431// assemble the right-hand side vector of the velocity system
433{
434 PetscErrorCode ierr;
435
436 PetscFunctionBeginUser;
437
438 ierr = PetscLogStagePush(stageRHSVelocity); CHKERRQ(ierr);
439
440 // initialize RHS vector with pressure gradient at time-step n
441 // $rhs_1 = - \frac{\partial p^n}{\partial x}$
442 ierr = MatMult(G, solution->pGlobal, rhs1); CHKERRQ(ierr);
443 ierr = VecScale(rhs1, -1.0); CHKERRQ(ierr);
444
445 // add explicit part of time derivative to the RHS vector
446 // $rhs_1 += \frac{u^n}{\Delta t}$
447 ierr = VecAXPY(rhs1, 1.0 / dt, solution->UGlobal); CHKERRQ(ierr);
448
449 // add all explicit convective terms to the RHS vector
450 // $rhs_1 += \sum_{k=0}^s conv_{n - k}$
451 {
452 // 1. discard the term at the oldest time-step
453 // and decrease the time-step by 1
454 for (int i = conv.size() - 1; i > 0; i--)
455 {
456 ierr = VecSwap(conv[i], conv[i - 1]); CHKERRQ(ierr);
457 }
458
459 if (conv.size() > 0)
460 {
461 // 2. compute and store the convective term from time-step n
462 ierr = MatMult(N, solution->UGlobal, conv[0]); CHKERRQ(ierr);
463
464 // 3. scale the newest convective term by -1
465 // (to be added to the RHS vector)
466 ierr = VecScale(conv[0], -1.0); CHKERRQ(ierr);
467 }
468
469 // 4. add all explicit convective terms to the RHS vector
470 for (unsigned int i = 0; i < conv.size(); ++i)
471 {
472 ierr = VecAXPY(rhs1, convCoeffs->explicitCoeffs[i], conv[i]);
473 CHKERRQ(ierr);
474 }
475 }
476
477 // add all explicit diffusion terms to the RHS vector
478 // $rhs_1 += \sum_{k=0}^s diff_{n - k}$
479 {
480 // 1. discard the term at the oldest time-step
481 // and decrease the time-step by 1
482 for (int i = diff.size() - 1; i > 0; i--)
483 {
484 ierr = VecSwap(diff[i], diff[i - 1]); CHKERRQ(ierr);
485 }
486
487 // 2. compute and store the diffusion term from time-step n
488 if (diff.size() > 0)
489 {
490 ierr = MatMult(L, solution->UGlobal, diff[0]); CHKERRQ(ierr);
491 ierr = MatMultAdd(
492 LCorrection, solution->UGlobal, diff[0], diff[0]); CHKERRQ(ierr);
493 ierr = VecScale(diff[0], nu); CHKERRQ(ierr);
494 }
495
496 // 3. add all explicit diffusion terms to the RHS vector
497 for (unsigned int i = 0; i < diff.size(); ++i)
498 {
499 ierr = VecAXPY(
500 rhs1, diffCoeffs->explicitCoeffs[i], diff[i]); CHKERRQ(ierr);
501 }
502 }
503
504 // add implicit BC correction terms arising from the diffusion term
505 // to the RHS vector
506 {
507 // 1. update the ghost-point equations
508 ierr = bc->updateEqs(solution, dt); CHKERRQ(ierr);
509
510 // 2. compute the implicit BC correction terms
511 ierr = MatMult(LCorrection, solution->UGlobal, bc1); CHKERRQ(ierr);
512 ierr = VecScale(bc1, nu); CHKERRQ(ierr);
513
514 // 3. add the correction terms to the RHS vector
515 ierr = VecAXPY(rhs1, diffCoeffs->implicitCoeff, bc1); CHKERRQ(ierr);
516 }
517
518 ierr = PetscLogStagePop(); CHKERRQ(ierr); // end of stageRHSVelocity
519
520 PetscFunctionReturn(0);
521} // assembleRHSVelocity
522
523// solve the linear system for the velocity
525{
526 PetscErrorCode ierr;
527
528 PetscFunctionBeginUser;
529
530 ierr = PetscLogStagePush(stageSolveVelocity); CHKERRQ(ierr);
531
532 ierr = vSolver->solve(solution->UGlobal, rhs1); CHKERRQ(ierr);
533
534 ierr = PetscLogStagePop(); CHKERRQ(ierr); // end of stageSolveVelocity
535
536 PetscFunctionReturn(0);
537} // solveVelocity
538
539// assemble the right-hand side vector of the Poisson system
541{
542 PetscErrorCode ierr;
543
544 PetscFunctionBeginUser;
545
546 ierr = PetscLogStagePush(stageRHSPoisson); CHKERRQ(ierr);
547
548 // compute the divergence of the intermediate velocity field
549 ierr = MatMult(D, solution->UGlobal, rhs2); CHKERRQ(ierr);
550 ierr = MatMultAdd(DCorrection, solution->UGlobal, rhs2, rhs2);
551 CHKERRQ(ierr);
552
553 if (isRefP) // if the pressure is pinned at one point
554 {
555 ierr = VecSetValue(rhs2, 0, 0.0, INSERT_VALUES); CHKERRQ(ierr);
556 ierr = VecAssemblyBegin(rhs2); CHKERRQ(ierr);
557 ierr = VecAssemblyEnd(rhs2); CHKERRQ(ierr);
558 }
559
560 ierr = PetscLogStagePop(); CHKERRQ(ierr); // end of stageRHSPoisson
561
562 PetscFunctionReturn(0);
563} // assembleRHSPoisson
564
565// solve the Poisson linear system for the pressure correction
567{
568 PetscErrorCode ierr;
569
570 PetscFunctionBeginUser;
571
572 ierr = PetscLogStagePush(stageSolvePoisson); CHKERRQ(ierr);
573
574 // solve for the pressure correction
575 ierr = pSolver->solve(dP, rhs2); CHKERRQ(ierr);
576
577 ierr = PetscLogStagePop(); CHKERRQ(ierr); // end of stageSolvePoisson
578
579 PetscFunctionReturn(0);
580} // solvePoisson
581
582// project the velocity field onto the divergence-free space
584{
585 PetscErrorCode ierr;
586
587 PetscFunctionBeginUser;
588
589 ierr = PetscLogStagePush(stageUpdate); CHKERRQ(ierr);
590
591 // u = u - BN G dp
592 ierr = MatMult(BNG, dP, rhs1); CHKERRQ(ierr);
593 ierr = VecAXPY(solution->UGlobal, -1.0, rhs1); CHKERRQ(ierr);
594
595 ierr = PetscLogStagePop(); CHKERRQ(ierr); // end of stageUpdate
596
597 PetscFunctionReturn(0);
598} // applyDivergenceFreeVelocity
599
600// update pressure field variable
602{
603 PetscErrorCode ierr;
604
605 PetscFunctionBeginUser;
606
607 ierr = PetscLogStagePush(stageUpdate); CHKERRQ(ierr);
608
609 // p = p + dp
610 ierr = VecAXPY(solution->pGlobal, 1.0, dP); CHKERRQ(ierr);
611
612 ierr = PetscLogStagePop(); CHKERRQ(ierr); // end of stageUpdate
613
614 PetscFunctionReturn(0);
615} // updatePressure
616
617// write the solution fields into a HDF5 file
618PetscErrorCode NavierStokesSolver::writeSolutionHDF5(const std::string &filePath)
619{
620 PetscErrorCode ierr;
621
622 PetscFunctionBeginUser;
623
624 ierr = PetscLogStagePush(stageWrite); CHKERRQ(ierr);
625
626 // write the solution fields to a file
627 ierr = solution->write(filePath); CHKERRQ(ierr);
628 // write the time value as an attribute of the pressure field dataset
629 ierr = writeTimeHDF5(t, filePath); CHKERRQ(ierr);
630
631 ierr = PetscLogStagePop(); CHKERRQ(ierr); // end of stageWrite
632
633 PetscFunctionReturn(0);
634} // writeSolutionHDF5
635
636// write all data required to restart a simulation into a HDF5 file
638 const std::string &filePath)
639{
640 PetscErrorCode ierr;
641 PetscViewer viewer;
642 PetscBool fileExist = PETSC_FALSE;
643
644 PetscFunctionBeginUser;
645
646 ierr = PetscLogStagePush(stageWrite); CHKERRQ(ierr);
647
648 // check if file exist
649 ierr = PetscTestFile(filePath.c_str(), 'w', &fileExist); CHKERRQ(ierr);
650
651 if (!fileExist) // if not, create one and write field solution into it
652 {
653 ierr = writeSolutionHDF5(filePath); CHKERRQ(ierr);
654 }
655
656 // create PetscViewer object with append mode
657 ierr = PetscViewerCreate(comm, &viewer); CHKERRQ(ierr);
658 ierr = PetscViewerSetType(viewer, PETSCVIEWERHDF5); CHKERRQ(ierr);
659 ierr = PetscViewerFileSetMode(viewer, FILE_MODE_APPEND); CHKERRQ(ierr);
660 ierr = PetscViewerFileSetName(viewer, filePath.c_str()); CHKERRQ(ierr);
661
662 // go to the root node first (just in case, not necessary)
663 ierr = PetscViewerHDF5PushGroup(viewer, "/"); CHKERRQ(ierr);
664
665 // write explicit convective terms
666 ierr = PetscViewerHDF5PushGroup(viewer, "/convection"); CHKERRQ(ierr);
667 for (unsigned int i = 0; i < conv.size(); ++i)
668 {
669 ierr = PetscObjectSetName(
670 (PetscObject)conv[i], std::to_string(i).c_str()); CHKERRQ(ierr);
671 ierr = VecView(conv[i], viewer); CHKERRQ(ierr);
672 }
673 // write explicit diffusion terms
674 ierr = PetscViewerHDF5PushGroup(viewer, "/diffusion"); CHKERRQ(ierr);
675 for (unsigned int i = 0; i < diff.size(); ++i)
676 {
677 ierr = PetscObjectSetName(
678 (PetscObject)diff[i], std::to_string(i).c_str()); CHKERRQ(ierr);
679 ierr = VecView(diff[i], viewer); CHKERRQ(ierr);
680 }
681
682 // destroy viewer
683 ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
684
685 ierr = PetscLogStagePop(); CHKERRQ(ierr); // end of stageWrite
686
687 PetscFunctionReturn(0);
688} // writeRestartDataHDF5
689
690// read all data required to restart a simulation into a HDF5 file
692 const std::string &filePath)
693{
694 PetscErrorCode ierr;
695 PetscViewer viewer;
696 PetscBool fileExist = PETSC_FALSE;
697
698 PetscFunctionBeginUser;
699
700 // check if file exist
701 ierr = PetscTestFile(filePath.c_str(), 'r', &fileExist); CHKERRQ(ierr);
702
703 if (!fileExist) // if the not, return error
704 SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_FILE_READ,
705 "Could not find file \"%s\" for restarting.\n",
706 filePath.c_str());
707
708 // read primary fields
709 ierr = solution->read(filePath); CHKERRQ(ierr);
710 ierr = readTimeHDF5(filePath, t); CHKERRQ(ierr);
711
712 // create a PetscViewer object with append mode
713 ierr = PetscViewerCreate(comm, &viewer); CHKERRQ(ierr);
714 ierr = PetscViewerSetType(viewer, PETSCVIEWERHDF5); CHKERRQ(ierr);
715 ierr = PetscViewerFileSetMode(viewer, FILE_MODE_READ); CHKERRQ(ierr);
716 ierr = PetscViewerFileSetName(viewer, filePath.c_str()); CHKERRQ(ierr);
717
718 // go to the root node first (just in case, not necessary)
719 ierr = PetscViewerHDF5PushGroup(viewer, "/"); CHKERRQ(ierr);
720
721 // read explicit convective terms
722 ierr = PetscViewerHDF5PushGroup(viewer, "/convection"); CHKERRQ(ierr);
723 for (unsigned int i = 0; i < conv.size(); ++i)
724 {
725 ierr = PetscObjectSetName(
726 (PetscObject)conv[i], std::to_string(i).c_str()); CHKERRQ(ierr);
727 ierr = VecLoad(conv[i], viewer); CHKERRQ(ierr);
728 }
729 // read explicit diffusion terms
730 ierr = PetscViewerHDF5PushGroup(viewer, "/diffusion"); CHKERRQ(ierr);
731 for (unsigned int i = 0; i < diff.size(); ++i)
732 {
733 ierr = PetscObjectSetName(
734 (PetscObject)diff[i], std::to_string(i).c_str()); CHKERRQ(ierr);
735 ierr = VecLoad(diff[i], viewer); CHKERRQ(ierr);
736 }
737
738 // destroy viewer
739 ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
740
741 // update ghost-point values and equations based on the current solutio
742 // TODO: for convective BCs, it's not totally correct
743 ierr = bc->setGhostICs(solution); CHKERRQ(ierr);
744
745 PetscFunctionReturn(0);
746} // readRestartDataHDF5
747
748// initialize an ASCII PetscViewer object
750 const std::string &filePath, const PetscFileMode &mode,
751 PetscViewer &viewer)
752{
753 PetscErrorCode ierr;
754
755 PetscFunctionBeginUser;
756
757 ierr = PetscViewerCreate(comm, &viewer); CHKERRQ(ierr);
758 ierr = PetscViewerSetType(viewer, PETSCVIEWERASCII); CHKERRQ(ierr);
759 ierr = PetscViewerFileSetMode(viewer, mode); CHKERRQ(ierr);
760 ierr = PetscViewerFileSetName(viewer, filePath.c_str()); CHKERRQ(ierr);
761
762 PetscFunctionReturn(0);
763} // createPetscViewerASCII
764
765// write numbers of iterations and residuals of linear solvers to an ASCII file
767{
768 PetscErrorCode ierr;
769 PetscInt nIters;
770 PetscReal res;
771
772 PetscFunctionBeginUser;
773
774 ierr = PetscLogStagePush(stageWrite); CHKERRQ(ierr);
775
776 // write the time value
777 ierr = PetscViewerASCIIPrintf(solversViewer, "%d\t", ite); CHKERRQ(ierr);
778
779 // write iterations number and residual for the velocity solver
780 ierr = vSolver->getIters(nIters); CHKERRQ(ierr);
781 ierr = vSolver->getResidual(res); CHKERRQ(ierr);
782 ierr = PetscViewerASCIIPrintf(
783 solversViewer, "%d\t%e\t", nIters, res); CHKERRQ(ierr);
784
785 // write iterations number and residual for the Poisson solver
786 ierr = pSolver->getIters(nIters); CHKERRQ(ierr);
787 ierr = pSolver->getResidual(res); CHKERRQ(ierr);
788 ierr = PetscViewerASCIIPrintf(
789 solversViewer, "%d\t%e\n", nIters, res); CHKERRQ(ierr);
790
791 ierr = PetscLogStagePop(); CHKERRQ(ierr); // end of stageWrite
792
793 PetscFunctionReturn(0);
794} // writeLinSolversInfo
795
796// write the time value into a HDF5 file
797PetscErrorCode NavierStokesSolver::writeTimeHDF5(const PetscReal &t,
798 const std::string &filePath)
799{
800 PetscErrorCode ierr;
801 PetscViewer viewer;
802
803 PetscFunctionBeginUser;
804
805 ierr = PetscViewerCreate(comm, &viewer); CHKERRQ(ierr);
806 ierr = PetscViewerSetType(viewer, PETSCVIEWERHDF5); CHKERRQ(ierr);
807 ierr = PetscViewerFileSetMode(viewer, FILE_MODE_APPEND); CHKERRQ(ierr);
808 ierr = PetscViewerFileSetName(viewer, filePath.c_str()); CHKERRQ(ierr);
809 // attribute has to belong to an existing dataset (choosing p)
810 ierr = PetscViewerHDF5WriteAttribute(
811 viewer, "/p", "time", PETSC_DOUBLE, &t); CHKERRQ(ierr);
812 ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
813
814 PetscFunctionReturn(0);
815} // writeTimeHDF5
816
817// read the time value from a HDF5 file
818PetscErrorCode NavierStokesSolver::readTimeHDF5(const std::string &filePath,
819 PetscReal &t)
820{
821 PetscErrorCode ierr;
822 PetscViewer viewer;
823
824 PetscFunctionBeginUser;
825
826 ierr = PetscViewerCreate(comm, &viewer); CHKERRQ(ierr);
827 ierr = PetscViewerSetType(viewer, PETSCVIEWERHDF5); CHKERRQ(ierr);
828 ierr = PetscViewerFileSetMode(viewer, FILE_MODE_READ); CHKERRQ(ierr);
829 ierr = PetscViewerFileSetName(viewer, filePath.c_str()); CHKERRQ(ierr);
830 // attribute has to belong to an existing dataset (choosing p)
831 ierr = PetscViewerHDF5ReadAttribute(
832 viewer, "/p", "time", PETSC_DOUBLE, nullptr, &t);
833 CHKERRQ(ierr);
834 ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
835
836 PetscFunctionReturn(0);
837} // readTimeHDF5
838
839// monitor the solution at probes
841{
842 PetscErrorCode ierr;
843
844 PetscFunctionBeginUser;
845
846 ierr = PetscLogStagePush(stageMonitor); CHKERRQ(ierr);
847
848 for (auto probe : probes)
849 {
850 ierr = probe->monitor(solution, mesh, ite, t); CHKERRQ(ierr);
851 }
852
853 ierr = PetscLogStagePop(); CHKERRQ(ierr); // end of stageMonitor
854
855 PetscFunctionReturn(0);
856} // monitorProbes
857
Vec rhs2
Right-hand side vector of the Poisson system.
Definition: navierstokes.h:173
petibm::type::Solution solution
Data object holding the velocity and pressure fields.
Definition: navierstokes.h:95
petibm::type::LinSolver pSolver
Poisson linear solver.
Definition: navierstokes.h:107
PetscReal nu
Viscous diffusion coefficient.
Definition: navierstokes.h:134
PetscInt nstart
Starting time-step index.
Definition: navierstokes.h:122
PetscLogStage stageMonitor
Log stage for monitoring user-defined regions of the domain.
Definition: navierstokes.h:206
Mat L
Laplacian operator.
Definition: navierstokes.h:137
Vec bc1
Inhomogeneous boundary terms for the velocity system.
Definition: navierstokes.h:167
PetscLogStage stageSolvePoisson
Log stage for solving the Poisson system.
Definition: navierstokes.h:197
PetscErrorCode ioInitialData()
Read or write initial data.
PetscReal t
Time value.
Definition: navierstokes.h:119
YAML::Node config
YAML configuration settings.
Definition: navierstokes.h:86
std::vector< petibm::type::Probe > probes
Probes to monitor the solution.
Definition: navierstokes.h:110
petibm::type::Boundary bc
Information about the domain boundaries.
Definition: navierstokes.h:92
NavierStokesSolver()=default
Default constructor.
PetscInt nsave
Frequency at which the solution fields are written to files.
Definition: navierstokes.h:128
virtual PetscErrorCode updatePressure()
virtual PetscErrorCode assembleRHSVelocity()
Assemble the RHS vector of the velocity system.
PetscErrorCode advance()
Advance the solution by one time step.
virtual PetscErrorCode readRestartDataHDF5(const std::string &filePath)
Read data required to restart a simulation from a HDF5 file.
petibm::type::TimeIntegration convCoeffs
Time scheme for the convective terms.
Definition: navierstokes.h:98
virtual PetscErrorCode writeLinSolversInfo()
Write numbers of iterations and residuals of solvers to file.
PetscLogStage stageInitialize
Log stage for the initialization phase.
Definition: navierstokes.h:185
virtual PetscErrorCode readTimeHDF5(const std::string &filePath, PetscReal &t)
Read the time value from a HDF5 file.
bool finished()
Evaluate if the simulation is finished.
Vec rhs1
Right-hand side vector of the velocity system.
Definition: navierstokes.h:170
Vec dP
Pressure-correction vector.
Definition: navierstokes.h:164
virtual PetscErrorCode writeSolutionHDF5(const std::string &filePath)
Write the solution fields into a HDF5 file.
Mat A
Implicit operator for the velocity solver.
Definition: navierstokes.h:155
Mat G
Gradient operator.
Definition: navierstokes.h:143
virtual PetscErrorCode createOperators()
Create operators.
petibm::type::LinSolver vSolver
Velocity linear solver.
Definition: navierstokes.h:104
PetscMPIInt commRank
Rank of the process in the MPI communicator.
Definition: navierstokes.h:83
PetscReal dt
Time-step size.
Definition: navierstokes.h:113
Mat N
Convective operator (matrix-free).
Definition: navierstokes.h:152
Mat LCorrection
Laplacian correction operator for boundary conditions.
Definition: navierstokes.h:140
std::vector< Vec > conv
Explicit convective terms.
Definition: navierstokes.h:176
virtual PetscErrorCode assembleRHSPoisson()
Assemble the RHS vector of the Poisson system.
MPI_Comm comm
MPI communicator.
Definition: navierstokes.h:77
virtual PetscErrorCode solvePoisson()
Solve the Poisson system.
virtual PetscErrorCode writeRestartDataHDF5(const std::string &filePath)
Write data required to restart a simulation into a HDF5 file.
PetscBool isRefP
True if we pin the pressure at a reference point.
Definition: navierstokes.h:182
~NavierStokesSolver()
Default destructor.
petibm::type::TimeIntegration diffCoeffs
Time scheme for the diffusion terms.
Definition: navierstokes.h:101
virtual PetscErrorCode applyDivergenceFreeVelocity()
PetscInt nrestart
Frequency at which data to restart are written to files.
Definition: navierstokes.h:131
Mat DCorrection
Divergence correction for boundary conditions.
Definition: navierstokes.h:149
PetscMPIInt commSize
Size of the MPI communicator.
Definition: navierstokes.h:80
PetscLogStage stageRHSVelocity
Log stage for assembling the RHS of the velocity system.
Definition: navierstokes.h:188
PetscErrorCode write()
Write solution and solver info to files.
PetscErrorCode init(const MPI_Comm &world, const YAML::Node &node)
Initialize the Navier-Stokes solver.
virtual PetscErrorCode setNullSpace()
Set Poisson nullspace or pin pressure at a reference point.
PetscLogStage stageWrite
Log stage when write the solution fields.
Definition: navierstokes.h:203
std::vector< Vec > diff
Explicit diffusion terms.
Definition: navierstokes.h:179
PetscLogStage stageUpdate
Log stage for updating field variables.
Definition: navierstokes.h:200
PetscInt ite
Time-step index.
Definition: navierstokes.h:116
petibm::type::Mesh mesh
Structured Cartesian mesh object.
Definition: navierstokes.h:89
PetscLogStage stageSolveVelocity
Log stage for solving the velocity system.
Definition: navierstokes.h:191
PetscLogStage stageRHSPoisson
Log stage for assembling the RHS of the Poisson system.
Definition: navierstokes.h:194
virtual PetscErrorCode solveVelocity()
Solve the velocity system.
virtual PetscErrorCode monitorProbes()
Monitor the solution at probes.
Mat BNG
Projection operator.
Definition: navierstokes.h:158
PetscInt nt
Number of time steps to compute.
Definition: navierstokes.h:125
virtual PetscErrorCode writeTimeHDF5(const PetscReal &t, const std::string &filePath)
Write the time value into a HDF5 file.
virtual PetscErrorCode createVectors()
Create vectors.
PetscErrorCode destroy()
Manually destroy data.
Mat D
Divergence operator.
Definition: navierstokes.h:146
virtual PetscErrorCode createPetscViewerASCII(const std::string &filePath, const PetscFileMode &mode, PetscViewer &viewer)
Create an ASCII PetscViewer.
Mat DBNG
Poisson operator.
Definition: navierstokes.h:161
PetscViewer solversViewer
ASCII PetscViewer object to output solvers info.
Definition: navierstokes.h:209
PetscErrorCode createBoundary(const type::Mesh &mesh, const YAML::Node &node, type::Boundary &boundary)
Create a Boundary object.
Definition: boundary.cpp:41
PetscErrorCode createLinSolver(const std::string &solverName, const YAML::Node &node, type::LinSolver &solver)
A factory function for creating a LinSolver.
Definition: linsolver.cpp:57
PetscErrorCode createMesh(const MPI_Comm &comm, const YAML::Node &node, type::Mesh &mesh)
Factory function for creating a Mesh object.
Definition: mesh.cpp:86
PetscErrorCode writePetscLog(const MPI_Comm comm, const std::string &filePath)
Write a summary of the PETSc logging into a ASCII file.
Definition: io.cpp:274
PetscErrorCode createProbe(const MPI_Comm &comm, const YAML::Node &node, const type::Mesh &mesh, type::Probe &probe)
Factory function to create a probe to monitor the solution.
Definition: probes.cpp:23
PetscErrorCode createDivergence(const type::Mesh &mesh, const type::Boundary &bc, Mat &D, Mat &DCorrection, const PetscBool &normalize=PETSC_TRUE)
Create a divergence operator, , and corresponding boundary correction, , for velocity fields.
PetscErrorCode createGradient(const type::Mesh &mesh, Mat &G, const PetscBool &normalize=PETSC_TRUE)
Create a gradient operator, , for pressure field.
PetscErrorCode createLaplacian(const type::Mesh &mesh, const type::Boundary &bc, Mat &L, Mat &LCorrection)
Create a Laplacian operator, , and boundary correction, for velocity fields.
PetscErrorCode createBnHead(const Mat &Op, const PetscReal &dt, const PetscReal &coeff, const PetscInt &n, Mat &BnHead)
Create non-normalized matrix of approximated , .
Definition: createbn.cpp:19
PetscErrorCode createConvection(const type::Mesh &mesh, const type::Boundary &bc, Mat &H)
Create a matrix-free Mat for convection operator, .
PetscErrorCode createSolution(const type::Mesh &mesh, type::Solution &solution)
Factory function to create a petibm::solution::Solution object.
Definition: solution.cpp:65
PetscErrorCode createTimeIntegration(const std::string &name, const YAML::Node &node, type::TimeIntegration &integration)
factory function for type::TimeIntegration.
Prototypes of I/O functions.
Definition of the class NavierStokesSolver.