36 PetscErrorCode (*AssembleInterior)(
UserCtx *, Vec, Mat);
64 PetscReal norm,
void *ctx);
66 PetscReal norm,
void *ctx);
69 SNESConvergedReason reason,
70 PetscInt nonlinear_its,
71 PetscInt function_evals,
80 Mat jacobian_operator, Mat preconditioning_matrix,
void *vctx);
82 UserCtx *user, Vec current_solution, Mat preconditioning_matrix);
84 UserCtx *user, Mat *preconditioning_matrix);
93 PetscReal norm,
void *vctx)
99 PetscFunctionBeginUser;
106 "step: %d | block: %d | newton: %d | nonlinear_norm: %.16e\n",
111 PetscFunctionReturn(PETSC_SUCCESS);
121 PetscReal norm,
void *vctx)
124 PetscInt newton_iteration = -1;
125 PetscReal relative_tolerance = 0.0;
127 PetscFunctionBeginUser;
129 PetscCall(SNESGetIterationNumber(ctx->
snes, &newton_iteration));
130 PetscCall(KSPGetTolerances(ksp, &relative_tolerance, NULL, NULL, NULL));
132 "step: %d | block: %d | newton: %d | krylov: %d | "
133 "requested_rtol: %.16e | reported_residual_norm: %.16e\n",
135 (
int)newton_iteration, (int)iteration,
136 (
double)relative_tolerance, (double)norm);
138 PetscFunctionReturn(PETSC_SUCCESS);
145 char path[PETSC_MAX_PATH_LEN + 128];
149 if (PetscSNPrintf(path,
sizeof(path),
150 "%s/Momentum_Solver_Newton_Krylov_History_Block_%d.log",
158 if (mode[0] ==
'w') {
160 "# step | block | Newton iteration | nonlinear residual norm\n");
164 if (PetscSNPrintf(path,
sizeof(path),
165 "%s/Momentum_Solver_Newton_Krylov_Linear_History_Block_%d.log",
172 if (mode[0] ==
'w') {
174 "# step | block | Newton iteration | Krylov iteration | "
175 "requested relative tolerance | PETSc-reported residual norm\n");
188 SNESConvergedReason reason,
189 PetscInt nonlinear_its,
190 PetscInt function_evals,
192 PetscReal final_norm,
196 char path[PETSC_MAX_PATH_LEN + 128];
198 const char *reason_name;
201 if (simCtx->
rank != 0)
return;
202 if (PetscSNPrintf(path,
sizeof(path),
203 "%s/Momentum_Solver_Newton_Krylov_Summary_Block_%d.log",
206 file = fopen(path, mode);
211 if (mode[0] ==
'w') {
213 "# step | block | solver | Jacobian | preconditioner | SNES reason | "
214 "reason code | Newton iterations | "
215 "residual evaluations | Krylov iterations | initial nonlinear norm | "
216 "final nonlinear norm | state\n");
218 (void)fprintf(file,
"# Continuation from step %d\n", (
int)simCtx->
StartStep);
220 reason_name = reason == SNES_CONVERGED_ITERATING
221 ?
"SNES_CONVERGED_ITERATING" : SNESConvergedReasons[reason];
223 "step: %d | block: %d | solver: Newton Krylov | "
224 "Jacobian: finite_difference / matrix_free | Preconditioner: %s | "
225 "reason: %s | reason_code: %d | "
226 "newton: %d | evals: %d | krylov: %d | initial: ",
229 "none" :
"frozen_momentum_jacobian / point_block",
230 reason_name, (int)reason,
231 (
int)nonlinear_its, (int)function_evals, (
int)linear_its);
233 else (
void)fprintf(file,
"unavailable");
234 (void)fprintf(file,
" | final: %.16e | state: %s\n", (
double)final_norm,
235 committed ?
"committed" :
"rolled_back");
240#define __FUNCT__ "MomentumNewtonKrylov_Validate"
249 PetscReal mask_max = 0.0;
250 PetscInt velocity_dof = 0;
252 PetscFunctionBeginUser;
253 PetscCheck(user != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
254 "Newton Krylov requires a non-NULL UserCtx.");
256 PetscCheck(simCtx != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
257 "Newton Krylov requires UserCtx::simCtx.");
258 PetscCall(DMDAGetInfo(user->
fda, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
259 &velocity_dof, NULL, NULL, NULL, NULL, NULL));
260 PetscCheck(velocity_dof == 3, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
261 "Newton Krylov requires a three-component velocity DMDA (got dof=%d).",
263 PetscCheck(simCtx->
block_number == 1, PETSC_COMM_WORLD, PETSC_ERR_SUP,
264 "Newton Krylov version one supports exactly one block (got %d).",
266 PetscCheck(!simCtx->
immersed, PETSC_COMM_WORLD, PETSC_ERR_SUP,
267 "Newton Krylov version one does not support immersed boundaries.");
268 PetscCheck(!simCtx->
movefsi && !simCtx->
rotatefsi, PETSC_COMM_WORLD, PETSC_ERR_SUP,
269 "Newton Krylov version one does not support moving or rotating bodies/FSI.");
271 "Newton Krylov version one does not support moving or rotating reference frames.");
272 PetscCheck(!simCtx->
TwoD, PETSC_COMM_WORLD, PETSC_ERR_SUP,
273 "Newton Krylov version one does not support TwoD component masking.");
274 for (PetscInt face = 0; face < 6; ++face) {
276 PetscBool supported = PETSC_FALSE;
300 supported = PETSC_FALSE;
303 PetscCheck(supported, PETSC_COMM_WORLD, PETSC_ERR_SUP,
304 "Newton Krylov version one does not support boundary face %d with mathematical type %d and handler %d.",
310 PETSC_COMM_WORLD, PETSC_ERR_SUP,
"Newton Krylov requires paired x-periodic faces.");
313 PETSC_COMM_WORLD, PETSC_ERR_SUP,
"Newton Krylov requires paired y-periodic faces.");
316 PETSC_COMM_WORLD, PETSC_ERR_SUP,
"Newton Krylov requires paired z-periodic faces.");
318 PetscCheck(user->
Nvert != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
319 "Newton Krylov requires the cell-mask vector Nvert.");
324 PetscCall(VecMax(user->
Nvert, NULL, &mask_max));
327 PetscFunctionReturn(PETSC_SUCCESS);
331#define __FUNCT__ "MomentumNewtonKrylov_ReadLinearizationConfig"
338 char type[48] =
"finite_difference";
339 char finite_difference_mode[32] =
"matrix_free";
340 char model[48] =
"none";
341 char structure[32] =
"none";
342 PetscBool set = PETSC_FALSE, match = PETSC_FALSE;
344 PetscFunctionBeginUser;
345 PetscCheck(jacobian != NULL && description != NULL, PETSC_COMM_SELF,
346 PETSC_ERR_ARG_NULL,
"Newton Krylov linearization configuration is NULL.");
347 PetscCall(PetscOptionsGetString(NULL, NULL,
"-mom_nk_jacobian_type",
348 type,
sizeof(type), &set));
349 PetscCall(PetscStrcasecmp(type,
"finite_difference", &match));
350 PetscCheck(match, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
351 "-mom_nk_jacobian_type must be 'finite_difference' (got '%s').", type);
353 PetscCall(PetscOptionsGetString(NULL, NULL,
"-mom_nk_jacobian_fd_mode",
354 finite_difference_mode,
355 sizeof(finite_difference_mode), &set));
356 PetscCall(PetscStrcasecmp(finite_difference_mode,
"matrix_free", &match));
357 PetscCheck(match, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
358 "-mom_nk_jacobian_fd_mode must be 'matrix_free' (got '%s').",
359 finite_difference_mode);
362 PetscCall(PetscOptionsGetString(NULL, NULL,
"-mom_nk_preconditioner_model",
363 model,
sizeof(model), &set));
364 PetscCall(PetscStrcasecmp(model,
"none", &match));
367 PetscCall(PetscStrcasecmp(model,
"frozen_momentum_jacobian", &match));
370 PetscCheck(match, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
371 "-mom_nk_preconditioner_model must be 'none' or "
372 "'frozen_momentum_jacobian' (got '%s').", model);
373 PetscCall(PetscOptionsGetString(NULL, NULL,
"-mom_nk_preconditioner_structure",
374 structure,
sizeof(structure), &set));
375 PetscCall(PetscStrcasecmp(structure,
"none", &match));
378 PetscCall(PetscStrcasecmp(structure,
"point_block", &match));
381 PetscCheck(match, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
382 "-mom_nk_preconditioner_structure must be 'none' or 'point_block' "
383 "(got '%s').", structure);
388 PETSC_COMM_WORLD, PETSC_ERR_SUP,
389 "Unsupported Newton Krylov preconditioner model/structure combination: "
390 "model='%s', structure='%s'.", model, structure);
391 PetscFunctionReturn(PETSC_SUCCESS);
403 UserCtx *user,
const PetscReal ***nvert, PetscInt i, PetscInt j, PetscInt k,
404 PetscInt component, PetscInt *ri, PetscInt *rj, PetscInt *rk)
416 return metric.
x * metric.
x + metric.
y * metric.
y + metric.
z * metric.
z;
445 const UserCtx *user,
const PetscReal ***
nu_t, PetscInt axis,
446 PetscInt i, PetscInt j, PetscInt k)
450 const PetscInt coord[3] = {i, j, k};
451 const PetscInt size[3] = {user->
info.mx, user->
info.my, user->
info.mz};
454 if (
nu_t == NULL)
return 0.0;
459 neighbour = (axis == 0) ?
nu_t[k][j][i + 1]
460 : (axis == 1) ?
nu_t[k][j + 1][i]
462 return 0.5 * (
nu_t[k][j][i] + neighbour);
468 const Cmpnts ***zet,
const PetscReal ***aj,
const PetscReal ***
nu_t,
469 PetscInt i, PetscInt j, PetscInt k, PetscScalar block[9])
473 const PetscReal molecular = simCtx->
ren > 0.0 ? 1.0 / simCtx->
ren : 0.0;
481 const PetscReal AJip = 0.5 * (aj[k][j][i] + aj[k][j][i + 1]);
482 const PetscReal AJjp = 0.5 * (aj[k][j][i] + aj[k][j + 1][i]);
483 const PetscReal AJkp = 0.5 * (aj[k][j][i] + aj[k + 1][j][i]);
484 const PetscReal g11ip = csi[k][j][i].
x * csi[k][j][i].
x +
485 csi[k][j][i].
y * csi[k][j][i].
y +
486 csi[k][j][i].
z * csi[k][j][i].
z;
487 const PetscReal g22ip = 0.25 * (
492 const PetscReal g33ip = 0.25 * (
497 const PetscReal g11jp = 0.25 * (
502 const PetscReal g22jp = eta[k][j][i].
x * eta[k][j][i].
x +
503 eta[k][j][i].
y * eta[k][j][i].
y +
504 eta[k][j][i].
z * eta[k][j][i].
z;
505 const PetscReal g33jp = 0.25 * (
510 const PetscReal g11kp = 0.25 * (
515 const PetscReal g22kp = 0.25 * (
520 const PetscReal g33kp = zet[k][j][i].
x * zet[k][j][i].
x +
521 zet[k][j][i].
y * zet[k][j][i].
y +
522 zet[k][j][i].
z * zet[k][j][i].
z;
523 const PetscReal U0jp = 0.25 * (ucont[k][j][i].
x + ucont[k][j][i - 1].
x +
524 ucont[k][j + 1][i].
x + ucont[k][j + 1][i - 1].
x);
525 const PetscReal U0kp = 0.25 * (ucont[k][j][i].
x + ucont[k][j][i - 1].
x +
526 ucont[k + 1][j][i].
x + ucont[k + 1][j][i - 1].
x);
527 const PetscReal U1ip = 0.25 * (ucont[k][j][i].
y + ucont[k][j - 1][i].
y +
528 ucont[k][j][i + 1].
y + ucont[k][j - 1][i + 1].
y);
529 const PetscReal U1kp = 0.25 * (ucont[k][j][i].
y + ucont[k][j - 1][i].
y +
530 ucont[k + 1][j][i].
y + ucont[k + 1][j - 1][i].
y);
531 const PetscReal U2ip = 0.25 * (ucont[k][j][i].
z + ucont[k - 1][j][i].
z +
532 ucont[k][j][i + 1].
z + ucont[k - 1][j][i + 1].
z);
533 const PetscReal U2jp = 0.25 * (ucont[k][j][i].
z + ucont[k - 1][j][i].
z +
534 ucont[k][j + 1][i].
z + ucont[k - 1][j + 1][i].
z);
535 PetscReal A[6][4] = {{0.0}};
536 PetscReal Su, Sv, Sw, nui, nuj, nuk;
538 A[0][0] = 0.125 * aj[k][j][i] * ucont[k][j][i].
y;
539 A[0][1] = -0.125 * aj[k][j - 1][i] * ucont[k][j - 1][i].
y;
540 A[0][2] = 0.125 * aj[k][j][i + 1] * ucont[k][j][i + 1].
y;
541 A[0][3] = -0.125 * aj[k][j - 1][i + 1] * ucont[k][j - 1][i + 1].
y;
542 A[1][0] = 0.125 * aj[k][j][i] * ucont[k][j][i].
z;
543 A[1][1] = -0.125 * aj[k - 1][j][i] * ucont[k - 1][j][i].
z;
544 A[1][2] = 0.125 * aj[k][j][i + 1] * ucont[k][j][i + 1].
z;
545 A[1][3] = -0.125 * aj[k - 1][j][i + 1] * ucont[k - 1][j][i + 1].
z;
546 A[2][0] = -0.125 * aj[k][j + 1][i - 1] * ucont[k][j + 1][i - 1].
x;
547 A[2][1] = -0.125 * aj[k][j][i - 1] * ucont[k][j][i - 1].
x;
548 A[2][2] = 0.125 * aj[k][j + 1][i] * ucont[k][j + 1][i].
x;
549 A[2][3] = 0.125 * aj[k][j][i] * ucont[k][j][i].
x;
550 A[3][0] = 0.125 * aj[k][j][i] * ucont[k][j][i].
z;
551 A[3][1] = -0.125 * aj[k - 1][j][i] * ucont[k - 1][j][i].
z;
552 A[3][2] = 0.125 * aj[k][j + 1][i] * ucont[k][j + 1][i].
z;
553 A[3][3] = -0.125 * aj[k - 1][j + 1][i] * ucont[k - 1][j + 1][i].
z;
554 A[4][0] = -0.125 * aj[k + 1][j][i - 1] * ucont[k + 1][j][i - 1].
x;
555 A[4][1] = -0.125 * aj[k][j][i - 1] * ucont[k][j][i - 1].
x;
556 A[4][2] = 0.125 * aj[k + 1][j][i] * ucont[k + 1][j][i].
x;
557 A[4][3] = 0.125 * aj[k][j][i] * ucont[k][j][i].
x;
558 A[5][0] = -0.125 * aj[k + 1][j - 1][i] * ucont[k + 1][j - 1][i].
y;
559 A[5][1] = -0.125 * aj[k][j - 1][i] * ucont[k][j - 1][i].
y;
560 A[5][2] = 0.125 * aj[k + 1][j][i] * ucont[k + 1][j][i].
y;
561 A[5][3] = 0.125 * aj[k][j][i] * ucont[k][j][i].
y;
562 Su = A[0][0] + A[0][1] + A[0][2] + A[0][3] +
563 A[1][0] + A[1][1] + A[1][2] + A[1][3];
564 Sv = A[2][0] + A[2][1] + A[2][2] + A[2][3] +
565 A[3][0] + A[3][1] + A[3][2] + A[3][3];
566 Sw = A[4][0] + A[4][1] + A[4][2] + A[4][3] +
567 A[5][0] + A[5][1] + A[5][2] + A[5][3];
568 nui = AJip * AJip * (g11ip + g22ip + g33ip) * nu_eff_i;
569 nuj = AJjp * AJjp * (g11jp + g22jp + g33jp) * nu_eff_j;
570 nuk = AJkp * AJkp * (g11kp + g22kp + g33kp) * nu_eff_k;
575 block[0] = dtc + nui + Su; block[1] = 0.5 * AJjp * U0jp; block[2] = 0.5 * AJkp * U0kp;
576 block[3] = 0.5 * AJip * U1ip; block[4] = dtc + nuj + Sv; block[5] = 0.5 * AJkp * U1kp;
577 block[6] = 0.5 * AJip * U2ip; block[7] = 0.5 * AJjp * U2jp; block[8] = dtc + nuk + Sw;
581#define __FUNCT__ "FrozenMomentumJacobian_DescribePointBlock"
586 PetscFunctionBeginUser;
588 PetscCheck(description != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
589 "Preconditioner description is NULL.");
594 PetscFunctionReturn(PETSC_SUCCESS);
598#define __FUNCT__ "FrozenMomentumJacobian_AssemblePointBlocks"
601 UserCtx *user, Vec current_solution, Mat preconditioning_matrix)
603 DMDALocalInfo info = user->
info;
604 Cmpnts ***ucont = NULL, ***csi = NULL, ***eta = NULL, ***zet = NULL;
605 PetscReal ***aj = NULL, ***nvert = NULL, ***
nu_t = NULL;
609 const PetscBool has_eddy_viscosity =
610 (PetscBool)(simCtx->
les && user->
lNu_t != NULL);
611 PetscErrorCode ierr = PETSC_SUCCESS, cleanup_ierr;
613 PetscFunctionBeginUser;
626 ierr = DMGlobalToLocalBegin(user->
fda, current_solution, INSERT_VALUES, user->
lUcont);
627 if (ierr)
goto cleanup;
628 ierr = DMGlobalToLocalEnd(user->
fda, current_solution, INSERT_VALUES, user->
lUcont);
629 if (ierr)
goto cleanup;
630 ierr = DMDAVecGetArrayRead(user->
fda, user->
lUcont, &ucont);
if (ierr)
goto cleanup;
631 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCsi, &csi);
if (ierr)
goto cleanup;
632 ierr = DMDAVecGetArrayRead(user->
fda, user->
lEta, &eta);
if (ierr)
goto cleanup;
633 ierr = DMDAVecGetArrayRead(user->
fda, user->
lZet, &zet);
if (ierr)
goto cleanup;
634 ierr = DMDAVecGetArrayRead(user->
da, user->
lAj, &aj);
if (ierr)
goto cleanup;
635 ierr = DMDAVecGetArrayRead(user->
da, user->
lNvert, &nvert);
if (ierr)
goto cleanup;
636 if (has_eddy_viscosity) {
637 ierr = DMDAVecGetArrayRead(user->
da, user->
lNu_t, &
nu_t);
if (ierr)
goto cleanup;
639 for (PetscInt k = info.zs; k < info.zs + info.zm; ++k) {
640 for (PetscInt j = info.ys; j < info.ys + info.ym; ++j) {
641 for (PetscInt i = info.xs; i < info.xs + info.xm; ++i) {
642 for (PetscInt component = 0; component < 3; ++component) {
643 MatStencil row = {.i = i, .j = j, .k = k, .c = component};
646 user, (
const PetscReal ***)nvert, i, j, k, component, &ri, &rj, &rk);
648 PetscScalar block[9];
649 MatStencil cols[3] = {
650 {.i = i, .j = j, .k = k, .c = 0},
651 {.i = i, .j = j, .k = k, .c = 1},
652 {.i = i, .j = j, .k = k, .c = 2}
656 (
const PetscReal ***)aj, (
const PetscReal ***)
nu_t, i, j, k, block);
657 ierr = MatSetValuesStencil(preconditioning_matrix, 1, &row, 3, cols,
658 &block[3 * component], INSERT_VALUES);
659 if (ierr)
goto cleanup;
666 if (
nu_t) { cleanup_ierr = DMDAVecRestoreArrayRead(user->
da, user->
lNu_t, &
nu_t);
if (!ierr) ierr = cleanup_ierr; }
667 if (nvert) { cleanup_ierr = DMDAVecRestoreArrayRead(user->
da, user->
lNvert, &nvert);
if (!ierr) ierr = cleanup_ierr; }
668 if (aj) { cleanup_ierr = DMDAVecRestoreArrayRead(user->
da, user->
lAj, &aj);
if (!ierr) ierr = cleanup_ierr; }
669 if (zet) { cleanup_ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lZet, &zet);
if (!ierr) ierr = cleanup_ierr; }
670 if (eta) { cleanup_ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lEta, &eta);
if (!ierr) ierr = cleanup_ierr; }
671 if (csi) { cleanup_ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCsi, &csi);
if (!ierr) ierr = cleanup_ierr; }
672 if (ucont) { cleanup_ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lUcont, &ucont);
if (!ierr) ierr = cleanup_ierr; }
673 PetscFunctionReturn(ierr);
677#define __FUNCT__ "MomentumPreconditionerEngine_ApplyConstraintRows"
680 UserCtx *user, Mat preconditioning_matrix)
682 DMDALocalInfo info = user->
info;
683 const PetscReal ***nvert = NULL;
685 PetscFunctionBeginUser;
686 PetscCall(DMDAVecGetArrayRead(user->
da, user->
lNvert, &nvert));
687 for (PetscInt k = info.zs; k < info.zs + info.zm; ++k) {
688 for (PetscInt j = info.ys; j < info.ys + info.ym; ++j) {
689 for (PetscInt i = info.xs; i < info.xs + info.xm; ++i) {
690 for (PetscInt component = 0; component < 3; ++component) {
693 user, nvert, i, j, k, component, &ri, &rj, &rk);
695 MatStencil row = {.i = i, .j = j, .k = k, .c = component};
696 MatStencil columns[2] = {row, row};
697 PetscScalar values[2] = {1.0, -1.0};
698 PetscInt column_count = 1;
700 columns[column_count++] = (MatStencil){
701 .i = ri, .j = rj, .k = rk, .c = component
704 PetscCall(MatSetValuesStencil(preconditioning_matrix, 1, &row,
705 column_count, columns, values,
712 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
lNvert, &nvert));
713 PetscFunctionReturn(PETSC_SUCCESS);
722#define __FUNCT__ "MomentumNewtonJacobian_Create"
727 PetscFunctionBeginUser;
730 PETSC_COMM_WORLD, PETSC_ERR_SUP,
731 "Unsupported Newton Krylov Jacobian type/finite-difference-mode combination.");
735 "momentum_jacobian_finite_difference_matrix_free"));
736 PetscFunctionReturn(PETSC_SUCCESS);
743 PetscFunctionBeginUser;
744 PetscCall(MatMFFDComputeJacobian(snes, current_solution, jacobian->
jacobian_operator,
746 PetscFunctionReturn(PETSC_SUCCESS);
754 PetscFunctionBeginUser;
758 PetscFunctionReturn(PETSC_SUCCESS);
764 PetscFunctionBeginUser;
766 PetscFunctionReturn(PETSC_SUCCESS);
770#define __FUNCT__ "MomentumPreconditionerEngine_Create"
776 PetscFunctionBeginUser;
794 "momentum_preconditioner_frozen_point_block"));
798 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP,
799 "Unsupported Newton Krylov preconditioner model/structure combination.");
801 PetscFunctionReturn(PETSC_SUCCESS);
805#define __FUNCT__ "MomentumPreconditionerEngine_Assemble"
810 PetscFunctionBeginUser;
819 PetscFunctionReturn(PETSC_SUCCESS);
826 PetscFunctionBeginUser;
828 PetscFunctionReturn(PETSC_SUCCESS);
835 const char *actual_type = NULL;
836 PetscBool matches = PETSC_FALSE;
838 PetscFunctionBeginUser;
839 PetscCall(PCGetType(pc, &actual_type));
840 PetscCall(PetscStrcmp(actual_type, engine->
petsc_pc_type, &matches));
841 PetscCheck(matches, PETSC_COMM_WORLD, PETSC_ERR_SUP,
842 "Newton Krylov preconditioner model/structure requires internal PETSc PC "
843 "type '%s', but raw option processing selected '%s'.",
844 engine->
petsc_pc_type, actual_type ? actual_type :
"(unset)");
845 PetscFunctionReturn(PETSC_SUCCESS);
852 PetscFunctionBeginUser;
857 PetscFunctionReturn(PETSC_SUCCESS);
861#define __FUNCT__ "MomentumNewtonKrylov_FormJacobian"
864 Mat jacobian_operator, Mat preconditioning_matrix,
void *vctx)
867 PetscFunctionBeginUser;
868 (void)jacobian_operator;
869 (void)preconditioning_matrix;
873 PetscFunctionReturn(PETSC_SUCCESS);
877#define __FUNCT__ "MomentumPreconditionerEngine_CreateExactPointBlockMatrix"
887 UserCtx *user, Mat *preconditioning_matrix)
890 ISLocalToGlobalMapping local_to_global = NULL;
893 PetscInt local_size, global_size, ownership_start, ownership_end;
894 PetscInt *diagonal_nnz = NULL, *offdiagonal_nnz = NULL;
895 PetscInt ghost_starts[4] = {0, 0, 0, 0}, ghost_sizes[3] = {0, 0, 0};
896 const PetscReal ***nvert = NULL;
897 PetscErrorCode ierr = PETSC_SUCCESS, cleanup_ierr;
899 PetscFunctionBeginUser;
900 PetscCheck(preconditioning_matrix != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
901 "Point-block matrix output is NULL.");
902 *preconditioning_matrix = NULL;
903 comm = PetscObjectComm((PetscObject)user->
fda);
904 PetscCall(DMDAGetLocalInfo(user->
fda, &info));
905 PetscCall(VecGetLocalSize(user->
Ucont, &local_size));
906 PetscCall(VecGetSize(user->
Ucont, &global_size));
907 PetscCall(VecGetOwnershipRange(user->
Ucont, &ownership_start, &ownership_end));
908 PetscCheck(local_size == ownership_end - ownership_start, comm, PETSC_ERR_PLIB,
909 "Velocity ownership range does not match its local size.");
910 ierr = PetscCalloc2(local_size, &diagonal_nnz,
911 local_size, &offdiagonal_nnz);
if (ierr)
goto cleanup;
912 ierr = DMGetLocalToGlobalMapping(user->
fda, &local_to_global);
if (ierr)
goto cleanup;
913 ierr = DMDAGetGhostCorners(user->
fda,
914 &ghost_starts[0], &ghost_starts[1], &ghost_starts[2],
915 &ghost_sizes[0], &ghost_sizes[1], &ghost_sizes[2]);
916 if (ierr)
goto cleanup;
917 ierr = DMDAVecGetArrayRead(user->
da, user->
lNvert, &nvert);
if (ierr)
goto cleanup;
919 for (PetscInt k = info.zs; k < info.zs + info.zm; ++k) {
920 for (PetscInt j = info.ys; j < info.ys + info.ym; ++j) {
921 for (PetscInt i = info.xs; i < info.xs + info.xm; ++i) {
922 for (PetscInt component = 0; component < 3; ++component) {
923 PetscInt ri, rj, rk, column_count;
924 MatStencil row_stencil = {.i = i, .j = j, .k = k, .c = component};
925 MatStencil column_stencils[3];
926 PetscInt row_local, row, column_locals[3], columns[3];
928 user, nvert, i, j, k, component, &ri, &rj, &rk);
932 for (PetscInt column_component = 0; column_component < 3;
933 ++column_component) {
934 column_stencils[column_component] = (MatStencil){
935 .i = i, .j = j, .k = k, .c = column_component
940 column_stencils[0] = row_stencil;
942 column_stencils[column_count++] = (MatStencil){
943 .i = ri, .j = rj, .k = rk, .c = component
947 row_local = component + 3 * (
948 (i - ghost_starts[0]) + ghost_sizes[0] * (
949 (j - ghost_starts[1]) + ghost_sizes[1] *
950 (k - ghost_starts[2])));
951 for (PetscInt column_index = 0; column_index < column_count;
953 const MatStencil column = column_stencils[column_index];
954 if (!(column.i >= ghost_starts[0] &&
955 column.i < ghost_starts[0] + ghost_sizes[0] &&
956 column.j >= ghost_starts[1] &&
957 column.j < ghost_starts[1] + ghost_sizes[1] &&
958 column.k >= ghost_starts[2] &&
959 column.k < ghost_starts[2] + ghost_sizes[2])) {
960 ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__,
961 PETSC_ERR_ARG_OUTOFRANGE,
963 "Point-block column lies outside the DMDA ghost stencil.");
966 column_locals[column_index] = column.c + 3 * (
967 (column.i - ghost_starts[0]) + ghost_sizes[0] * (
968 (column.j - ghost_starts[1]) + ghost_sizes[1] *
969 (column.k - ghost_starts[2])));
971 ierr = ISLocalToGlobalMappingApply(local_to_global, 1,
973 if (ierr)
goto cleanup;
974 ierr = ISLocalToGlobalMappingApply(local_to_global, column_count,
975 column_locals, columns);
976 if (ierr)
goto cleanup;
977 if (!(row >= ownership_start && row < ownership_end)) {
978 ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__,
979 PETSC_ERR_PLIB, PETSC_ERROR_INITIAL,
980 "DMDA-mapped point-block row is not locally owned.");
983 for (PetscInt column_index = 0; column_index < column_count;
985 PetscBool duplicate = PETSC_FALSE;
986 for (PetscInt previous = 0; previous < column_index; ++previous)
987 if (columns[previous] == columns[column_index]) duplicate = PETSC_TRUE;
988 if (columns[column_index] < 0) {
989 ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__,
990 PETSC_ERR_PLIB, PETSC_ERROR_INITIAL,
991 "DMDA-mapped point-block column is invalid.");
994 if (duplicate)
continue;
995 if (columns[column_index] >= ownership_start &&
996 columns[column_index] < ownership_end)
997 ++diagonal_nnz[row - ownership_start];
999 ++offdiagonal_nnz[row - ownership_start];
1006 ierr = MatCreateAIJ(comm, local_size, local_size, global_size, global_size,
1007 0, diagonal_nnz, 0, offdiagonal_nnz, &matrix);
1008 if (ierr)
goto cleanup;
1009 ierr = MatSetBlockSize(matrix, 3);
if (ierr)
goto cleanup;
1010 ierr = MatSetLocalToGlobalMapping(matrix, local_to_global, local_to_global);
1011 if (ierr)
goto cleanup;
1012 ierr = MatSetStencil(matrix, 3, ghost_sizes, ghost_starts, 3);
1013 if (ierr)
goto cleanup;
1014 ierr = MatSetDM(matrix, user->
fda);
if (ierr)
goto cleanup;
1015 ierr = MatSetOption(matrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);
1016 if (ierr)
goto cleanup;
1017 ierr = PetscFree2(diagonal_nnz, offdiagonal_nnz);
if (ierr)
goto cleanup;
1019 *preconditioning_matrix = matrix;
1024 cleanup_ierr = DMDAVecRestoreArrayRead(user->
da, user->
lNvert, &nvert);
1025 if (!ierr) ierr = cleanup_ierr;
1027 cleanup_ierr = MatDestroy(&matrix);
if (!ierr) ierr = cleanup_ierr;
1028 cleanup_ierr = PetscFree2(diagonal_nnz, offdiagonal_nnz);
1029 if (!ierr) ierr = cleanup_ierr;
1030 PetscFunctionReturn(ierr);
1034#define __FUNCT__ "MomentumNewtonKrylov_ApplyConstraints"
1054 DMDALocalInfo info = user->
info;
1056 Cmpnts ***x = NULL, ***conditioned = NULL, ***f = NULL, ***lx = NULL;
1057 const PetscInt xs = info.xs, xe = info.xs + info.xm;
1058 const PetscInt ys = info.ys, ye = info.ys + info.ym;
1059 const PetscInt zs = info.zs, ze = info.zs + info.zm;
1061 PetscFunctionBeginUser;
1062 PetscCall(DMGetLocalVector(user->
fda, &local_x));
1063 PetscCall(DMGlobalToLocalBegin(user->
fda, X, INSERT_VALUES, local_x));
1064 PetscCall(DMGlobalToLocalEnd(user->
fda, X, INSERT_VALUES, local_x));
1065 PetscCall(DMDAVecGetArrayRead(user->
fda, X, &x));
1066 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucont, &conditioned));
1067 PetscCall(DMDAVecGetArray(user->
fda, F, &f));
1068 PetscCall(DMDAVecGetArrayRead(user->
fda, local_x, &lx));
1070 for (PetscInt k = zs; k < ze; ++k) {
1071 for (PetscInt j = ys; j < ye; ++j) {
1072 for (PetscInt i = xs; i < xe; ++i) {
1073 PetscScalar *fv = &f[k][j][i].x;
1074 const PetscScalar *xv = &x[k][j][i].
x;
1075 const PetscScalar *cv = &conditioned[k][j][i].x;
1077 for (PetscInt component = 0; component < 3; ++component) {
1078 PetscInt ri, rj, rk;
1080 user, i, j, k, component, &ri, &rj, &rk);
1081 const PetscScalar *rv = &lx[rk][rj][ri].x;
1091 PetscCall(DMDAVecRestoreArrayRead(user->
fda, local_x, &lx));
1092 PetscCall(DMDAVecRestoreArray(user->
fda, F, &f));
1093 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucont, &conditioned));
1094 PetscCall(DMDAVecRestoreArrayRead(user->
fda, X, &x));
1095 PetscCall(DMRestoreLocalVector(user->
fda, &local_x));
1096 PetscFunctionReturn(PETSC_SUCCESS);
1100#define __FUNCT__ "MomentumNewtonKrylov_FormResidual"
1137 PetscFunctionBeginUser;
1139 PetscCall(VecCopy(X, user->
Ucont));
1182 PetscCall(VecCopy(user->
Rhs, F));
1183 PetscCall(VecScale(F, -1.0));
1185 PetscFunctionReturn(PETSC_SUCCESS);
1189#define __FUNCT__ "MomentumSolver_NewtonKrylov"
1197 PetscErrorCode ierr = PETSC_SUCCESS, cleanup_ierr;
1200 Vec solution = NULL, entry_backup = NULL;
1204 PetscBool restore_entry = PETSC_FALSE;
1205 PetscBool rhs_created = PETSC_FALSE;
1206 PetscBool solve_started = PETSC_FALSE;
1207 PetscBool committed = PETSC_FALSE;
1208 SNESConvergedReason reason = SNES_CONVERGED_ITERATING;
1209 PetscInt nonlinear_its = 0, function_evals = 0, linear_its = 0;
1210 PetscReal final_norm = PETSC_MAX_REAL;
1214 PetscFunctionBeginUser;
1216 PetscCheck(ibm == NULL && fsi == NULL, PETSC_COMM_WORLD, PETSC_ERR_SUP,
1217 "Newton Krylov version one does not accept IBM or FSI objects.");
1218 PetscCheck(user->
Rhs == NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
1219 "Newton Krylov requires UserCtx::Rhs to be unallocated on entry.");
1222 ierr = VecDuplicate(user->
Ucont, &solution);
if (ierr)
goto cleanup;
1223 ierr = VecDuplicate(user->
Ucont, &entry_backup);
if (ierr)
goto cleanup;
1224 ierr = VecDuplicate(user->
Ucont, &user->
Rhs);
if (ierr)
goto cleanup;
1225 rhs_created = PETSC_TRUE;
1226 ierr = SNESCreate(PetscObjectComm((PetscObject)user->
Ucont), &snes);
if (ierr)
goto cleanup;
1230 ierr = VecCopy(user->
Ucont, entry_backup);
if (ierr)
goto cleanup;
1231 restore_entry = PETSC_TRUE;
1232 ierr = VecCopy(user->
Ucont, solution);
if (ierr)
goto cleanup;
1237 &ctx.
jacobian, &preconditioner_description);
if (ierr)
goto cleanup;
1238 ierr = SNESSetOptionsPrefix(snes,
"mom_nk_");
if (ierr)
goto cleanup;
1239 ierr = SNESSetType(snes, SNESNEWTONLS);
if (ierr)
goto cleanup;
1240 ierr = SNESSetDM(snes, user->
fda);
if (ierr)
goto cleanup;
1244 &preconditioner_description,
1248 ierr = SNESGetKSP(snes, &ksp);
if (ierr)
goto cleanup;
1249 ierr = KSPSetType(ksp, KSPGMRES);
if (ierr)
goto cleanup;
1250 ierr = KSPGetPC(ksp, &pc);
if (ierr)
goto cleanup;
1252 ierr = SNESSetFromOptions(snes);
if (ierr)
goto cleanup;
1258 "Newton Krylov Jacobian: finite_difference / matrix_free; "
1259 "Preconditioner: %s; PETSc Jacobian matrix type: MATMFFD; "
1260 "PETSc PC type: %s.\n",
1262 "none" :
"frozen_momentum_jacobian / point_block",
1266 solve_started = PETSC_TRUE;
1267 ierr = SNESSolve(snes, NULL, solution);
1268 if (ierr)
goto cleanup;
1269 ierr = SNESGetConvergedReason(snes, &reason);
if (ierr)
goto cleanup;
1270 ierr = SNESGetIterationNumber(snes, &nonlinear_its);
if (ierr)
goto cleanup;
1271 ierr = SNESGetNumberFunctionEvals(snes, &function_evals);
if (ierr)
goto cleanup;
1272 ierr = SNESGetLinearSolveIterations(snes, &linear_its);
if (ierr)
goto cleanup;
1273 ierr = SNESGetFunctionNorm(snes, &final_norm);
if (ierr)
goto cleanup;
1276 ierr = VecCopy(solution, user->
Ucont);
if (ierr)
goto cleanup;
1279 ierr = VecCopy(entry_backup, user->
Ucont);
if (ierr)
goto cleanup;
1284 restore_entry = PETSC_FALSE;
1285 committed = (PetscBool)(reason > 0);
1288 "Newton Krylov momentum solve: reason=%s (%d), Newton iterations=%d, residual evaluations=%d, Krylov iterations=%d, final norm=%.6e, state=%s.\n",
1289 SNESConvergedReasons[reason], (PetscInt)reason, nonlinear_its, function_evals,
1290 linear_its, (
double)final_norm, reason > 0 ?
"committed" :
"rolled back");
1291 if (reason <= 0) ierr = PETSC_ERR_CONV_FAILED;
1297 if (solve_started && snes) {
1298 (void)SNESGetConvergedReason(snes, &reason);
1299 (void)SNESGetIterationNumber(snes, &nonlinear_its);
1300 (void)SNESGetNumberFunctionEvals(snes, &function_evals);
1301 (void)SNESGetLinearSolveIterations(snes, &linear_its);
1302 (void)SNESGetFunctionNorm(snes, &final_norm);
1304 if (restore_entry && entry_backup) {
1305 cleanup_ierr = VecCopy(entry_backup, user->
Ucont);
1306 if (!ierr) ierr = cleanup_ierr;
1308 if (!ierr) ierr = cleanup_ierr;
1310 if (!ierr) ierr = cleanup_ierr;
1312 committed = PETSC_FALSE;
1322 if (solve_started) {
1324 linear_its, final_norm, committed);
1327 cleanup_ierr = VecDestroy(&user->
Rhs);
1328 if (!ierr) ierr = cleanup_ierr;
1330 cleanup_ierr = VecDestroy(&entry_backup);
if (!ierr) ierr = cleanup_ierr;
1331 cleanup_ierr = VecDestroy(&solution);
if (!ierr) ierr = cleanup_ierr;
1334 cleanup_ierr = SNESDestroy(&snes);
if (!ierr) ierr = cleanup_ierr;
1335 PetscFunctionReturn(ierr);
MomentumRowType
Classification of one staggered momentum row (location + component).
@ MOM_ROW_FIXED_HOMOGENEOUS
Dummy/tangential row carrying no unknown at all.
@ MOM_ROW_PHYSICAL
Independent unknown governed by the momentum equation.
@ MOM_ROW_PERIODIC_DUPLICATE
Duplicate of a wrapped representative row (see ri, rj, rk).
@ MOM_ROW_FIXED_CONDITIONED
Strong Dirichlet row; the value comes from ApplyBoundaryConditions().
MomentumRowType ClassifyMomentumRow(UserCtx *user, PetscInt i, PetscInt j, PetscInt k, PetscInt component, PetscInt *ri, PetscInt *rj, PetscInt *rk)
Single source of truth for "which staggered momentum rows are unknowns".
PetscBool MomentumRowIsSolidMasked(const PetscReal ***nvert, PetscInt i, PetscInt j, PetscInt k, PetscInt component)
Reports whether a momentum row is masked out by the solid-cell field.
PetscErrorCode SynchronizePeriodicStaggeredFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes persistent component-staggered vector fields.
PetscErrorCode ApplyBoundaryConditions(UserCtx *user)
Main boundary-condition orchestrator executed during solver timestepping.
PetscErrorCode SynchronizePeriodicCellFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes periodic endpoint cells for a list of cell-centered fields.
FieldId
Compile-time identity for a catalogued Eulerian field.
#define GLOBAL
Scope for global logging across all processes.
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
#define LOG(scope, level, fmt,...)
Logging macro for PETSc-based applications with scope control.
@ LOG_INFO
Informational messages about program execution.
@ LOG_WARNING
Non-critical issues that warrant attention.
@ LOG_DEBUG
Detailed debugging information.
static PetscReal FrozenMomentumJacobian_FaceEddyViscosity(const UserCtx *user, const PetscReal ***nu_t, PetscInt axis, PetscInt i, PetscInt j, PetscInt k)
Returns the face-averaged eddy viscosity the residual uses on one face.
static PetscErrorCode MomentumNewtonJacobian_Register(SNES snes, MomentumNewtonJacobian *jacobian, MomentumPreconditionerEngine *engine, MomentumNewtonKrylovContext *ctx)
Registers the application orchestration callback and both SNES matrices.
static const MomentumPreconditionerModelOps frozen_momentum_point_block_ops
PetscBool aliases_jacobian_operator
const MomentumPreconditionerModelOps * model_ops
static PetscErrorCode MomentumPreconditionerEngine_ConfigurePetscPC(MomentumPreconditionerEngine *engine, PC pc)
Applies the validated model/structure-to-PETSc-PC mapping.
static PetscErrorCode FrozenMomentumJacobian_DescribePointBlock(UserCtx *user, MomentumPreconditionerDescription *description)
Describes the audited frozen-coefficient point-block model.
static PetscErrorCode MomentumNewtonKrylov_ApplyConstraints(MomentumNewtonKrylovContext *ctx, Vec X, Vec F)
Replaces every non-independent residual row with an explicit equation.
static PetscErrorCode MomentumPreconditionerEngine_CreateExactPointBlockMatrix(UserCtx *user, Mat *preconditioning_matrix)
Creates the frozen point-block P matrix with its exact scalar pattern.
static PetscErrorCode MomentumPreconditionerEngine_ValidatePetscPC(MomentumPreconditionerEngine *engine, PC pc)
Rejects raw options that select an unvalidated PETSc PC backend.
static PetscReal FrozenMomentumJacobian_MetricNormSquared(Cmpnts metric)
Returns the squared Euclidean norm of one metric vector.
MomentumPreconditionerStructure
@ MOM_NK_PC_STRUCTURE_POINT_BLOCK
@ MOM_NK_PC_STRUCTURE_NONE
static PetscErrorCode MomentumNewtonKrylov_FormJacobian(SNES snes, Vec current_solution, Mat jacobian_operator, Mat preconditioning_matrix, void *vctx)
Updates the Jacobian and then assembles any separate preconditioning matrix.
MomentumPreconditionerDescription description
static PetscErrorCode MomentumPreconditionerEngine_Create(UserCtx *user, Mat jacobian_operator, const MomentumPreconditionerDescription *requested, MomentumPreconditionerEngine *engine)
Validates a model/structure and creates or aliases its matrix.
const char * petsc_pc_type
static void MomentumNewtonKrylov_WriteSummary(const MomentumNewtonKrylovContext *ctx, SNESConvergedReason reason, PetscInt nonlinear_its, PetscInt function_evals, PetscInt linear_its, PetscReal final_norm, PetscBool committed)
Appends one rank-zero structured Newton result for a physical step.
MomentumNewtonFiniteDifferenceMode finite_difference_mode
MomentumNewtonJacobianType type
static PetscErrorCode MomentumNewtonKrylov_ReadLinearizationConfig(MomentumNewtonJacobian *jacobian, MomentumPreconditionerDescription *description)
Reads application-owned Jacobian and preconditioner mathematics.
static PetscErrorCode MomentumPreconditionerEngine_Assemble(MomentumPreconditionerEngine *engine, UserCtx *user, Vec current_solution)
Runs model insertion, common row handling, and final assembly.
static PetscErrorCode MomentumNewtonJacobian_Destroy(MomentumNewtonJacobian *jacobian)
Destroys a partially or fully created Jacobian operator.
MomentumNewtonJacobian jacobian
static void FrozenMomentumJacobian_PointBlock(const UserCtx *user, const Cmpnts ***ucont, const Cmpnts ***csi, const Cmpnts ***eta, const Cmpnts ***zet, const PetscReal ***aj, const PetscReal ***nu_t, PetscInt i, PetscInt j, PetscInt k, PetscScalar block[9])
Returns the frozen-momentum point block for the current residual convention.
static void MomentumNewtonKrylov_OpenHistory(MomentumNewtonKrylovContext *ctx)
Opens the optional rank-zero Newton iteration-history file.
MomentumPreconditionerModel model
static PetscErrorCode MomentumNewtonKrylov_LinearMonitor(KSP ksp, PetscInt iteration, PetscReal norm, void *ctx)
Writes the effective KSP tolerance and PETSc-reported norm for each inner iteration.
static PetscErrorCode MomentumNewtonJacobian_Create(SNES snes, MomentumNewtonJacobian *jacobian)
Creates the selected Jacobian operator; currently PETSc MFFD only.
MomentumPreconditionerStructure structure
static PetscErrorCode FrozenMomentumJacobian_AssemblePointBlocks(UserCtx *user, Vec current_solution, Mat preconditioning_matrix)
Inserts only the audited interior frozen-momentum point blocks.
MomentumNewtonJacobianType
@ MOM_NK_JACOBIAN_FINITE_DIFFERENCE
Mat preconditioning_matrix
static PetscErrorCode MomentumNewtonJacobian_Update(SNES snes, Vec current_solution, MomentumNewtonJacobian *jacobian)
Updates the matrix-free finite-difference operator base.
PetscBool have_initial_norm
PetscBool owns_preconditioning_matrix
static PetscErrorCode MomentumNewtonKrylov_Validate(UserCtx *user)
Rejects configurations outside the audited version-one feature set.
static PetscErrorCode MomentumPreconditionerEngine_Destroy(MomentumPreconditionerEngine *engine)
Destroys only a separately owned preconditioning matrix.
FILE * linear_history_file
MomentumPreconditionerEngine preconditioning_engine
static PetscErrorCode MomentumNewtonKrylov_FormResidual(SNES snes, Vec X, Vec F, void *ctx)
Adapts a PETSc trial vector to the existing momentum residual path.
static MomentumRowType MomentumNewtonKrylov_ClassifyRow(UserCtx *user, const PetscReal ***nvert, PetscInt i, PetscInt j, PetscInt k, PetscInt component, PetscInt *ri, PetscInt *rj, PetscInt *rk)
Row classification with solid-cell masking folded in.
MomentumNewtonFiniteDifferenceMode
@ MOM_NK_FD_MODE_MATRIX_FREE
static PetscErrorCode MomentumNewtonKrylov_Monitor(SNES snes, PetscInt iteration, PetscReal norm, void *ctx)
Captures SNES iteration norms and optionally writes PICurv history rows.
static PetscErrorCode MomentumPreconditionerEngine_ApplyConstraintRows(UserCtx *user, Mat preconditioning_matrix)
Inserts all common fixed, homogeneous, and periodic-duplicate rows.
MomentumPreconditionerModel
@ MOM_NK_PC_MODEL_FROZEN_MOMENTUM_JACOBIAN
PetscReal MomentumBDFCoefficient(SimCtx *simCtx)
Returns the BDF physical-time coefficient a0 for the current step.
PetscErrorCode ComputeTotalResidual(UserCtx *user)
Computes the shared spatial-plus-BDF momentum residual in user->Rhs.
PetscErrorCode Contra2Cart(UserCtx *user)
Reconstructs Cartesian velocity (Ucat) at cell centers from contravariant velocity (Ucont) defined on...
PetscErrorCode UpdateLocalGhosts(UserCtx *user, FieldId field_id)
Updates the local vector (including ghost points) from its corresponding global vector.
PetscErrorCode(* Describe)(UserCtx *, MomentumPreconditionerDescription *)
PetscErrorCode(* AssembleInterior)(UserCtx *, Vec, Mat)
#define MomentumSolver_NewtonKrylov
PetscBool mom_nk_monitor_history
BoundaryFaceConfig boundary_faces[6]
SimCtx * simCtx
Back-pointer to the master simulation context.
PetscBool mom_last_converged
@ BC_HANDLER_PERIODIC_GEOMETRIC
@ BC_HANDLER_INLET_PARABOLIC
@ BC_HANDLER_INLET_CONSTANT_VELOCITY
@ BC_HANDLER_PERIODIC_DRIVEN_INITIAL_FLUX
@ BC_HANDLER_PERIODIC_DRIVEN_CONSTANT_FLUX
@ BC_HANDLER_INLET_PROFILE_FROM_FILE
@ BC_HANDLER_OUTLET_CONSERVATION
BCHandlerType handler_type
PetscInt rotatefsi
Refused at setup: immersed boundaries and moving bodies are not implemented.
char log_dir[PETSC_MAX_PATH_LEN]
PetscInt les
Active LES closure; an LESModelType value.
PetscInt rotateframe
moveframe/rotateframe are refused at setup.
BCFace
Identifies the six logical faces of a structured computational block.
Holds the complete configuration for one of the six boundary faces.
A 3D point or vector with PetscScalar components.
Holds all data related to the state and motion of a body in FSI.
Represents a collection of nodes forming a surface for the IBM.
The master context for the entire simulation.
User-defined context containing data specific to a single computational grid level.
double nu_t(double yplus)
Computes turbulent eddy viscosity ratio (ν_t / ν)