PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
Functions
poisson.h File Reference

Pressure-Poisson projection: the multigrid pressure-correction solve, the pressure update, and the velocity correction that makes Ucont divergence-free. More...

#include "variables.h"
#include "Boundaries.h"
Include dependency graph for poisson.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

PetscErrorCode PoissonSolver_Multigrid (UserMG *usermg)
 Solves the pressure-correction equation for every block with geometric multigrid.
 
PetscErrorCode AssemblePoissonOperator (UserCtx *user)
 Assembles the pressure-correction operator on one multigrid level.
 
PetscErrorCode ComputePoissonRHS (UserCtx *user, Vec B)
 Forms the right-hand side of the pressure-correction equation.
 
PetscErrorCode UpdatePressure (UserCtx *user)
 Adds the pressure correction to the pressure, P += Phi, and refreshes both fields' periodic images and ghosts.
 
PetscErrorCode ProjectVelocity (UserCtx *user)
 Corrects the contravariant flux with the gradient of Phi.
 

Detailed Description

Pressure-Poisson projection: the multigrid pressure-correction solve, the pressure update, and the velocity correction that makes Ucont divergence-free.

The discrete operator, the right-hand side, and the projection gradient are built from one face-gradient definition, so the Laplacian the solver inverts is exactly the divergence of the gradient the projection applies.

Every masked operation reads the solid field from the UserCtx of the level it acts on (lNvert). Solid cells are excluded from the operator, the right-hand side, the projection, and the multigrid transfers; cells next to a solid face use one-sided transverse differences.

Definition in file poisson.h.

Function Documentation

◆ PoissonSolver_Multigrid()

PetscErrorCode PoissonSolver_Multigrid ( UserMG *  usermg)
extern

Solves the pressure-correction equation for every block with geometric multigrid.

On the first call for a block, assembles the operator on every multigrid level and builds the outer Krylov solver with its PCMG preconditioner, grid transfers, level smoothers, coarse solve, and null space. The solver is kept in the finest level's UserCtx::ksp and reused on every later call; it is destroyed with the context.

Each call refreshes the ghosted contravariant flux, forms the right-hand side, solves for Phi on the finest level, and appends the iteration history to Poisson_Solver_Convergence_History_Block_<bi>.log in the run's log directory.

Solver controls are read from PETSc options under the ps_ prefix (-ps_ksp_*, -ps_mg_levels_N_*, -ps_mg_coarse_*) when the solver is built.

Parameters
[in,out]usermgMultigrid hierarchy; the finest level's Phi receives the solution.
Returns
PETSc error code. A non-finite residual or a preconditioner that could not be built stops the run with PETSC_ERR_NOT_CONVERGED.

Solves the pressure-correction equation for every block with geometric multigrid.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/poisson.h.

See also
PoissonSolver_Multigrid()

Definition at line 952 of file poisson.c.

953{
954 SimCtx *simCtx = usermg->mgctx[0].user[0].simCtx;
955 const FieldId staggered_fields[] = {FIELD_ID_UCONT};
956
957 PetscFunctionBeginUser;
959 LOG_ALLOW(GLOBAL, LOG_INFO, "Starting Multigrid Poisson Solve...\n");
960
961 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
962 UserCtx *user = &usermg->mgctx[usermg->mglevels - 1].user[bi];
963 KSPConvergedReason reason;
964
965 if (!user->ksp) PetscCall(PoissonMultigrid_Build(usermg, bi));
966
967 PetscCall(SynchronizePeriodicStaggeredFields(user, 1, staggered_fields));
968 PetscCall(ComputePoissonRHS(user, user->B));
969
970 PetscCall(PoissonMultigrid_OpenConvergenceLog(user->ksp, simCtx, bi));
971 PetscCall(KSPSolve(user->ksp, user->B, user->Phi));
973
974 /* A non-finite residual or a preconditioner that could not be built leaves Phi
975 meaningless, and the projection would carry it into the next momentum step,
976 where it surfaces as a failure of the wrong solver. Stopping at max_it is this
977 solve's normal mode and stays silent; any other divergence is reported, because
978 the projection proceeds on that Phi. */
979 PetscCall(KSPGetConvergedReason(user->ksp, &reason));
980 PetscCheck(reason != KSP_DIVERGED_NANORINF && reason != KSP_DIVERGED_PC_FAILED,
981 PETSC_COMM_WORLD, PETSC_ERR_NOT_CONVERGED,
982 "Pressure Poisson solve on block %" PetscInt_FMT " failed at step %" PetscInt_FMT
983 " (KSP reason %s). Known causes: a multigrid hierarchy coarsened too far "
984 "(reduce poisson_solver.multigrid.levels or refine the grid), or a momentum "
985 "field that has already diverged, such as an explicit time step beyond its "
986 "stability limit.",
987 bi, simCtx->step, KSPConvergedReasons[reason]);
988 if (reason < 0 && reason != KSP_DIVERGED_ITS) {
989 LOG(GLOBAL, LOG_WARNING, "Pressure Poisson solve on block %" PetscInt_FMT
990 " diverged at step %" PetscInt_FMT " (KSP reason %s); the projection uses the last iterate.\n",
991 bi, simCtx->step, KSPConvergedReasons[reason]);
992 }
993 }
994
995 LOG_ALLOW(GLOBAL, LOG_INFO, "Multigrid Poisson Solve complete.\n");
997 PetscFunctionReturn(0);
998}
PetscErrorCode SynchronizePeriodicStaggeredFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes persistent component-staggered vector fields.
FieldId
Compile-time identity for a catalogued Eulerian field.
@ FIELD_ID_UCONT
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:46
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
Definition logging.h:200
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:894
#define LOG(scope, level, fmt,...)
Logging macro for PETSc-based applications with scope control.
Definition logging.h:84
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:31
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:30
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Definition logging.h:885
static PetscErrorCode PoissonMultigrid_CloseConvergenceLog(KSP ksp)
Closes the log file opened by PoissonMultigrid_OpenConvergenceLog().
Definition poisson.c:931
static PetscErrorCode PoissonMultigrid_OpenConvergenceLog(KSP ksp, SimCtx *simCtx, PetscInt bi)
Prepares the convergence monitor for one solve and opens its log file on rank 0.
Definition poisson.c:902
PetscErrorCode ComputePoissonRHS(UserCtx *user, Vec B)
Implementation of ComputePoissonRHS().
Definition poisson.c:353
static PetscErrorCode PoissonMultigrid_Build(UserMG *usermg, PetscInt bi)
Builds the multigrid solver for block bi and stores it in the finest level.
Definition poisson.c:793
UserCtx * user
Definition variables.h:729
PetscInt block_number
Definition variables.h:952
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:1077
PetscInt mglevels
Definition variables.h:736
PetscInt step
Definition variables.h:867
MGCtx * mgctx
Definition variables.h:739
The master context for the entire simulation.
Definition variables.h:859
User-defined context containing data specific to a single computational grid level.
Definition variables.h:1074
Here is the call graph for this function:
Here is the caller graph for this function:

◆ AssemblePoissonOperator()

PetscErrorCode AssemblePoissonOperator ( UserCtx *  user)
extern

Assembles the pressure-correction operator on one multigrid level.

Allocates user->A on the first call and reassembles its entries on later calls into the same nonzero structure. Fluid rows carry the 19-point curvilinear Laplacian; dummy rows on the domain boundary and solid rows are identities. Non-periodic faces are homogeneous Neumann; periodic faces wrap to the opposite interior layer.

Parameters
[in,out]userLevel context supplying metrics, lNvert, and boundary types.
Returns
PETSc error code.

Assembles the pressure-correction operator on one multigrid level.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/poisson.h.

See also
AssemblePoissonOperator()

Definition at line 251 of file poisson.c.

252{
253 const DMDALocalInfo info = user->info;
254 const PetscInt m[3] = {info.mx, info.my, info.mz};
255 PetscBool periodic[3];
256 PoissonFaceMetrics metrics;
257 const PetscReal ***nvert, ***aj;
258 AO ao;
259
260 PetscFunctionBeginUser;
262
263 if (!user->A) {
264 PetscInt local_rows;
265 PetscCall(VecGetLocalSize(user->Phi, &local_rows));
266 PetscCall(MatCreateAIJ(PETSC_COMM_WORLD, local_rows, local_rows, m[0] * m[1] * m[2], m[0] * m[1] * m[2],
267 19, NULL, 19, NULL, &user->A));
268 }
269 PetscCall(MatZeroEntries(user->A));
270
271 PoissonOperator_PeriodicAxes(user, periodic);
272 PetscCall(DMDAGetAO(user->da, &ao));
273 PetscCall(PoissonOperator_GetFaceMetrics(user, &metrics));
274 PetscCall(DMDAVecGetArrayRead(user->da, user->lNvert, (void *)&nvert));
275 PetscCall(DMDAVecGetArrayRead(user->da, user->lAj, (void *)&aj));
276
277 for (PetscInt k = info.zs; k < info.zs + info.zm; k++) {
278 for (PetscInt j = info.ys; j < info.ys + info.ym; j++) {
279 for (PetscInt i = info.xs; i < info.xs + info.xm; i++) {
280 const PetscInt c[3] = {i, j, k};
281 PetscInt row = i + j * m[0] + k * m[0] * m[1];
282 PetscInt columns[19];
283 PetscScalar coefficients[19] = {0.0};
284
285 PetscCall(AOApplicationToPetsc(ao, 1, &row));
286 if (i == 0 || i == m[0] - 1 || j == 0 || j == m[1] - 1 || k == 0 || k == m[2] - 1) {
287 const PetscScalar one = 1.0;
288 PetscCall(MatSetValues(user->A, 1, &row, 1, &row, &one, INSERT_VALUES));
289 continue;
290 }
291
292 for (PetscInt s = 0; s < 19; s++) {
293 const PetscInt *d = POISSON_STENCIL_OFFSETS[s];
294 columns[s] = PoissonOperator_NeighborIndex(i, d[0], m[0], periodic[0]) +
295 PoissonOperator_NeighborIndex(j, d[1], m[1], periodic[1]) * m[0] +
296 PoissonOperator_NeighborIndex(k, d[2], m[2], periodic[2]) * m[0] * m[1];
297 }
298 PetscCall(AOApplicationToPetsc(ao, 19, columns));
299
300 if (nvert[k][j][i] > POISSON_SOLID_THRESHOLD) {
301 /* Solid rows keep the fluid row's structure with zero couplings, so a
302 solid field that changes during a run reassembles in place. */
303 coefficients[0] = 1.0;
304 PetscCall(MatSetValues(user->A, 1, &row, 19, columns, coefficients, INSERT_VALUES));
305 continue;
306 }
307
308 /* Faces in the order east, west, north, south, top, bottom. Non-periodic
309 boundary faces carry no flux (homogeneous Neumann). */
310 for (PetscInt n = 0; n < 3; n++) {
311 const PetscInt first = periodic[n] ? 0 : 1;
312 const PetscInt last = periodic[n] ? m[n] - 1 : m[n] - 2;
313 for (PetscInt side = 0; side < 2; side++) {
314 PetscInt across[3] = {0, 0, 0}, own[3] = {0, 0, 0}, face_cell[3] = {i, j, k};
315 const PetscBool upper = (PetscBool)(side == 0);
316
317 across[n] = upper ? 1 : -1;
318 if (PoissonOperator_At(nvert, c, across) >= POISSON_SOLID_THRESHOLD) continue;
319 if (c[n] == (upper ? last : first)) continue;
320 if (!upper) { own[n] = -1; face_cell[n] -= 1; }
321
322 const PoissonFaceGradient face =
323 PoissonOperator_FaceGradientStencil(&metrics, nvert, face_cell, n, m, periodic);
324 PoissonOperator_AddFaceFlux(&face, own, n, upper ? 1.0 : -1.0, coefficients);
325 }
326 }
327
328 for (PetscInt s = 0; s < 19; s++) coefficients[s] *= -aj[k][j][i];
329 PetscCall(MatSetValues(user->A, 1, &row, 19, columns, coefficients, INSERT_VALUES));
330 }
331 }
332 }
333
334 PetscCall(DMDAVecRestoreArrayRead(user->da, user->lAj, (void *)&aj));
335 PetscCall(DMDAVecRestoreArrayRead(user->da, user->lNvert, (void *)&nvert));
336 PetscCall(PoissonOperator_RestoreFaceMetrics(user, &metrics));
337 PetscCall(MatAssemblyBegin(user->A, MAT_FINAL_ASSEMBLY));
338 PetscCall(MatAssemblyEnd(user->A, MAT_FINAL_ASSEMBLY));
339
340 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Poisson operator assembled on level %d.\n", user->thislevel);
342 PetscFunctionReturn(0);
343}
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:32
static PetscInt PoissonOperator_NeighborIndex(PetscInt v, PetscInt d, PetscInt m, PetscBool periodic)
Index of the neighbour at offset d (-1, 0, +1) from v on an axis of m points, wrapping between the in...
Definition poisson.c:198
static PetscErrorCode PoissonOperator_RestoreFaceMetrics(UserCtx *user, PoissonFaceMetrics *metrics)
Returns the arrays borrowed by PoissonOperator_GetFaceMetrics().
Definition poisson.c:178
static const PetscInt POISSON_STENCIL_OFFSETS[19][3]
Offsets of the 19 stencil points, in the column order used to insert each row.
Definition poisson.c:29
static void PoissonOperator_AddFaceFlux(const PoissonFaceGradient *face, const PetscInt own[3], PetscInt n, PetscReal sign, PetscScalar coefficients[19])
Adds the signed gradient flux through one face to a row's stencil coefficients.
Definition poisson.c:214
#define POISSON_SOLID_THRESHOLD
Cells whose nvert exceeds this value are solid.
Definition poisson.c:26
static PetscReal PoissonOperator_At(const PetscReal ***field, const PetscInt c[3], const PetscInt d[3])
Value of a cell-centred array at cell c displaced by d.
Definition poisson.c:85
static PetscErrorCode PoissonOperator_GetFaceMetrics(UserCtx *user, PoissonFaceMetrics *metrics)
Borrows read access to the face metric arrays of user.
Definition poisson.c:161
static void PoissonOperator_PeriodicAxes(const UserCtx *user, PetscBool periodic[3])
Records which axes are periodic, from the negative face of each axis.
Definition poisson.c:92
static PoissonFaceGradient PoissonOperator_FaceGradientStencil(const PoissonFaceMetrics *metrics, const PetscReal ***nvert, const PetscInt c[3], PetscInt n, const PetscInt m[3], const PetscBool periodic[3])
Gathers the metric coefficients and transverse differences of the gradient flux through the face betw...
Definition poisson.c:140
Everything needed to evaluate the gradient flux through one face.
Definition poisson.c:52
Read-only face metric arrays: metric[n][b] is F_b on the n-faces.
Definition poisson.c:59
Vec lNvert
Definition variables.h:1113
PetscInt thislevel
Definition variables.h:1165
DMDALocalInfo info
Definition variables.h:1086
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ComputePoissonRHS()

PetscErrorCode ComputePoissonRHS ( UserCtx *  user,
Vec  B 
)
extern

Forms the right-hand side of the pressure-correction equation.

Writes the scaled divergence of the ghosted contravariant flux lUcont into B, zero on dummy and solid cells, and stores its domain integral in SimCtx::poissonSourceImbalance.

Parameters
[in]userFinest-level context.
[out]BRight-hand-side vector on user->da.
Returns
PETSc error code.

Forms the right-hand side of the pressure-correction equation.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/poisson.h.

See also
ComputePoissonRHS()

Definition at line 353 of file poisson.c.

354{
355 SimCtx *simCtx = user->simCtx;
356 const DMDALocalInfo info = user->info;
357 const PetscInt mx = info.mx, my = info.my, mz = info.mz;
358 const PetscReal dt = simCtx->dt;
359 const Cmpnts ***ucont;
360 const PetscReal ***nvert, ***aj;
361 PetscReal ***rhs;
362 PetscReal local_sum = 0.0, global_sum = 0.0;
363
364 PetscFunctionBeginUser;
366 PetscCall(DMDAVecGetArray(user->da, B, &rhs));
367 PetscCall(DMDAVecGetArrayRead(user->fda, user->lUcont, (void *)&ucont));
368 PetscCall(DMDAVecGetArrayRead(user->da, user->lNvert, (void *)&nvert));
369 PetscCall(DMDAVecGetArrayRead(user->da, user->lAj, (void *)&aj));
370
371 for (PetscInt k = info.zs; k < info.zs + info.zm; k++) {
372 for (PetscInt j = info.ys; j < info.ys + info.ym; j++) {
373 for (PetscInt i = info.xs; i < info.xs + info.xm; i++) {
374 if (i == 0 || i == mx - 1 || j == 0 || j == my - 1 || k == 0 || k == mz - 1 ||
375 nvert[k][j][i] > POISSON_SOLID_THRESHOLD) {
376 rhs[k][j][i] = 0.0;
377 } else {
378 rhs[k][j][i] = -(ucont[k][j][i].x - ucont[k][j][i-1].x +
379 ucont[k][j][i].y - ucont[k][j-1][i].y +
380 ucont[k][j][i].z - ucont[k-1][j][i].z) / dt * aj[k][j][i] * COEF_TIME_ACCURACY;
381 }
382 }
383 }
384 }
385
386 /* The integral of the right-hand side is the net volume flux into the domain carried
387 by the uncorrected velocity. With Neumann pressure boundaries it must vanish for
388 the equation to have a solution. */
389 for (PetscInt k = info.zs; k < info.zs + info.zm; k++) {
390 for (PetscInt j = info.ys; j < info.ys + info.ym; j++) {
391 for (PetscInt i = info.xs; i < info.xs + info.xm; i++) {
392 local_sum += rhs[k][j][i] / aj[k][j][i] * dt / COEF_TIME_ACCURACY;
393 }
394 }
395 }
396 PetscCallMPI(MPI_Allreduce(&local_sum, &global_sum, 1, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)B)));
397 simCtx->poissonSourceImbalance = global_sum;
398 LOG_ALLOW(GLOBAL, LOG_INFO, "Poisson source imbalance: %le\n", (double)global_sum);
399
400 PetscCall(DMDAVecRestoreArrayRead(user->da, user->lAj, (void *)&aj));
401 PetscCall(DMDAVecRestoreArrayRead(user->da, user->lNvert, (void *)&nvert));
402 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lUcont, (void *)&ucont));
403 PetscCall(DMDAVecRestoreArray(user->da, B, &rhs));
405 PetscFunctionReturn(0);
406}
PetscReal poissonSourceImbalance
Definition variables.h:1026
PetscReal dt
Definition variables.h:874
PetscScalar x
Definition variables.h:122
PetscScalar z
Definition variables.h:122
Vec lUcont
Definition variables.h:1113
PetscScalar y
Definition variables.h:122
#define COEF_TIME_ACCURACY
Coefficient controlling the temporal accuracy scheme (e.g., 1.5 for 2nd Order Backward Difference).
Definition variables.h:75
A 3D point or vector with PetscScalar components.
Definition variables.h:121
Here is the caller graph for this function:

◆ UpdatePressure()

PetscErrorCode UpdatePressure ( UserCtx *  user)
extern

Adds the pressure correction to the pressure, P += Phi, and refreshes both fields' periodic images and ghosts.

Parameters
[in,out]userBlock context holding P and Phi.
Returns
PETSc error code.

Adds the pressure correction to the pressure, P += Phi, and refreshes both fields' periodic images and ghosts.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/poisson.h.

See also
UpdatePressure()

Definition at line 416 of file poisson.c.

417{
418 const FieldId periodic_fields[] = {FIELD_ID_P, FIELD_ID_PHI};
419
420 PetscFunctionBeginUser;
422 PetscCall(VecAXPY(user->P, 1.0, user->Phi));
423 PetscCall(SynchronizePeriodicCellFields(user, 2, periodic_fields));
424 PetscCall(UpdateLocalGhosts(user, FIELD_ID_P));
425 PetscCall(UpdateLocalGhosts(user, FIELD_ID_PHI));
427 PetscFunctionReturn(0);
428}
PetscErrorCode SynchronizePeriodicCellFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes periodic endpoint cells for a list of cell-centered fields.
@ FIELD_ID_PHI
@ FIELD_ID_P
PetscErrorCode UpdateLocalGhosts(UserCtx *user, FieldId field_id)
Updates the local vector (including ghost points) from its corresponding global vector.
Definition setup.c:2489
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ProjectVelocity()

PetscErrorCode ProjectVelocity ( UserCtx *  user)
extern

Corrects the contravariant flux with the gradient of Phi.

Subtracts dt / COEF_TIME_ACCURACY times the face pressure-gradient flux from every fluid face of Ucont, then refreshes the periodic images, reconstructs the Cartesian velocity, and finalizes the cell fields that depend on it.

Parameters
[in,out]userBlock context; reads the ghosted lPhi.
Returns
PETSc error code.

Corrects the contravariant flux with the gradient of Phi.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/poisson.h.

See also
ProjectVelocity()

Definition at line 438 of file poisson.c.

439{
440 SimCtx *simCtx = user->simCtx;
441 const DMDALocalInfo info = user->info;
442 const PetscInt m[3] = {info.mx, info.my, info.mz};
443 const PetscInt start[3] = {info.xs, info.ys, info.zs};
444 const PetscInt end[3] = {info.xs + info.xm, info.ys + info.ym, info.zs + info.zm};
445 const PetscReal scale = simCtx->dt / COEF_TIME_ACCURACY;
446 const FieldId staggered_fields[] = {FIELD_ID_UCONT};
447 PetscBool periodic[3];
448 PetscInt interior_start[3], interior_end[3];
449 PoissonFaceMetrics metrics;
450 const PetscReal ***nvert, ***phi;
451 Cmpnts ***ucont;
452
453 PetscFunctionBeginUser;
455 PoissonOperator_PeriodicAxes(user, periodic);
456 for (PetscInt a = 0; a < 3; a++) {
457 interior_start[a] = (start[a] == 0) ? 1 : start[a];
458 interior_end[a] = (end[a] == m[a]) ? m[a] - 1 : end[a];
459 }
460
461 PetscCall(PoissonOperator_GetFaceMetrics(user, &metrics));
462 PetscCall(DMDAVecGetArrayRead(user->da, user->lNvert, (void *)&nvert));
463 PetscCall(DMDAVecGetArrayRead(user->da, user->lPhi, (void *)&phi));
464 PetscCall(DMDAVecGetArray(user->fda, user->Ucont, &ucont));
465
466 /* One pass per face orientation. Faces between two interior cells are corrected on
467 every axis; a periodic axis also corrects its seam face at index 0. */
468 for (PetscInt n = 0; n < 3; n++) {
469 PetscInt lo[3], hi[3];
470 for (PetscInt a = 0; a < 3; a++) { lo[a] = interior_start[a]; hi[a] = interior_end[a]; }
471 if (periodic[n] && start[n] == 0) lo[n] = 0;
472 hi[n] = PetscMin(hi[n], periodic[n] ? m[n] - 1 : m[n] - 2);
473
474 for (PetscInt k = lo[2]; k < hi[2]; k++) {
475 for (PetscInt j = lo[1]; j < hi[1]; j++) {
476 for (PetscInt i = lo[0]; i < hi[0]; i++) {
477 const PetscInt c[3] = {i, j, k};
478 PetscInt across[3] = {0, 0, 0};
479 PetscReal difference[3];
480
481 across[n] = 1;
482 if (nvert[k][j][i] > POISSON_SOLID_THRESHOLD ||
483 PoissonOperator_At(nvert, c, across) > POISSON_SOLID_THRESHOLD) continue;
484
485 const PoissonFaceGradient face =
486 PoissonOperator_FaceGradientStencil(&metrics, nvert, c, n, m, periodic);
487 for (PetscInt b = 0; b < 3; b++) {
488 if (b == n) {
489 difference[b] = PoissonOperator_At(phi, c, across) - phi[k][j][i];
490 continue;
491 }
492 const PoissonTransverseDifference diff = face.diff[b];
493 PetscInt hi_lower[3] = {0, 0, 0}, hi_upper[3] = {0, 0, 0};
494 PetscInt lo_lower[3] = {0, 0, 0}, lo_upper[3] = {0, 0, 0};
495 hi_lower[b] = diff.hi; hi_upper[b] = diff.hi; hi_upper[n] = 1;
496 lo_lower[b] = diff.lo; lo_upper[b] = diff.lo; lo_upper[n] = 1;
497 difference[b] = (diff.weight == 0.0) ? 0.0 :
498 (PoissonOperator_At(phi, c, hi_lower) + PoissonOperator_At(phi, c, hi_upper) -
499 PoissonOperator_At(phi, c, lo_lower) - PoissonOperator_At(phi, c, lo_upper)) * diff.weight;
500 }
501
502 const PetscReal flux = difference[0] * face.dot[0] * face.aj +
503 difference[1] * face.dot[1] * face.aj +
504 difference[2] * face.dot[2] * face.aj;
505 const PetscReal correction = flux * scale;
506 if (n == 0) ucont[k][j][i].x -= correction;
507 else if (n == 1) ucont[k][j][i].y -= correction;
508 else ucont[k][j][i].z -= correction;
509 }
510 }
511 }
512 }
513
514 PetscCall(DMDAVecRestoreArray(user->fda, user->Ucont, &ucont));
515 PetscCall(DMDAVecRestoreArrayRead(user->da, user->lPhi, (void *)&phi));
516 PetscCall(DMDAVecRestoreArrayRead(user->da, user->lNvert, (void *)&nvert));
517 PetscCall(PoissonOperator_RestoreFaceMetrics(user, &metrics));
518
519 PetscCall(SynchronizePeriodicStaggeredFields(user, 1, staggered_fields));
520 PetscCall(Contra2Cart(user));
521 PetscCall(FinalizePostProjectionCellFields(user));
523 PetscFunctionReturn(0);
524}
PetscErrorCode FinalizePostProjectionCellFields(UserCtx *user)
Finalizes cell-centered fields after the projection step.
PetscReal aj
Inverse Jacobian on the face.
Definition poisson.c:54
PetscReal weight
0.25 central, 0.5 one-sided, 0 when no fluid side remains.
Definition poisson.c:48
PoissonTransverseDifference diff[3]
Transverse differences; diff[n] is unused.
Definition poisson.c:55
PetscInt hi
Transverse offset of the added row pair.
Definition poisson.c:47
PetscReal dot[3]
F_b .
Definition poisson.c:53
PetscInt lo
Transverse offset of the subtracted row pair.
Definition poisson.c:46
Transverse difference used at one face.
Definition poisson.c:45
PetscErrorCode Contra2Cart(UserCtx *user)
Reconstructs Cartesian velocity (Ucat) at cell centers from contravariant velocity (Ucont) defined on...
Definition setup.c:3300
Vec Ucont
Definition variables.h:1113
Here is the call graph for this function:
Here is the caller graph for this function: