PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | Functions | Variables
momentum_newton_krylov.c File Reference
#include "momentumsolvers.h"
Include dependency graph for momentum_newton_krylov.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  MomentumNewtonJacobian
 
struct  MomentumPreconditionerDescription
 
struct  MomentumPreconditionerModelOps
 
struct  MomentumPreconditionerEngine
 
struct  MomentumNewtonKrylovContext
 

Macros

#define __FUNCT__   "MomentumNewtonKrylov_Validate"
 
#define __FUNCT__   "MomentumNewtonKrylov_ReadLinearizationConfig"
 
#define __FUNCT__   "FrozenMomentumJacobian_DescribePointBlock"
 
#define __FUNCT__   "FrozenMomentumJacobian_AssemblePointBlocks"
 
#define __FUNCT__   "MomentumPreconditionerEngine_ApplyConstraintRows"
 
#define __FUNCT__   "MomentumNewtonJacobian_Create"
 
#define __FUNCT__   "MomentumPreconditionerEngine_Create"
 
#define __FUNCT__   "MomentumPreconditionerEngine_Assemble"
 
#define __FUNCT__   "MomentumNewtonKrylov_FormJacobian"
 
#define __FUNCT__   "MomentumNewtonKrylov_ClassifyRow"
 
#define __FUNCT__   "MomentumPreconditionerEngine_CreateExactPointBlockMatrix"
 
#define __FUNCT__   "MomentumNewtonKrylov_ApplyConstraints"
 
#define __FUNCT__   "MomentumNewtonKrylov_FormResidual"
 
#define __FUNCT__   "MomentumSolver_NewtonKrylov"
 

Enumerations

enum  MomentumNewtonJacobianType { MOM_NK_JACOBIAN_FINITE_DIFFERENCE }
 
enum  MomentumNewtonFiniteDifferenceMode { MOM_NK_FD_MODE_MATRIX_FREE }
 
enum  MomentumPreconditionerModel { MOM_NK_PC_MODEL_NONE , MOM_NK_PC_MODEL_FROZEN_MOMENTUM_JACOBIAN }
 
enum  MomentumPreconditionerStructure { MOM_NK_PC_STRUCTURE_NONE , MOM_NK_PC_STRUCTURE_POINT_BLOCK }
 
enum  MomentumNewtonKrylovRowType { MOM_NK_ROW_PHYSICAL = 0 , MOM_NK_ROW_FIXED_CONDITIONED , MOM_NK_ROW_FIXED_HOMOGENEOUS , MOM_NK_ROW_PERIODIC_DUPLICATE }
 

Functions

static PetscErrorCode MomentumNewtonKrylov_Validate (UserCtx *user)
 Rejects configurations outside the audited version-one feature set.
 
static PetscErrorCode MomentumNewtonKrylov_FormResidual (SNES snes, Vec X, Vec F, void *vctx)
 Adapts a PETSc trial vector to the existing momentum residual path.
 
static PetscErrorCode MomentumNewtonKrylov_Monitor (SNES snes, PetscInt iteration, PetscReal norm, void *vctx)
 Captures SNES iteration norms and optionally writes PICurv history rows.
 
static void MomentumNewtonKrylov_OpenHistory (MomentumNewtonKrylovContext *ctx)
 Opens the optional rank-zero Newton iteration-history file.
 
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.
 
static PetscErrorCode MomentumNewtonKrylov_ApplyConstraints (MomentumNewtonKrylovContext *ctx, Vec X, Vec F)
 Replaces every non-independent residual row with an explicit equation.
 
static MomentumNewtonKrylovRowType MomentumNewtonKrylov_ClassifyRow (UserCtx *user, PetscInt i, PetscInt j, PetscInt k, PetscInt component, PetscInt *ri, PetscInt *rj, PetscInt *rk)
 Classifies one stored staggered component row and its periodic representative.
 
static PetscErrorCode MomentumNewtonKrylov_ReadLinearizationConfig (MomentumNewtonJacobian *jacobian, MomentumPreconditionerDescription *description)
 Reads application-owned Jacobian and preconditioner mathematics.
 
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.
 
static PetscErrorCode FrozenMomentumJacobian_AssemblePointBlocks (UserCtx *user, Vec current_solution, Mat preconditioning_matrix)
 Inserts only the audited interior frozen-momentum point blocks.
 
static PetscErrorCode MomentumPreconditionerEngine_CreateExactPointBlockMatrix (UserCtx *user, Mat *preconditioning_matrix)
 Creates the frozen point-block P matrix with its exact scalar pattern.
 
static PetscReal FrozenMomentumJacobian_MetricNormSquared (Cmpnts metric)
 Returns the squared Euclidean norm of one metric vector.
 
static void FrozenMomentumJacobian_PointBlock (const SimCtx *simCtx, const Cmpnts ***ucont, const Cmpnts ***csi, const Cmpnts ***eta, const Cmpnts ***zet, const PetscReal ***aj, PetscInt i, PetscInt j, PetscInt k, PetscScalar block[9])
 Returns the audited frozen-momentum point block in modern residual sign.
 
static PetscErrorCode FrozenMomentumJacobian_DescribePointBlock (UserCtx *user, MomentumPreconditionerDescription *description)
 Describes the audited frozen-coefficient point-block model.
 
static PetscErrorCode MomentumPreconditionerEngine_ApplyConstraintRows (UserCtx *user, Mat preconditioning_matrix)
 Inserts all common fixed, homogeneous, and periodic-duplicate rows.
 
static PetscErrorCode MomentumNewtonJacobian_Create (SNES snes, MomentumNewtonJacobian *jacobian)
 Creates the selected Jacobian operator; currently PETSc MFFD only.
 
static PetscErrorCode MomentumNewtonJacobian_Update (SNES snes, Vec current_solution, MomentumNewtonJacobian *jacobian)
 Updates the matrix-free finite-difference operator base.
 
static PetscErrorCode MomentumNewtonJacobian_Register (SNES snes, MomentumNewtonJacobian *jacobian, MomentumPreconditionerEngine *engine, MomentumNewtonKrylovContext *ctx)
 Registers the application orchestration callback and both SNES matrices.
 
static PetscErrorCode MomentumNewtonJacobian_Destroy (MomentumNewtonJacobian *jacobian)
 Destroys a partially or fully created Jacobian operator.
 
static PetscErrorCode MomentumPreconditionerEngine_Create (UserCtx *user, Mat jacobian_operator, const MomentumPreconditionerDescription *requested, MomentumPreconditionerEngine *engine)
 Validates a model/structure and creates or aliases its matrix.
 
static PetscErrorCode MomentumPreconditionerEngine_Assemble (MomentumPreconditionerEngine *engine, UserCtx *user, Vec current_solution)
 Runs model insertion, common row handling, and final assembly.
 
static PetscErrorCode MomentumPreconditionerEngine_ConfigurePetscPC (MomentumPreconditionerEngine *engine, PC pc)
 Applies the validated model/structure-to-PETSc-PC mapping.
 
static PetscErrorCode MomentumPreconditionerEngine_ValidatePetscPC (MomentumPreconditionerEngine *engine, PC pc)
 Rejects raw options that select an unvalidated PETSc PC backend.
 
static PetscErrorCode MomentumPreconditionerEngine_Destroy (MomentumPreconditionerEngine *engine)
 Destroys only a separately owned preconditioning matrix.
 
PetscErrorCode MomentumSolver_NewtonKrylov (UserCtx *user, IBMNodes *ibm, FSInfo *fsi)
 Solves one physical momentum step with matrix-free Newton–Krylov.
 

Variables

static const MomentumPreconditionerModelOps frozen_momentum_point_block_ops
 

Data Structure Documentation

◆ MomentumNewtonJacobian

struct MomentumNewtonJacobian

Definition at line 11 of file momentum_newton_krylov.c.

Data Fields
MomentumNewtonJacobianType type
MomentumNewtonFiniteDifferenceMode finite_difference_mode
Mat jacobian_operator

◆ MomentumPreconditionerDescription

struct MomentumPreconditionerDescription

Definition at line 27 of file momentum_newton_krylov.c.

Data Fields
MomentumPreconditionerModel model
MomentumPreconditionerStructure structure
PetscInt block_size
PetscInt stencil_width

◆ MomentumPreconditionerEngine

struct MomentumPreconditionerEngine

Definition at line 39 of file momentum_newton_krylov.c.

Collaboration diagram for MomentumPreconditionerEngine:
[legend]
Data Fields
MomentumPreconditionerDescription description
const MomentumPreconditionerModelOps * model_ops
Mat preconditioning_matrix
PetscBool aliases_jacobian_operator
PetscBool owns_preconditioning_matrix
const char * petsc_pc_type

◆ MomentumNewtonKrylovContext

struct MomentumNewtonKrylovContext

Definition at line 48 of file momentum_newton_krylov.c.

Collaboration diagram for MomentumNewtonKrylovContext:
[legend]
Data Fields
UserCtx * user
FILE * history_file
PetscBool have_initial_norm
PetscReal initial_norm
MomentumNewtonJacobian jacobian
MomentumPreconditionerEngine preconditioning_engine

Macro Definition Documentation

◆ __FUNCT__ [1/14]

#define __FUNCT__   "MomentumNewtonKrylov_Validate"

Definition at line 203 of file momentum_newton_krylov.c.

◆ __FUNCT__ [2/14]

#define __FUNCT__   "MomentumNewtonKrylov_ReadLinearizationConfig"

Definition at line 203 of file momentum_newton_krylov.c.

◆ __FUNCT__ [3/14]

#define __FUNCT__   "FrozenMomentumJacobian_DescribePointBlock"

Definition at line 203 of file momentum_newton_krylov.c.

◆ __FUNCT__ [4/14]

#define __FUNCT__   "FrozenMomentumJacobian_AssemblePointBlocks"

Definition at line 203 of file momentum_newton_krylov.c.

◆ __FUNCT__ [5/14]

#define __FUNCT__   "MomentumPreconditionerEngine_ApplyConstraintRows"

Definition at line 203 of file momentum_newton_krylov.c.

◆ __FUNCT__ [6/14]

#define __FUNCT__   "MomentumNewtonJacobian_Create"

Definition at line 203 of file momentum_newton_krylov.c.

◆ __FUNCT__ [7/14]

#define __FUNCT__   "MomentumPreconditionerEngine_Create"

Definition at line 203 of file momentum_newton_krylov.c.

◆ __FUNCT__ [8/14]

#define __FUNCT__   "MomentumPreconditionerEngine_Assemble"

Definition at line 203 of file momentum_newton_krylov.c.

◆ __FUNCT__ [9/14]

#define __FUNCT__   "MomentumNewtonKrylov_FormJacobian"

Definition at line 203 of file momentum_newton_krylov.c.

◆ __FUNCT__ [10/14]

#define __FUNCT__   "MomentumNewtonKrylov_ClassifyRow"

Definition at line 203 of file momentum_newton_krylov.c.

◆ __FUNCT__ [11/14]

#define __FUNCT__   "MomentumPreconditionerEngine_CreateExactPointBlockMatrix"

Definition at line 203 of file momentum_newton_krylov.c.

◆ __FUNCT__ [12/14]

#define __FUNCT__   "MomentumNewtonKrylov_ApplyConstraints"

Definition at line 203 of file momentum_newton_krylov.c.

◆ __FUNCT__ [13/14]

#define __FUNCT__   "MomentumNewtonKrylov_FormResidual"

Definition at line 203 of file momentum_newton_krylov.c.

◆ __FUNCT__ [14/14]

#define __FUNCT__   "MomentumSolver_NewtonKrylov"

Definition at line 203 of file momentum_newton_krylov.c.

Enumeration Type Documentation

◆ MomentumNewtonJacobianType

Enumerator
MOM_NK_JACOBIAN_FINITE_DIFFERENCE 

Definition at line 3 of file momentum_newton_krylov.c.

◆ MomentumNewtonFiniteDifferenceMode

Enumerator
MOM_NK_FD_MODE_MATRIX_FREE 

Definition at line 7 of file momentum_newton_krylov.c.

◆ MomentumPreconditionerModel

Enumerator
MOM_NK_PC_MODEL_NONE 
MOM_NK_PC_MODEL_FROZEN_MOMENTUM_JACOBIAN 

Definition at line 17 of file momentum_newton_krylov.c.

◆ MomentumPreconditionerStructure

Enumerator
MOM_NK_PC_STRUCTURE_NONE 
MOM_NK_PC_STRUCTURE_POINT_BLOCK 

Definition at line 22 of file momentum_newton_krylov.c.

◆ MomentumNewtonKrylovRowType

Enumerator
MOM_NK_ROW_PHYSICAL 
MOM_NK_ROW_FIXED_CONDITIONED 
MOM_NK_ROW_FIXED_HOMOGENEOUS 
MOM_NK_ROW_PERIODIC_DUPLICATE 

Definition at line 59 of file momentum_newton_krylov.c.

Function Documentation

◆ MomentumNewtonKrylov_Validate()

static PetscErrorCode MomentumNewtonKrylov_Validate ( UserCtx user)
static

Rejects configurations outside the audited version-one feature set.

Parameters
userSingle-block momentum context to validate.
Returns
PetscErrorCode 0 when the configuration is supported.

Definition at line 209 of file momentum_newton_krylov.c.

210{
211 SimCtx *simCtx;
212 PetscReal mask_max = 0.0;
213 PetscInt velocity_dof = 0;
214
215 PetscFunctionBeginUser;
216 PetscCheck(user != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
217 "Newton Krylov requires a non-NULL UserCtx.");
218 simCtx = user->simCtx;
219 PetscCheck(simCtx != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
220 "Newton Krylov requires UserCtx::simCtx.");
221 PetscCall(DMDAGetInfo(user->fda, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
222 &velocity_dof, NULL, NULL, NULL, NULL, NULL));
223 PetscCheck(velocity_dof == 3, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
224 "Newton Krylov requires a three-component velocity DMDA (got dof=%d).",
225 velocity_dof);
226 PetscCheck(simCtx->block_number == 1, PETSC_COMM_WORLD, PETSC_ERR_SUP,
227 "Newton Krylov version one supports exactly one block (got %d).",
228 simCtx->block_number);
229 PetscCheck(!simCtx->immersed, PETSC_COMM_WORLD, PETSC_ERR_SUP,
230 "Newton Krylov version one does not support immersed boundaries.");
231 PetscCheck(!simCtx->movefsi && !simCtx->rotatefsi, PETSC_COMM_WORLD, PETSC_ERR_SUP,
232 "Newton Krylov version one does not support moving or rotating bodies/FSI.");
233 PetscCheck(!simCtx->moveframe && !simCtx->rotateframe, PETSC_COMM_WORLD, PETSC_ERR_SUP,
234 "Newton Krylov version one does not support moving or rotating reference frames.");
235 PetscCheck(!simCtx->rans, PETSC_COMM_WORLD, PETSC_ERR_SUP,
236 "Newton Krylov version one does not support RANS.");
237 PetscCheck(!simCtx->clark, PETSC_COMM_WORLD, PETSC_ERR_SUP,
238 "Newton Krylov version one does not support the Clark model.");
239 PetscCheck(!simCtx->TwoD, PETSC_COMM_WORLD, PETSC_ERR_SUP,
240 "Newton Krylov version one does not support TwoD component masking.");
241 PetscCheck(!simCtx->wallfunction, PETSC_COMM_WORLD, PETSC_ERR_SUP,
242 "Newton Krylov version one does not support wall functions.");
243 for (PetscInt face = 0; face < 6; ++face) {
244 const BoundaryFaceConfig *cfg = &user->boundary_faces[face];
245 PetscBool supported = PETSC_FALSE;
246
247 switch (cfg->handler_type) {
249 supported = (PetscBool)(cfg->mathematical_type == WALL);
250 break;
254 supported = (PetscBool)(cfg->mathematical_type == INLET);
255 break;
257 supported = (PetscBool)(cfg->mathematical_type == OUTLET);
258 break;
260 supported = (PetscBool)(cfg->mathematical_type == PERIODIC);
261 break;
262 default:
263 supported = PETSC_FALSE;
264 break;
265 }
266 PetscCheck(supported, PETSC_COMM_WORLD, PETSC_ERR_SUP,
267 "Newton Krylov version one does not support boundary face %d with mathematical type %d and handler %d.",
268 face, (PetscInt)cfg->mathematical_type, (PetscInt)cfg->handler_type);
269 }
270
273 PETSC_COMM_WORLD, PETSC_ERR_SUP, "Newton Krylov requires paired x-periodic faces.");
276 PETSC_COMM_WORLD, PETSC_ERR_SUP, "Newton Krylov requires paired y-periodic faces.");
279 PETSC_COMM_WORLD, PETSC_ERR_SUP, "Newton Krylov requires paired z-periodic faces.");
280
281 PetscCheck(user->Nvert != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
282 "Newton Krylov requires the cell-mask vector Nvert.");
283 PetscCall(VecMax(user->Nvert, NULL, &mask_max));
284 PetscCheck(mask_max <= 0.1, PETSC_COMM_WORLD, PETSC_ERR_SUP,
285 "Newton Krylov version one does not define equations for masked solid cells (max Nvert=%g).",
286 (double)mask_max);
287 PetscFunctionReturn(PETSC_SUCCESS);
288}
PetscInt clark
Definition variables.h:790
PetscInt movefsi
Definition variables.h:714
@ INLET
Definition variables.h:288
@ OUTLET
Definition variables.h:287
@ PERIODIC
Definition variables.h:290
@ WALL
Definition variables.h:284
PetscInt moveframe
Definition variables.h:715
PetscInt TwoD
Definition variables.h:715
BoundaryFaceConfig boundary_faces[6]
Definition variables.h:896
PetscInt block_number
Definition variables.h:768
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:879
PetscInt rans
Definition variables.h:789
@ BC_HANDLER_PERIODIC_GEOMETRIC
Definition variables.h:314
@ BC_HANDLER_INLET_PARABOLIC
Definition variables.h:307
@ BC_HANDLER_INLET_CONSTANT_VELOCITY
Definition variables.h:306
@ BC_HANDLER_INLET_PROFILE_FROM_FILE
Definition variables.h:308
@ BC_HANDLER_WALL_NOSLIP
Definition variables.h:303
@ BC_HANDLER_OUTLET_CONSERVATION
Definition variables.h:312
BCHandlerType handler_type
Definition variables.h:367
PetscInt rotatefsi
Definition variables.h:714
PetscInt wallfunction
Definition variables.h:790
Vec Nvert
Definition variables.h:904
BCType mathematical_type
Definition variables.h:366
PetscInt rotateframe
Definition variables.h:715
PetscInt immersed
Definition variables.h:714
@ BC_FACE_NEG_X
Definition variables.h:260
@ BC_FACE_POS_Z
Definition variables.h:262
@ BC_FACE_POS_Y
Definition variables.h:261
@ BC_FACE_NEG_Z
Definition variables.h:262
@ BC_FACE_POS_X
Definition variables.h:260
@ BC_FACE_NEG_Y
Definition variables.h:261
Holds the complete configuration for one of the six boundary faces.
Definition variables.h:364
The master context for the entire simulation.
Definition variables.h:684
Here is the caller graph for this function:

◆ MomentumNewtonKrylov_FormResidual()

static PetscErrorCode MomentumNewtonKrylov_FormResidual ( SNES  snes,
Vec  X,
Vec  F,
void *  vctx 
)
static

Adapts a PETSc trial vector to the existing momentum residual path.

A matrix-free SNES residual must be a deterministic function of the trial vector X alone: F(X) may not depend on any state left by a previous residual or MFFD evaluation, or finite-difference Jacobian actions become inconsistent. To honor that contract this callback fully derives the Cartesian velocity state (Ucat/lUcat) from X before the first boundary sweep – see the inline comment below for why ApplyBoundaryConditions()'s own internal reconstruction is not sufficient for the first outlet pass.

State invariants:

  • On entry, X is the only input that determines the result; user->Ucont, user->Ucat and their local ghosts are treated as scratch and are fully overwritten from X.
  • Supported handlers may overwrite flux totals and other diagnostics on every call, but those values must not affect a later call at the same X; the deterministic seed guarantees this.
  • No histories, pressure, viscosity, or controller state advance here.

Side effects: overwrites user->Ucont/lUcont, user->Ucat/lUcat, user->Rhs, the boundary Ubcs targets, and boundary flux/area diagnostics; writes F.

Parameters
snesCalling nonlinear solver.
XTrial solution (read-only).
FResidual output.
vctxPointer to MomentumNewtonKrylovContext.
Returns
PetscErrorCode 0 on success.

Definition at line 1066 of file momentum_newton_krylov.c.

1067{
1069 UserCtx *user = ctx->user;
1070 const FieldId staggered_fields[] = {FIELD_ID_UCONT};
1071 const FieldId cell_fields[] = {FIELD_ID_UCAT};
1072
1073 PetscFunctionBeginUser;
1074 (void)snes;
1075 PetscCall(VecCopy(X, user->Ucont));
1076 PetscCall(SynchronizePeriodicStaggeredFields(user, 1, staggered_fields));
1077
1078 /* Deterministic pre-boundary Cartesian seed. Establish the full Ucat/lUcat
1079 * state from the current X before any boundary handler runs:
1080 *
1081 * X -> Ucont/lUcont -> Ucat -> periodic Ucat -> lUcat -> boundaries
1082 *
1083 * Why this is required, and why it is NOT redundant with the reconstruction
1084 * already performed inside ApplyBoundaryConditions():
1085 *
1086 * 1. A matrix-free SNES residual must be a deterministic function of X. If
1087 * the Cartesian state is left over from a previous residual/MFFD call,
1088 * F(X) becomes history dependent and the finite-difference Jacobian
1089 * action Jv = (F(X+hv)-F(X))/h is invalidated.
1090 * 2. The conservation-outlet handler reads lUcat during the FIRST boundary
1091 * sweep (it measures the uncorrected outflow and builds the outlet
1092 * profile from the Cartesian field). Without this seed it would read the
1093 * stale lUcat from the preceding evaluation.
1094 * 3. ApplyBoundaryConditions() does reconstruct Ucat/lUcat, but only AFTER
1095 * each handler sweep (Contra2Cart runs after BoundarySystem_ExecuteStep
1096 * within every pass). Those internal updates therefore prepare passes 2
1097 * and 3 -- they cannot prepare the very first outlet read of pass 1.
1098 * 4. Contra2Cart() rebuilds the global Ucat interior from the current
1099 * lUcont, but it does not by itself refresh lUcat (nor lUcont; that was
1100 * done by the SynchronizePeriodicStaggeredFields call above).
1101 * 5. SynchronizePeriodicCellFields(FIELD_ID_UCAT) must run before the ghost
1102 * scatter so periodic duplicate planes are finalized consistently (it is
1103 * a no-op when no direction is periodic, as on the straight duct).
1104 * 6. UpdateLocalGhosts(FIELD_ID_UCAT) is required because the outlet handler reads
1105 * lUcat -- the local ghosted vector -- not merely the global Ucat.
1106 *
1107 * Do NOT "simplify" this to a bare Contra2Cart(user), and do NOT delete it
1108 * as apparently redundant with ApplyBoundaryConditions(): the three internal
1109 * boundary passes remain necessary (they refresh the Cartesian state after
1110 * each boundary correction), but only this sequence makes pass 1's input a
1111 * deterministic function of X. */
1112 PetscCall(Contra2Cart(user));
1113 PetscCall(SynchronizePeriodicCellFields(user, 1, cell_fields));
1114 PetscCall(UpdateLocalGhosts(user, FIELD_ID_UCAT));
1115
1116 PetscCall(ApplyBoundaryConditions(user));
1117 PetscCall(ComputeTotalResidual(user));
1118 PetscCall(VecCopy(user->Rhs, F));
1119 PetscCall(VecScale(F, -1.0));
1120 PetscCall(MomentumNewtonKrylov_ApplyConstraints(ctx, X, F));
1121 PetscFunctionReturn(PETSC_SUCCESS);
1122}
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.
@ FIELD_ID_UCAT
@ FIELD_ID_UCONT
static PetscErrorCode MomentumNewtonKrylov_ApplyConstraints(MomentumNewtonKrylovContext *ctx, Vec X, Vec F)
Replaces every non-independent residual row with an explicit equation.
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...
Definition setup.c:2564
PetscErrorCode UpdateLocalGhosts(UserCtx *user, FieldId field_id)
Updates the local vector (including ghost points) from its corresponding global vector.
Definition setup.c:1753
Vec Rhs
Definition variables.h:912
Vec Ucont
Definition variables.h:904
User-defined context containing data specific to a single computational grid level.
Definition variables.h:876
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MomentumNewtonKrylov_Monitor()

static PetscErrorCode MomentumNewtonKrylov_Monitor ( SNES  snes,
PetscInt  iteration,
PetscReal  norm,
void *  vctx 
)
static

Captures SNES iteration norms and optionally writes PICurv history rows.

SNES supplies the already-computed norm, so this monitor never causes an additional nonlinear residual evaluation. PETSc monitors selected through -mom_nk_snes_monitor remain independent and may run alongside this callback.

Definition at line 98 of file momentum_newton_krylov.c.

100{
102 SimCtx *simCtx = ctx->user->simCtx;
103
104 (void)snes;
105 PetscFunctionBeginUser;
106 if (iteration == 0 && !ctx->have_initial_norm) {
107 ctx->initial_norm = norm;
108 ctx->have_initial_norm = PETSC_TRUE;
109 }
110 if (ctx->history_file) {
111 (void)fprintf(ctx->history_file,
112 "step: %d | block: %d | newton: %d | nonlinear_norm: %.16e\n",
113 (int)simCtx->step, (int)ctx->user->_this, (int)iteration,
114 (double)norm);
115 (void)fflush(ctx->history_file);
116 }
117 PetscFunctionReturn(PETSC_SUCCESS);
118}
PetscInt _this
Definition variables.h:889
PetscInt step
Definition variables.h:692
Here is the caller graph for this function:

◆ MomentumNewtonKrylov_OpenHistory()

static void MomentumNewtonKrylov_OpenHistory ( MomentumNewtonKrylovContext ctx)
static

Opens the optional rank-zero Newton iteration-history file.

Definition at line 121 of file momentum_newton_krylov.c.

122{
123 SimCtx *simCtx = ctx->user->simCtx;
124 char path[PETSC_MAX_PATH_LEN + 128];
125 const char *mode;
126
127 if (!simCtx->mom_nk_monitor_history || simCtx->rank != 0) return;
128 if (PetscSNPrintf(path, sizeof(path),
129 "%s/Momentum_Solver_Newton_Krylov_History_Block_%d.log",
130 simCtx->log_dir, (int)ctx->user->_this)) return;
131 mode = (simCtx->step == simCtx->StartStep + 1 && !simCtx->continueMode) ? "w" : "a";
132 ctx->history_file = fopen(path, mode);
133 if (!ctx->history_file) {
134 LOG(GLOBAL, LOG_WARNING, "Could not open Newton iteration-history log '%s'.\n", path);
135 return;
136 }
137 if (mode[0] == 'w') {
138 (void)fprintf(ctx->history_file,
139 "# step | block | Newton iteration | nonlinear residual norm\n");
140 } else if (simCtx->continueMode && simCtx->step == simCtx->StartStep + 1) {
141 (void)fprintf(ctx->history_file, "# Continuation from step %d\n", (int)simCtx->StartStep);
142 }
143}
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:45
#define LOG(scope, level, fmt,...)
Logging macro for PETSc-based applications with scope control.
Definition logging.h:83
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:29
PetscBool mom_nk_monitor_history
Definition variables.h:740
PetscBool continueMode
Definition variables.h:701
PetscMPIInt rank
Definition variables.h:687
PetscInt StartStep
Definition variables.h:694
char log_dir[PETSC_MAX_PATH_LEN]
Definition variables.h:709
Here is the caller graph for this function:

◆ MomentumNewtonKrylov_WriteSummary()

static void MomentumNewtonKrylov_WriteSummary ( const MomentumNewtonKrylovContext ctx,
SNESConvergedReason  reason,
PetscInt  nonlinear_its,
PetscInt  function_evals,
PetscInt  linear_its,
PetscReal  final_norm,
PetscBool  committed 
)
static

Appends one rank-zero structured Newton result for a physical step.

File failures are deliberately diagnostic-only: rollback and PETSc cleanup must retain their original error behavior.

Definition at line 150 of file momentum_newton_krylov.c.

157{
158 SimCtx *simCtx = ctx->user->simCtx;
159 char path[PETSC_MAX_PATH_LEN + 128];
160 const char *mode;
161 const char *reason_name;
162 FILE *file;
163
164 if (simCtx->rank != 0) return;
165 if (PetscSNPrintf(path, sizeof(path),
166 "%s/Momentum_Solver_Newton_Krylov_Summary_Block_%d.log",
167 simCtx->log_dir, (int)ctx->user->_this)) return;
168 mode = (simCtx->step == simCtx->StartStep + 1 && !simCtx->continueMode) ? "w" : "a";
169 file = fopen(path, mode);
170 if (!file) {
171 LOG(GLOBAL, LOG_WARNING, "Could not open Newton summary log '%s'.\n", path);
172 return;
173 }
174 if (mode[0] == 'w') {
175 (void)fprintf(file,
176 "# step | block | solver | Jacobian | preconditioner | SNES reason | "
177 "reason code | Newton iterations | "
178 "residual evaluations | Krylov iterations | initial nonlinear norm | "
179 "final nonlinear norm | state\n");
180 } else if (simCtx->continueMode && simCtx->step == simCtx->StartStep + 1) {
181 (void)fprintf(file, "# Continuation from step %d\n", (int)simCtx->StartStep);
182 }
183 reason_name = reason == SNES_CONVERGED_ITERATING
184 ? "SNES_CONVERGED_ITERATING" : SNESConvergedReasons[reason];
185 (void)fprintf(file,
186 "step: %d | block: %d | solver: Newton Krylov | "
187 "Jacobian: finite_difference / matrix_free | Preconditioner: %s | "
188 "reason: %s | reason_code: %d | "
189 "newton: %d | evals: %d | krylov: %d | initial: ",
190 (int)simCtx->step, (int)ctx->user->_this,
192 "none" : "frozen_momentum_jacobian / point_block",
193 reason_name, (int)reason,
194 (int)nonlinear_its, (int)function_evals, (int)linear_its);
195 if (ctx->have_initial_norm) (void)fprintf(file, "%.16e", (double)ctx->initial_norm);
196 else (void)fprintf(file, "unavailable");
197 (void)fprintf(file, " | final: %.16e | state: %s\n", (double)final_norm,
198 committed ? "committed" : "rolled_back");
199 (void)fclose(file);
200}
MomentumPreconditionerDescription description
MomentumPreconditionerEngine preconditioning_engine
Here is the caller graph for this function:

◆ MomentumNewtonKrylov_ApplyConstraints()

static PetscErrorCode MomentumNewtonKrylov_ApplyConstraints ( MomentumNewtonKrylovContext ctx,
Vec  X,
Vec  F 
)
static

Replaces every non-independent residual row with an explicit equation.

Conditioned face-normal rows use F=X-Uconditioned, unconditioned legacy dummy/tangential rows use F=X, and periodic duplicates use Fdup=Xdup-Xrep. These equations prevent the zero Jacobian rows produced by simply retaining EnforceRHSBoundaryConditions() zeros in a matrix-free Newton operator. Immersed, masked, TwoD, and interface rows are rejected before this callback is installed.

Parameters
ctxActive solve context.
XUnconditioned PETSc trial state.
FResidual vector to update in place.
Returns
PetscErrorCode 0 on success.

Definition at line 986 of file momentum_newton_krylov.c.

988{
989 UserCtx *user = ctx->user;
990 DMDALocalInfo info = user->info;
991 Vec local_x = NULL;
992 Cmpnts ***x = NULL, ***conditioned = NULL, ***f = NULL, ***lx = NULL;
993 const PetscInt xs = info.xs, xe = info.xs + info.xm;
994 const PetscInt ys = info.ys, ye = info.ys + info.ym;
995 const PetscInt zs = info.zs, ze = info.zs + info.zm;
996
997 PetscFunctionBeginUser;
998 PetscCall(DMGetLocalVector(user->fda, &local_x));
999 PetscCall(DMGlobalToLocalBegin(user->fda, X, INSERT_VALUES, local_x));
1000 PetscCall(DMGlobalToLocalEnd(user->fda, X, INSERT_VALUES, local_x));
1001 PetscCall(DMDAVecGetArrayRead(user->fda, X, &x));
1002 PetscCall(DMDAVecGetArrayRead(user->fda, user->Ucont, &conditioned));
1003 PetscCall(DMDAVecGetArray(user->fda, F, &f));
1004 PetscCall(DMDAVecGetArrayRead(user->fda, local_x, &lx));
1005
1006 for (PetscInt k = zs; k < ze; ++k) {
1007 for (PetscInt j = ys; j < ye; ++j) {
1008 for (PetscInt i = xs; i < xe; ++i) {
1009 PetscScalar *fv = &f[k][j][i].x;
1010 const PetscScalar *xv = &x[k][j][i].x;
1011 const PetscScalar *cv = &conditioned[k][j][i].x;
1012
1013 for (PetscInt component = 0; component < 3; ++component) {
1014 PetscInt ri, rj, rk;
1016 user, i, j, k, component, &ri, &rj, &rk);
1017 const PetscScalar *rv = &lx[rk][rj][ri].x;
1018
1019 if (row == MOM_NK_ROW_FIXED_CONDITIONED) fv[component] = xv[component] - cv[component];
1020 else if (row == MOM_NK_ROW_FIXED_HOMOGENEOUS) fv[component] = xv[component];
1021 else if (row == MOM_NK_ROW_PERIODIC_DUPLICATE) fv[component] = xv[component] - rv[component];
1022 }
1023 }
1024 }
1025 }
1026
1027 PetscCall(DMDAVecRestoreArrayRead(user->fda, local_x, &lx));
1028 PetscCall(DMDAVecRestoreArray(user->fda, F, &f));
1029 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->Ucont, &conditioned));
1030 PetscCall(DMDAVecRestoreArrayRead(user->fda, X, &x));
1031 PetscCall(DMRestoreLocalVector(user->fda, &local_x));
1032 PetscFunctionReturn(PETSC_SUCCESS);
1033}
static MomentumNewtonKrylovRowType MomentumNewtonKrylov_ClassifyRow(UserCtx *user, PetscInt i, PetscInt j, PetscInt k, PetscInt component, PetscInt *ri, PetscInt *rj, PetscInt *rk)
Classifies one stored staggered component row and its periodic representative.
PetscScalar x
Definition variables.h:101
DMDALocalInfo info
Definition variables.h:883
A 3D point or vector with PetscScalar components.
Definition variables.h:100
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MomentumNewtonKrylov_ClassifyRow()

static MomentumNewtonKrylovRowType MomentumNewtonKrylov_ClassifyRow ( UserCtx user,
PetscInt  i,
PetscInt  j,
PetscInt  k,
PetscInt  component,
PetscInt *  ri,
PetscInt *  rj,
PetscInt *  rk 
)
static

Classifies one stored staggered component row and its periodic representative.

Negative nonperiodic planes and positive dummy planes are zeroed by the legacy residual treatment. Only a face-normal row actually written by its boundary handler is conditioned; the remaining zeroed rows use F=X. Periodic endpoint rows use the same wrapped representatives as SynchronizePeriodicStaggeredFields(). At periodic/nonperiodic intersections the periodic equation owns rows that a shrunken boundary-handler loop does not condition.

Parameters
userBlock context containing boundary metadata and global dimensions.
iGlobal i index.
jGlobal j index.
kGlobal k index.
componentStored component, 0=x, 1=y, 2=z.
riReturned periodic representative i index.
rjReturned periodic representative j index.
rkReturned periodic representative k index.
Returns
Exact version-one row category.

Definition at line 769 of file momentum_newton_krylov.c.

772{
773 const PetscInt mx = user->info.mx, my = user->info.my, mz = user->info.mz;
774 const PetscInt coord[3] = {i, j, k};
775 const PetscInt size[3] = {mx, my, mz};
776 const BCFace neg_face[3] = {BC_FACE_NEG_X, BC_FACE_NEG_Y, BC_FACE_NEG_Z};
777 PetscBool periodic[3], periodic_duplicate = PETSC_FALSE;
778 PetscBool residual_zeroed = PETSC_FALSE, conditioned = PETSC_FALSE;
779
780 *ri = i; *rj = j; *rk = k;
781 for (PetscInt axis = 0; axis < 3; ++axis) {
782 periodic[axis] = (PetscBool)(
783 user->boundary_faces[neg_face[axis]].mathematical_type == PERIODIC);
784 if (periodic[axis] && coord[axis] == 0) {
785 periodic_duplicate = PETSC_TRUE;
786 if (axis == 0) *ri = -2;
787 else if (axis == 1) *rj = -2;
788 else *rk = -2;
789 }
790 if (periodic[axis] && coord[axis] == size[axis] - 1) {
791 periodic_duplicate = PETSC_TRUE;
792 if (axis == 0) *ri = mx + 1;
793 else if (axis == 1) *rj = my + 1;
794 else *rk = mz + 1;
795 }
796
797 if (!periodic[axis] && coord[axis] == 0) residual_zeroed = PETSC_TRUE;
798 if (coord[axis] == size[axis] - 1) residual_zeroed = PETSC_TRUE;
799 if (!periodic[axis] && coord[axis] == size[axis] - 2 && component == axis)
800 residual_zeroed = PETSC_TRUE;
801 }
802
803 if (!periodic[component] &&
804 (coord[component] == 0 || coord[component] == size[component] - 2)) {
805 PetscBool tangential_interior = PETSC_TRUE;
806 for (PetscInt axis = 0; axis < 3; ++axis) {
807 if (axis == component) continue;
808 if (coord[axis] < 1 || coord[axis] > size[axis] - 2)
809 tangential_interior = PETSC_FALSE;
810 }
811 conditioned = tangential_interior;
812 }
813
814 if (conditioned) return MOM_NK_ROW_FIXED_CONDITIONED;
815 if (periodic_duplicate) return MOM_NK_ROW_PERIODIC_DUPLICATE;
816 if (residual_zeroed) return MOM_NK_ROW_FIXED_HOMOGENEOUS;
817 return MOM_NK_ROW_PHYSICAL;
818}
BCFace
Identifies the six logical faces of a structured computational block.
Definition variables.h:259
Here is the caller graph for this function:

◆ MomentumNewtonKrylov_ReadLinearizationConfig()

static PetscErrorCode MomentumNewtonKrylov_ReadLinearizationConfig ( MomentumNewtonJacobian jacobian,
MomentumPreconditionerDescription description 
)
static

Reads application-owned Jacobian and preconditioner mathematics.

Definition at line 295 of file momentum_newton_krylov.c.

297{
298 char type[48] = "finite_difference";
299 char finite_difference_mode[32] = "matrix_free";
300 char model[48] = "none";
301 char structure[32] = "none";
302 PetscBool set = PETSC_FALSE, match = PETSC_FALSE;
303
304 PetscFunctionBeginUser;
305 PetscCheck(jacobian != NULL && description != NULL, PETSC_COMM_SELF,
306 PETSC_ERR_ARG_NULL, "Newton Krylov linearization configuration is NULL.");
307 PetscCall(PetscOptionsGetString(NULL, NULL, "-mom_nk_jacobian_type",
308 type, sizeof(type), &set));
309 PetscCall(PetscStrcasecmp(type, "finite_difference", &match));
310 PetscCheck(match, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
311 "-mom_nk_jacobian_type must be 'finite_difference' (got '%s').", type);
313 PetscCall(PetscOptionsGetString(NULL, NULL, "-mom_nk_jacobian_fd_mode",
314 finite_difference_mode,
315 sizeof(finite_difference_mode), &set));
316 PetscCall(PetscStrcasecmp(finite_difference_mode, "matrix_free", &match));
317 PetscCheck(match, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
318 "-mom_nk_jacobian_fd_mode must be 'matrix_free' (got '%s').",
319 finite_difference_mode);
321
322 PetscCall(PetscOptionsGetString(NULL, NULL, "-mom_nk_preconditioner_model",
323 model, sizeof(model), &set));
324 PetscCall(PetscStrcasecmp(model, "none", &match));
325 if (match) description->model = MOM_NK_PC_MODEL_NONE;
326 if (!match) {
327 PetscCall(PetscStrcasecmp(model, "frozen_momentum_jacobian", &match));
328 if (match) description->model = MOM_NK_PC_MODEL_FROZEN_MOMENTUM_JACOBIAN;
329 }
330 PetscCheck(match, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
331 "-mom_nk_preconditioner_model must be 'none' or "
332 "'frozen_momentum_jacobian' (got '%s').", model);
333 PetscCall(PetscOptionsGetString(NULL, NULL, "-mom_nk_preconditioner_structure",
334 structure, sizeof(structure), &set));
335 PetscCall(PetscStrcasecmp(structure, "none", &match));
336 if (match) description->structure = MOM_NK_PC_STRUCTURE_NONE;
337 if (!match) {
338 PetscCall(PetscStrcasecmp(structure, "point_block", &match));
339 if (match) description->structure = MOM_NK_PC_STRUCTURE_POINT_BLOCK;
340 }
341 PetscCheck(match, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
342 "-mom_nk_preconditioner_structure must be 'none' or 'point_block' "
343 "(got '%s').", structure);
344 PetscCheck((description->model == MOM_NK_PC_MODEL_NONE &&
345 description->structure == MOM_NK_PC_STRUCTURE_NONE) ||
348 PETSC_COMM_WORLD, PETSC_ERR_SUP,
349 "Unsupported Newton Krylov preconditioner model/structure combination: "
350 "model='%s', structure='%s'.", model, structure);
351 PetscFunctionReturn(PETSC_SUCCESS);
352}
MomentumNewtonFiniteDifferenceMode finite_difference_mode
MomentumNewtonJacobianType type
MomentumPreconditionerStructure structure
Here is the caller graph for this function:

◆ MomentumNewtonKrylov_FormJacobian()

static PetscErrorCode MomentumNewtonKrylov_FormJacobian ( SNES  snes,
Vec  current_solution,
Mat  jacobian_operator,
Mat  preconditioning_matrix,
void *  vctx 
)
static

Updates the Jacobian and then assembles any separate preconditioning matrix.

Definition at line 734 of file momentum_newton_krylov.c.

736{
738 PetscFunctionBeginUser;
739 (void)jacobian_operator;
740 (void)preconditioning_matrix;
741 PetscCall(MomentumNewtonJacobian_Update(snes, current_solution, &ctx->jacobian));
743 &ctx->preconditioning_engine, ctx->user, current_solution));
744 PetscFunctionReturn(PETSC_SUCCESS);
745}
static PetscErrorCode MomentumPreconditionerEngine_Assemble(MomentumPreconditionerEngine *engine, UserCtx *user, Vec current_solution)
Runs model insertion, common row handling, and final assembly.
static PetscErrorCode MomentumNewtonJacobian_Update(SNES snes, Vec current_solution, MomentumNewtonJacobian *jacobian)
Updates the matrix-free finite-difference operator base.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FrozenMomentumJacobian_AssemblePointBlocks()

static PetscErrorCode FrozenMomentumJacobian_AssemblePointBlocks ( UserCtx user,
Vec  current_solution,
Mat  preconditioning_matrix 
)
static

Inserts only the audited interior frozen-momentum point blocks.

Definition at line 485 of file momentum_newton_krylov.c.

487{
488 DMDALocalInfo info = user->info;
489 Cmpnts ***ucont = NULL, ***csi = NULL, ***eta = NULL, ***zet = NULL;
490 PetscReal ***aj = NULL;
491 PetscErrorCode ierr = PETSC_SUCCESS, cleanup_ierr;
492
493 PetscFunctionBeginUser;
494 /*
495 * current_solution is the current SNES trial Ucont Vec: it is layout-compatible
496 * with user->fda/user->Ucont, but is not necessarily the canonical user->Ucont
497 * selected by UpdateLocalGhosts(FIELD_ID_UCONT). Scatter that trial Vec directly with
498 * user->fda so PETSc applies its MPI ownership, periodic topology, component
499 * ordering, and ghost mapping without canonical-field synchronization or mutation
500 * of current_solution. UpdateLocalGhosts additionally repairs the component-normal
501 * staggered buffers Uxi(i=-1,mx), Ueta(j=-1,my), and Uzeta(k=-1,mz); the audited
502 * point-block velocity stencil reads none of those planes, so the repair cannot
503 * change a coefficient. Revisit this choice and extend the periodic-localization
504 * tests if the model stencil is expanded to read any repaired normal buffer.
505 */
506 ierr = DMGlobalToLocalBegin(user->fda, current_solution, INSERT_VALUES, user->lUcont);
507 if (ierr) goto cleanup;
508 ierr = DMGlobalToLocalEnd(user->fda, current_solution, INSERT_VALUES, user->lUcont);
509 if (ierr) goto cleanup;
510 ierr = DMDAVecGetArrayRead(user->fda, user->lUcont, &ucont); if (ierr) goto cleanup;
511 ierr = DMDAVecGetArrayRead(user->fda, user->lCsi, &csi); if (ierr) goto cleanup;
512 ierr = DMDAVecGetArrayRead(user->fda, user->lEta, &eta); if (ierr) goto cleanup;
513 ierr = DMDAVecGetArrayRead(user->fda, user->lZet, &zet); if (ierr) goto cleanup;
514 ierr = DMDAVecGetArrayRead(user->da, user->lAj, &aj); if (ierr) goto cleanup;
515 for (PetscInt k = info.zs; k < info.zs + info.zm; ++k) {
516 for (PetscInt j = info.ys; j < info.ys + info.ym; ++j) {
517 for (PetscInt i = info.xs; i < info.xs + info.xm; ++i) {
518 for (PetscInt component = 0; component < 3; ++component) {
519 MatStencil row = {.i = i, .j = j, .k = k, .c = component};
520 PetscInt ri, rj, rk;
522 user, i, j, k, component, &ri, &rj, &rk);
523 if (type == MOM_NK_ROW_PHYSICAL) {
524 PetscScalar block[9];
525 MatStencil cols[3] = {
526 {.i = i, .j = j, .k = k, .c = 0},
527 {.i = i, .j = j, .k = k, .c = 1},
528 {.i = i, .j = j, .k = k, .c = 2}
529 };
530 FrozenMomentumJacobian_PointBlock(user->simCtx, (const Cmpnts ***)ucont,
531 (const Cmpnts ***)csi, (const Cmpnts ***)eta, (const Cmpnts ***)zet,
532 (const PetscReal ***)aj, i, j, k, block);
533 ierr = MatSetValuesStencil(preconditioning_matrix, 1, &row, 3, cols,
534 &block[3 * component], INSERT_VALUES);
535 if (ierr) goto cleanup;
536 }
537 }
538 }
539 }
540 }
541cleanup:
542 if (aj) { cleanup_ierr = DMDAVecRestoreArrayRead(user->da, user->lAj, &aj); if (!ierr) ierr = cleanup_ierr; }
543 if (zet) { cleanup_ierr = DMDAVecRestoreArrayRead(user->fda, user->lZet, &zet); if (!ierr) ierr = cleanup_ierr; }
544 if (eta) { cleanup_ierr = DMDAVecRestoreArrayRead(user->fda, user->lEta, &eta); if (!ierr) ierr = cleanup_ierr; }
545 if (csi) { cleanup_ierr = DMDAVecRestoreArrayRead(user->fda, user->lCsi, &csi); if (!ierr) ierr = cleanup_ierr; }
546 if (ucont) { cleanup_ierr = DMDAVecRestoreArrayRead(user->fda, user->lUcont, &ucont); if (!ierr) ierr = cleanup_ierr; }
547 PetscFunctionReturn(ierr);
548}
static void FrozenMomentumJacobian_PointBlock(const SimCtx *simCtx, const Cmpnts ***ucont, const Cmpnts ***csi, const Cmpnts ***eta, const Cmpnts ***zet, const PetscReal ***aj, PetscInt i, PetscInt j, PetscInt k, PetscScalar block[9])
Returns the audited frozen-momentum point block in modern residual sign.
Vec lZet
Definition variables.h:927
Vec lCsi
Definition variables.h:927
Vec lUcont
Definition variables.h:904
Vec lAj
Definition variables.h:927
Vec lEta
Definition variables.h:927
Here is the call graph for this function:

◆ MomentumPreconditionerEngine_CreateExactPointBlockMatrix()

static PetscErrorCode MomentumPreconditionerEngine_CreateExactPointBlockMatrix ( UserCtx user,
Mat *  preconditioning_matrix 
)
static

Creates the frozen point-block P matrix with its exact scalar pattern.

Row and column ownership follows the velocity DMDA global vector. Physical rows reserve the three same-point components, fixed rows reserve only their diagonal, and periodic duplicate rows additionally reserve their wrapped representative. DMDA AO, local mapping, and stencil metadata are retained so the existing insertion paths keep their exact ordering.

Definition at line 830 of file momentum_newton_krylov.c.

832{
833 DMDALocalInfo info;
834 ISLocalToGlobalMapping local_to_global = NULL;
835 Mat matrix = NULL;
836 MPI_Comm comm;
837 PetscInt local_size, global_size, ownership_start, ownership_end;
838 PetscInt *diagonal_nnz = NULL, *offdiagonal_nnz = NULL;
839 PetscInt ghost_starts[4] = {0, 0, 0, 0}, ghost_sizes[3] = {0, 0, 0};
840 PetscErrorCode ierr = PETSC_SUCCESS, cleanup_ierr;
841
842 PetscFunctionBeginUser;
843 PetscCheck(preconditioning_matrix != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
844 "Point-block matrix output is NULL.");
845 *preconditioning_matrix = NULL;
846 comm = PetscObjectComm((PetscObject)user->fda);
847 PetscCall(DMDAGetLocalInfo(user->fda, &info));
848 PetscCall(VecGetLocalSize(user->Ucont, &local_size));
849 PetscCall(VecGetSize(user->Ucont, &global_size));
850 PetscCall(VecGetOwnershipRange(user->Ucont, &ownership_start, &ownership_end));
851 PetscCheck(local_size == ownership_end - ownership_start, comm, PETSC_ERR_PLIB,
852 "Velocity ownership range does not match its local size.");
853 ierr = PetscCalloc2(local_size, &diagonal_nnz,
854 local_size, &offdiagonal_nnz); if (ierr) goto cleanup;
855 ierr = DMGetLocalToGlobalMapping(user->fda, &local_to_global); if (ierr) goto cleanup;
856 ierr = DMDAGetGhostCorners(user->fda,
857 &ghost_starts[0], &ghost_starts[1], &ghost_starts[2],
858 &ghost_sizes[0], &ghost_sizes[1], &ghost_sizes[2]);
859 if (ierr) goto cleanup;
860
861 for (PetscInt k = info.zs; k < info.zs + info.zm; ++k) {
862 for (PetscInt j = info.ys; j < info.ys + info.ym; ++j) {
863 for (PetscInt i = info.xs; i < info.xs + info.xm; ++i) {
864 for (PetscInt component = 0; component < 3; ++component) {
865 PetscInt ri, rj, rk, column_count;
866 MatStencil row_stencil = {.i = i, .j = j, .k = k, .c = component};
867 MatStencil column_stencils[3];
868 PetscInt row_local, row, column_locals[3], columns[3];
870 user, i, j, k, component, &ri, &rj, &rk);
871
872 if (type == MOM_NK_ROW_PHYSICAL) {
873 column_count = 3;
874 for (PetscInt column_component = 0; column_component < 3;
875 ++column_component) {
876 column_stencils[column_component] = (MatStencil){
877 .i = i, .j = j, .k = k, .c = column_component
878 };
879 }
880 } else {
881 column_count = 1;
882 column_stencils[0] = row_stencil;
883 if (type == MOM_NK_ROW_PERIODIC_DUPLICATE) {
884 column_stencils[column_count++] = (MatStencil){
885 .i = ri, .j = rj, .k = rk, .c = component
886 };
887 }
888 }
889 row_local = component + 3 * (
890 (i - ghost_starts[0]) + ghost_sizes[0] * (
891 (j - ghost_starts[1]) + ghost_sizes[1] *
892 (k - ghost_starts[2])));
893 for (PetscInt column_index = 0; column_index < column_count;
894 ++column_index) {
895 const MatStencil column = column_stencils[column_index];
896 if (!(column.i >= ghost_starts[0] &&
897 column.i < ghost_starts[0] + ghost_sizes[0] &&
898 column.j >= ghost_starts[1] &&
899 column.j < ghost_starts[1] + ghost_sizes[1] &&
900 column.k >= ghost_starts[2] &&
901 column.k < ghost_starts[2] + ghost_sizes[2])) {
902 ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__,
903 PETSC_ERR_ARG_OUTOFRANGE,
904 PETSC_ERROR_INITIAL,
905 "Point-block column lies outside the DMDA ghost stencil.");
906 goto cleanup;
907 }
908 column_locals[column_index] = column.c + 3 * (
909 (column.i - ghost_starts[0]) + ghost_sizes[0] * (
910 (column.j - ghost_starts[1]) + ghost_sizes[1] *
911 (column.k - ghost_starts[2])));
912 }
913 ierr = ISLocalToGlobalMappingApply(local_to_global, 1,
914 &row_local, &row);
915 if (ierr) goto cleanup;
916 ierr = ISLocalToGlobalMappingApply(local_to_global, column_count,
917 column_locals, columns);
918 if (ierr) goto cleanup;
919 if (!(row >= ownership_start && row < ownership_end)) {
920 ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__,
921 PETSC_ERR_PLIB, PETSC_ERROR_INITIAL,
922 "DMDA-mapped point-block row is not locally owned.");
923 goto cleanup;
924 }
925 for (PetscInt column_index = 0; column_index < column_count;
926 ++column_index) {
927 PetscBool duplicate = PETSC_FALSE;
928 for (PetscInt previous = 0; previous < column_index; ++previous)
929 if (columns[previous] == columns[column_index]) duplicate = PETSC_TRUE;
930 if (columns[column_index] < 0) {
931 ierr = PetscError(comm, __LINE__, PETSC_FUNCTION_NAME, __FILE__,
932 PETSC_ERR_PLIB, PETSC_ERROR_INITIAL,
933 "DMDA-mapped point-block column is invalid.");
934 goto cleanup;
935 }
936 if (duplicate) continue;
937 if (columns[column_index] >= ownership_start &&
938 columns[column_index] < ownership_end)
939 ++diagonal_nnz[row - ownership_start];
940 else
941 ++offdiagonal_nnz[row - ownership_start];
942 }
943 }
944 }
945 }
946 }
947
948 ierr = MatCreateAIJ(comm, local_size, local_size, global_size, global_size,
949 0, diagonal_nnz, 0, offdiagonal_nnz, &matrix);
950 if (ierr) goto cleanup;
951 ierr = MatSetBlockSize(matrix, 3); if (ierr) goto cleanup;
952 ierr = MatSetLocalToGlobalMapping(matrix, local_to_global, local_to_global);
953 if (ierr) goto cleanup;
954 ierr = MatSetStencil(matrix, 3, ghost_sizes, ghost_starts, 3);
955 if (ierr) goto cleanup;
956 ierr = MatSetDM(matrix, user->fda); if (ierr) goto cleanup;
957 ierr = MatSetOption(matrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);
958 if (ierr) goto cleanup;
959 ierr = PetscFree2(diagonal_nnz, offdiagonal_nnz); if (ierr) goto cleanup;
960
961 *preconditioning_matrix = matrix;
962 matrix = NULL;
963
964cleanup:
965 cleanup_ierr = MatDestroy(&matrix); if (!ierr) ierr = cleanup_ierr;
966 cleanup_ierr = PetscFree2(diagonal_nnz, offdiagonal_nnz);
967 if (!ierr) ierr = cleanup_ierr;
968 PetscFunctionReturn(ierr);
969}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FrozenMomentumJacobian_MetricNormSquared()

static PetscReal FrozenMomentumJacobian_MetricNormSquared ( Cmpnts  metric)
static

Returns the squared Euclidean norm of one metric vector.

Definition at line 355 of file momentum_newton_krylov.c.

356{
357 return metric.x * metric.x + metric.y * metric.y + metric.z * metric.z;
358}
PetscScalar z
Definition variables.h:101
PetscScalar y
Definition variables.h:101
Here is the caller graph for this function:

◆ FrozenMomentumJacobian_PointBlock()

static void FrozenMomentumJacobian_PointBlock ( const SimCtx simCtx,
const Cmpnts ***  ucont,
const Cmpnts ***  csi,
const Cmpnts ***  eta,
const Cmpnts ***  zet,
const PetscReal ***  aj,
PetscInt  i,
PetscInt  j,
PetscInt  k,
PetscScalar  block[9] 
)
static

Returns the audited frozen-momentum point block in modern residual sign.

Definition at line 361 of file momentum_newton_krylov.c.

365{
366 const PetscReal dtc = MomentumBDFCoefficient((SimCtx *)simCtx) / simCtx->dt;
367 const PetscReal inverse_reynolds = simCtx->ren > 0.0 ? 1.0 / simCtx->ren : 0.0;
368 const PetscReal AJip = 0.5 * (aj[k][j][i] + aj[k][j][i + 1]);
369 const PetscReal AJjp = 0.5 * (aj[k][j][i] + aj[k][j + 1][i]);
370 const PetscReal AJkp = 0.5 * (aj[k][j][i] + aj[k + 1][j][i]);
371 const PetscReal g11ip = csi[k][j][i].x * csi[k][j][i].x +
372 csi[k][j][i].y * csi[k][j][i].y +
373 csi[k][j][i].z * csi[k][j][i].z;
374 const PetscReal g22ip = 0.25 * (
378 FrozenMomentumJacobian_MetricNormSquared(eta[k][j - 1][i + 1]));
379 const PetscReal g33ip = 0.25 * (
383 FrozenMomentumJacobian_MetricNormSquared(zet[k - 1][j][i + 1]));
384 const PetscReal g11jp = 0.25 * (
388 FrozenMomentumJacobian_MetricNormSquared(csi[k][j + 1][i - 1]));
389 const PetscReal g22jp = eta[k][j][i].x * eta[k][j][i].x +
390 eta[k][j][i].y * eta[k][j][i].y +
391 eta[k][j][i].z * eta[k][j][i].z;
392 const PetscReal g33jp = 0.25 * (
396 FrozenMomentumJacobian_MetricNormSquared(zet[k - 1][j + 1][i]));
397 const PetscReal g11kp = 0.25 * (
401 FrozenMomentumJacobian_MetricNormSquared(csi[k + 1][j][i - 1]));
402 const PetscReal g22kp = 0.25 * (
406 FrozenMomentumJacobian_MetricNormSquared(eta[k + 1][j - 1][i]));
407 const PetscReal g33kp = zet[k][j][i].x * zet[k][j][i].x +
408 zet[k][j][i].y * zet[k][j][i].y +
409 zet[k][j][i].z * zet[k][j][i].z;
410 const PetscReal U0jp = 0.25 * (ucont[k][j][i].x + ucont[k][j][i - 1].x +
411 ucont[k][j + 1][i].x + ucont[k][j + 1][i - 1].x);
412 const PetscReal U0kp = 0.25 * (ucont[k][j][i].x + ucont[k][j][i - 1].x +
413 ucont[k + 1][j][i].x + ucont[k + 1][j][i - 1].x);
414 const PetscReal U1ip = 0.25 * (ucont[k][j][i].y + ucont[k][j - 1][i].y +
415 ucont[k][j][i + 1].y + ucont[k][j - 1][i + 1].y);
416 const PetscReal U1kp = 0.25 * (ucont[k][j][i].y + ucont[k][j - 1][i].y +
417 ucont[k + 1][j][i].y + ucont[k + 1][j - 1][i].y);
418 const PetscReal U2ip = 0.25 * (ucont[k][j][i].z + ucont[k - 1][j][i].z +
419 ucont[k][j][i + 1].z + ucont[k - 1][j][i + 1].z);
420 const PetscReal U2jp = 0.25 * (ucont[k][j][i].z + ucont[k - 1][j][i].z +
421 ucont[k][j + 1][i].z + ucont[k - 1][j + 1][i].z);
422 PetscReal A[6][4] = {{0.0}};
423 PetscReal Su, Sv, Sw, nui, nuj, nuk;
424
425 A[0][0] = 0.125 * aj[k][j][i] * ucont[k][j][i].y;
426 A[0][1] = -0.125 * aj[k][j - 1][i] * ucont[k][j - 1][i].y;
427 A[0][2] = 0.125 * aj[k][j][i + 1] * ucont[k][j][i + 1].y;
428 A[0][3] = -0.125 * aj[k][j - 1][i + 1] * ucont[k][j - 1][i + 1].y;
429 A[1][0] = 0.125 * aj[k][j][i] * ucont[k][j][i].z;
430 A[1][1] = -0.125 * aj[k - 1][j][i] * ucont[k - 1][j][i].z;
431 A[1][2] = 0.125 * aj[k][j][i + 1] * ucont[k][j][i + 1].z;
432 A[1][3] = -0.125 * aj[k - 1][j][i + 1] * ucont[k - 1][j][i + 1].z;
433 A[2][0] = -0.125 * aj[k][j + 1][i - 1] * ucont[k][j + 1][i - 1].x;
434 A[2][1] = -0.125 * aj[k][j][i - 1] * ucont[k][j][i - 1].x;
435 A[2][2] = 0.125 * aj[k][j + 1][i] * ucont[k][j + 1][i].x;
436 A[2][3] = 0.125 * aj[k][j][i] * ucont[k][j][i].x;
437 A[3][0] = 0.125 * aj[k][j][i] * ucont[k][j][i].z;
438 A[3][1] = -0.125 * aj[k - 1][j][i] * ucont[k - 1][j][i].z;
439 A[3][2] = 0.125 * aj[k][j + 1][i] * ucont[k][j + 1][i].z;
440 A[3][3] = -0.125 * aj[k - 1][j + 1][i] * ucont[k - 1][j + 1][i].z;
441 A[4][0] = -0.125 * aj[k + 1][j][i - 1] * ucont[k + 1][j][i - 1].x;
442 A[4][1] = -0.125 * aj[k][j][i - 1] * ucont[k][j][i - 1].x;
443 A[4][2] = 0.125 * aj[k + 1][j][i] * ucont[k + 1][j][i].x;
444 A[4][3] = 0.125 * aj[k][j][i] * ucont[k][j][i].x;
445 A[5][0] = -0.125 * aj[k + 1][j - 1][i] * ucont[k + 1][j - 1][i].y;
446 A[5][1] = -0.125 * aj[k][j - 1][i] * ucont[k][j - 1][i].y;
447 A[5][2] = 0.125 * aj[k + 1][j][i] * ucont[k + 1][j][i].y;
448 A[5][3] = 0.125 * aj[k][j][i] * ucont[k][j][i].y;
449 Su = A[0][0] + A[0][1] + A[0][2] + A[0][3] +
450 A[1][0] + A[1][1] + A[1][2] + A[1][3];
451 Sv = A[2][0] + A[2][1] + A[2][2] + A[2][3] +
452 A[3][0] + A[3][1] + A[3][2] + A[3][3];
453 Sw = A[4][0] + A[4][1] + A[4][2] + A[4][3] +
454 A[5][0] + A[5][1] + A[5][2] + A[5][3];
455 nui = AJip * AJip * (g11ip + g22ip + g33ip) * inverse_reynolds;
456 nuj = AJjp * AJjp * (g11jp + g22jp + g33jp) * inverse_reynolds;
457 nuk = AJkp * AJkp * (g11kp + g22kp + g33kp) * inverse_reynolds;
458
459 /* The modern residual is the negative of the legacy residual. */
460 block[0] = dtc + nui + Su; block[1] = 0.5 * AJip * U1ip; block[2] = 0.5 * AJip * U2ip;
461 block[3] = 0.5 * AJjp * U0jp; block[4] = dtc + nuj + Sv; block[5] = 0.5 * AJjp * U2jp;
462 block[6] = 0.5 * AJkp * U0kp; block[7] = 0.5 * AJkp * U1kp; block[8] = dtc + nuk + Sw;
463}
static PetscReal FrozenMomentumJacobian_MetricNormSquared(Cmpnts metric)
Returns the squared Euclidean norm of one metric vector.
PetscReal MomentumBDFCoefficient(SimCtx *simCtx)
Returns the BDF physical-time coefficient a0 for the current step.
PetscReal ren
Definition variables.h:732
PetscReal dt
Definition variables.h:699
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FrozenMomentumJacobian_DescribePointBlock()

static PetscErrorCode FrozenMomentumJacobian_DescribePointBlock ( UserCtx user,
MomentumPreconditionerDescription description 
)
static

Describes the audited frozen-coefficient point-block model.

Definition at line 468 of file momentum_newton_krylov.c.

470{
471 PetscFunctionBeginUser;
472 (void)user;
473 PetscCheck(description != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
474 "Preconditioner description is NULL.");
477 description->block_size = 3;
478 description->stencil_width = 0;
479 PetscFunctionReturn(PETSC_SUCCESS);
480}

◆ MomentumPreconditionerEngine_ApplyConstraintRows()

static PetscErrorCode MomentumPreconditionerEngine_ApplyConstraintRows ( UserCtx user,
Mat  preconditioning_matrix 
)
static

Inserts all common fixed, homogeneous, and periodic-duplicate rows.

Definition at line 553 of file momentum_newton_krylov.c.

555{
556 DMDALocalInfo info = user->info;
557
558 PetscFunctionBeginUser;
559 for (PetscInt k = info.zs; k < info.zs + info.zm; ++k) {
560 for (PetscInt j = info.ys; j < info.ys + info.ym; ++j) {
561 for (PetscInt i = info.xs; i < info.xs + info.xm; ++i) {
562 for (PetscInt component = 0; component < 3; ++component) {
563 PetscInt ri, rj, rk;
565 user, i, j, k, component, &ri, &rj, &rk);
566 if (type != MOM_NK_ROW_PHYSICAL) {
567 MatStencil row = {.i = i, .j = j, .k = k, .c = component};
568 MatStencil columns[2] = {row, row};
569 PetscScalar values[2] = {1.0, -1.0};
570 PetscInt column_count = 1;
571 if (type == MOM_NK_ROW_PERIODIC_DUPLICATE) {
572 columns[column_count++] = (MatStencil){
573 .i = ri, .j = rj, .k = rk, .c = component
574 };
575 }
576 PetscCall(MatSetValuesStencil(preconditioning_matrix, 1, &row,
577 column_count, columns, values,
578 INSERT_VALUES));
579 }
580 }
581 }
582 }
583 }
584 PetscFunctionReturn(PETSC_SUCCESS);
585}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MomentumNewtonJacobian_Create()

static PetscErrorCode MomentumNewtonJacobian_Create ( SNES  snes,
MomentumNewtonJacobian jacobian 
)
static

Creates the selected Jacobian operator; currently PETSc MFFD only.

Definition at line 595 of file momentum_newton_krylov.c.

597{
598 PetscFunctionBeginUser;
599 PetscCheck(jacobian->type == MOM_NK_JACOBIAN_FINITE_DIFFERENCE &&
601 PETSC_COMM_WORLD, PETSC_ERR_SUP,
602 "Unsupported Newton Krylov Jacobian type/finite-difference-mode combination.");
603 PetscCall(MatCreateSNESMF(snes, &jacobian->jacobian_operator));
604 PetscCall(MatSetOptionsPrefix(jacobian->jacobian_operator, "mom_nk_"));
605 PetscCall(PetscObjectSetName((PetscObject)jacobian->jacobian_operator,
606 "momentum_jacobian_finite_difference_matrix_free"));
607 PetscFunctionReturn(PETSC_SUCCESS);
608}
Here is the caller graph for this function:

◆ MomentumNewtonJacobian_Update()

static PetscErrorCode MomentumNewtonJacobian_Update ( SNES  snes,
Vec  current_solution,
MomentumNewtonJacobian jacobian 
)
static

Updates the matrix-free finite-difference operator base.

Definition at line 611 of file momentum_newton_krylov.c.

613{
614 PetscFunctionBeginUser;
615 PetscCall(MatMFFDComputeJacobian(snes, current_solution, jacobian->jacobian_operator,
616 jacobian->jacobian_operator, NULL));
617 PetscFunctionReturn(PETSC_SUCCESS);
618}
Here is the caller graph for this function:

◆ MomentumNewtonJacobian_Register()

static PetscErrorCode MomentumNewtonJacobian_Register ( SNES  snes,
MomentumNewtonJacobian jacobian,
MomentumPreconditionerEngine engine,
MomentumNewtonKrylovContext ctx 
)
static

Registers the application orchestration callback and both SNES matrices.

Definition at line 621 of file momentum_newton_krylov.c.

624{
625 PetscFunctionBeginUser;
626 PetscCall(SNESSetJacobian(snes, jacobian->jacobian_operator,
629 PetscFunctionReturn(PETSC_SUCCESS);
630}
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.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MomentumNewtonJacobian_Destroy()

static PetscErrorCode MomentumNewtonJacobian_Destroy ( MomentumNewtonJacobian jacobian)
static

Destroys a partially or fully created Jacobian operator.

Definition at line 633 of file momentum_newton_krylov.c.

634{
635 PetscFunctionBeginUser;
636 PetscCall(MatDestroy(&jacobian->jacobian_operator));
637 PetscFunctionReturn(PETSC_SUCCESS);
638}
Here is the caller graph for this function:

◆ MomentumPreconditionerEngine_Create()

static PetscErrorCode MomentumPreconditionerEngine_Create ( UserCtx user,
Mat  jacobian_operator,
const MomentumPreconditionerDescription requested,
MomentumPreconditionerEngine engine 
)
static

Validates a model/structure and creates or aliases its matrix.

Definition at line 643 of file momentum_newton_krylov.c.

646{
647 PetscFunctionBeginUser;
648 engine->description = *requested;
649 if (requested->model == MOM_NK_PC_MODEL_NONE &&
650 requested->structure == MOM_NK_PC_STRUCTURE_NONE) {
651 engine->description.block_size = 0;
652 engine->description.stencil_width = 0;
653 engine->preconditioning_matrix = jacobian_operator;
654 engine->aliases_jacobian_operator = PETSC_TRUE;
655 engine->owns_preconditioning_matrix = PETSC_FALSE;
656 engine->petsc_pc_type = PCNONE;
657 } else if (requested->model == MOM_NK_PC_MODEL_FROZEN_MOMENTUM_JACOBIAN &&
660 PetscCall(engine->model_ops->Describe(user, &engine->description));
662 user, &engine->preconditioning_matrix));
663 engine->owns_preconditioning_matrix = PETSC_TRUE;
664 PetscCall(PetscObjectSetName((PetscObject)engine->preconditioning_matrix,
665 "momentum_preconditioner_frozen_point_block"));
666 engine->aliases_jacobian_operator = PETSC_FALSE;
667 engine->petsc_pc_type = PCPBJACOBI;
668 } else {
669 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP,
670 "Unsupported Newton Krylov preconditioner model/structure combination.");
671 }
672 PetscFunctionReturn(PETSC_SUCCESS);
673}
static const MomentumPreconditionerModelOps frozen_momentum_point_block_ops
const MomentumPreconditionerModelOps * model_ops
static PetscErrorCode MomentumPreconditionerEngine_CreateExactPointBlockMatrix(UserCtx *user, Mat *preconditioning_matrix)
Creates the frozen point-block P matrix with its exact scalar pattern.
PetscErrorCode(* Describe)(UserCtx *, MomentumPreconditionerDescription *)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MomentumPreconditionerEngine_Assemble()

static PetscErrorCode MomentumPreconditionerEngine_Assemble ( MomentumPreconditionerEngine engine,
UserCtx user,
Vec  current_solution 
)
static

Runs model insertion, common row handling, and final assembly.

Definition at line 678 of file momentum_newton_krylov.c.

680{
681 PetscFunctionBeginUser;
682 if (engine->aliases_jacobian_operator) PetscFunctionReturn(PETSC_SUCCESS);
683 PetscCall(MatZeroEntries(engine->preconditioning_matrix));
684 PetscCall(engine->model_ops->AssembleInterior(user, current_solution,
685 engine->preconditioning_matrix));
687 user, engine->preconditioning_matrix));
688 PetscCall(MatAssemblyBegin(engine->preconditioning_matrix, MAT_FINAL_ASSEMBLY));
689 PetscCall(MatAssemblyEnd(engine->preconditioning_matrix, MAT_FINAL_ASSEMBLY));
690 PetscFunctionReturn(PETSC_SUCCESS);
691}
static PetscErrorCode MomentumPreconditionerEngine_ApplyConstraintRows(UserCtx *user, Mat preconditioning_matrix)
Inserts all common fixed, homogeneous, and periodic-duplicate rows.
PetscErrorCode(* AssembleInterior)(UserCtx *, Vec, Mat)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MomentumPreconditionerEngine_ConfigurePetscPC()

static PetscErrorCode MomentumPreconditionerEngine_ConfigurePetscPC ( MomentumPreconditionerEngine engine,
PC  pc 
)
static

Applies the validated model/structure-to-PETSc-PC mapping.

Definition at line 694 of file momentum_newton_krylov.c.

696{
697 PetscFunctionBeginUser;
698 PetscCall(PCSetType(pc, engine->petsc_pc_type));
699 PetscFunctionReturn(PETSC_SUCCESS);
700}
Here is the caller graph for this function:

◆ MomentumPreconditionerEngine_ValidatePetscPC()

static PetscErrorCode MomentumPreconditionerEngine_ValidatePetscPC ( MomentumPreconditionerEngine engine,
PC  pc 
)
static

Rejects raw options that select an unvalidated PETSc PC backend.

Definition at line 703 of file momentum_newton_krylov.c.

705{
706 const char *actual_type = NULL;
707 PetscBool matches = PETSC_FALSE;
708
709 PetscFunctionBeginUser;
710 PetscCall(PCGetType(pc, &actual_type));
711 PetscCall(PetscStrcmp(actual_type, engine->petsc_pc_type, &matches));
712 PetscCheck(matches, PETSC_COMM_WORLD, PETSC_ERR_SUP,
713 "Newton Krylov preconditioner model/structure requires internal PETSc PC "
714 "type '%s', but raw option processing selected '%s'.",
715 engine->petsc_pc_type, actual_type ? actual_type : "(unset)");
716 PetscFunctionReturn(PETSC_SUCCESS);
717}
Here is the caller graph for this function:

◆ MomentumPreconditionerEngine_Destroy()

static PetscErrorCode MomentumPreconditionerEngine_Destroy ( MomentumPreconditionerEngine engine)
static

Destroys only a separately owned preconditioning matrix.

Definition at line 720 of file momentum_newton_krylov.c.

722{
723 PetscFunctionBeginUser;
724 if (!engine->owns_preconditioning_matrix) engine->preconditioning_matrix = NULL;
725 PetscCall(MatDestroy(&engine->preconditioning_matrix));
726 engine->aliases_jacobian_operator = PETSC_FALSE;
727 engine->owns_preconditioning_matrix = PETSC_FALSE;
728 PetscFunctionReturn(PETSC_SUCCESS);
729}
Here is the caller graph for this function:

◆ MomentumSolver_NewtonKrylov()

PetscErrorCode MomentumSolver_NewtonKrylov ( UserCtx user,
IBMNodes ibm,
FSInfo fsi 
)

Solves one physical momentum step with matrix-free Newton–Krylov.

The Jacobian operator is the finite-difference, matrix-free operator of the complete deterministic residual. With no mathematical preconditioner its matrix is also passed to PETSc's preconditioning slot and PCNONE is derived. The optional provisional frozen-momentum, point-block model approximates same-cell frozen coupling, owns a separate matrix, and derives a block-Jacobi PETSc backend. It does not relax the version-one physics or boundary-condition restrictions. All PETSc solver objects are local to this call. Rows removed by legacy boundary residual enforcement are made explicit: conditioned normal rows use X-Uconditioned, untouched dummy/tangential rows use X, and periodic duplicates use Xdup-Xrepresentative. Unsupported masked, interface, and component-disabled rows are rejected before setup.

Parameters
userSingle-block momentum context.
ibmMust be NULL; immersed boundaries are not supported in version one.
fsiMust be NULL; moving-body coupling is not supported in version one.
Returns
0 on convergence, PETSC_ERR_CONV_FAILED after rollback on nonconvergence.

Definition at line 1131 of file momentum_newton_krylov.c.

1132{
1133 PetscErrorCode ierr = PETSC_SUCCESS, cleanup_ierr;
1134 SimCtx *simCtx;
1135 SNES snes = NULL;
1136 Vec solution = NULL, entry_backup = NULL;
1137 KSP ksp = NULL;
1138 PC pc = NULL;
1139 MomentumPreconditionerDescription preconditioner_description = {0};
1140 PetscBool restore_entry = PETSC_FALSE;
1141 PetscBool rhs_created = PETSC_FALSE;
1142 PetscBool solve_started = PETSC_FALSE;
1143 PetscBool committed = PETSC_FALSE;
1144 SNESConvergedReason reason = SNES_CONVERGED_ITERATING;
1145 PetscInt nonlinear_its = 0, function_evals = 0, linear_its = 0;
1146 PetscReal final_norm = PETSC_MAX_REAL;
1148 const FieldId staggered_fields[] = {FIELD_ID_UCONT};
1149
1150 PetscFunctionBeginUser;
1151 PetscCall(MomentumNewtonKrylov_Validate(user));
1152 PetscCheck(ibm == NULL && fsi == NULL, PETSC_COMM_WORLD, PETSC_ERR_SUP,
1153 "Newton Krylov version one does not accept IBM or FSI objects.");
1154 PetscCheck(user->Rhs == NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
1155 "Newton Krylov requires UserCtx::Rhs to be unallocated on entry.");
1156 simCtx = user->simCtx;
1157
1158 ierr = VecDuplicate(user->Ucont, &solution); if (ierr) goto cleanup;
1159 ierr = VecDuplicate(user->Ucont, &entry_backup); if (ierr) goto cleanup;
1160 ierr = VecDuplicate(user->Ucont, &user->Rhs); if (ierr) goto cleanup;
1161 rhs_created = PETSC_TRUE;
1162 ierr = SNESCreate(PetscObjectComm((PetscObject)user->Ucont), &snes); if (ierr) goto cleanup;
1163
1164 ierr = SynchronizePeriodicStaggeredFields(user, 1, staggered_fields); if (ierr) goto cleanup;
1165 ierr = ApplyBoundaryConditions(user); if (ierr) goto cleanup;
1166 ierr = VecCopy(user->Ucont, entry_backup); if (ierr) goto cleanup;
1167 restore_entry = PETSC_TRUE;
1168 ierr = VecCopy(user->Ucont, solution); if (ierr) goto cleanup;
1169
1170 ctx.user = user;
1172 &ctx.jacobian, &preconditioner_description); if (ierr) goto cleanup;
1173 ierr = SNESSetOptionsPrefix(snes, "mom_nk_"); if (ierr) goto cleanup;
1174 ierr = SNESSetType(snes, SNESNEWTONLS); if (ierr) goto cleanup;
1175 ierr = SNESSetDM(snes, user->fda); if (ierr) goto cleanup;
1176 ierr = SNESSetFunction(snes, NULL, MomentumNewtonKrylov_FormResidual, &ctx); if (ierr) goto cleanup;
1177 ierr = MomentumNewtonJacobian_Create(snes, &ctx.jacobian); if (ierr) goto cleanup;
1179 &preconditioner_description,
1180 &ctx.preconditioning_engine); if (ierr) goto cleanup;
1181 ierr = MomentumNewtonJacobian_Register(snes, &ctx.jacobian,
1182 &ctx.preconditioning_engine, &ctx); if (ierr) goto cleanup;
1183 ierr = SNESGetKSP(snes, &ksp); if (ierr) goto cleanup;
1184 ierr = KSPSetType(ksp, KSPGMRES); if (ierr) goto cleanup;
1185 ierr = KSPGetPC(ksp, &pc); if (ierr) goto cleanup;
1186 ierr = MomentumPreconditionerEngine_ConfigurePetscPC(&ctx.preconditioning_engine, pc); if (ierr) goto cleanup;
1187 ierr = SNESSetFromOptions(snes); if (ierr) goto cleanup;
1188 ierr = SNESMonitorSet(snes, MomentumNewtonKrylov_Monitor, &ctx, NULL); if (ierr) goto cleanup;
1189 ierr = MomentumPreconditionerEngine_ValidatePetscPC(&ctx.preconditioning_engine, pc); if (ierr) goto cleanup;
1190
1192 "Newton Krylov Jacobian: finite_difference / matrix_free; "
1193 "Preconditioner: %s; PETSc Jacobian matrix type: MATMFFD; "
1194 "PETSc PC type: %s.\n",
1196 "none" : "frozen_momentum_jacobian / point_block",
1197 ctx.preconditioning_engine.petsc_pc_type);
1198
1200 solve_started = PETSC_TRUE;
1201 ierr = SNESSolve(snes, NULL, solution);
1202 if (ierr) goto cleanup;
1203 ierr = SNESGetConvergedReason(snes, &reason); if (ierr) goto cleanup;
1204 ierr = SNESGetIterationNumber(snes, &nonlinear_its); if (ierr) goto cleanup;
1205 ierr = SNESGetNumberFunctionEvals(snes, &function_evals); if (ierr) goto cleanup;
1206 ierr = SNESGetLinearSolveIterations(snes, &linear_its); if (ierr) goto cleanup;
1207 ierr = SNESGetFunctionNorm(snes, &final_norm); if (ierr) goto cleanup;
1208
1209 if (reason > 0) {
1210 ierr = VecCopy(solution, user->Ucont); if (ierr) goto cleanup;
1211 simCtx->mom_last_converged = PETSC_TRUE;
1212 } else {
1213 ierr = VecCopy(entry_backup, user->Ucont); if (ierr) goto cleanup;
1214 simCtx->mom_last_converged = PETSC_FALSE;
1215 }
1216 ierr = SynchronizePeriodicStaggeredFields(user, 1, staggered_fields); if (ierr) goto cleanup;
1217 ierr = ApplyBoundaryConditions(user); if (ierr) goto cleanup;
1218 restore_entry = PETSC_FALSE;
1219 committed = (PetscBool)(reason > 0);
1220
1222 "Newton Krylov momentum solve: reason=%s (%d), Newton iterations=%d, residual evaluations=%d, Krylov iterations=%d, final norm=%.6e, state=%s.\n",
1223 SNESConvergedReasons[reason], (PetscInt)reason, nonlinear_its, function_evals,
1224 linear_its, (double)final_norm, reason > 0 ? "committed" : "rolled back");
1225 if (reason <= 0) ierr = PETSC_ERR_CONV_FAILED;
1226
1227cleanup:
1228 /* A PETSc solve error can bypass the normal statistics path. Query whatever
1229 SNES retained without replacing the primary error so a failed attempt is
1230 still represented in the structured log. */
1231 if (solve_started && snes) {
1232 (void)SNESGetConvergedReason(snes, &reason);
1233 (void)SNESGetIterationNumber(snes, &nonlinear_its);
1234 (void)SNESGetNumberFunctionEvals(snes, &function_evals);
1235 (void)SNESGetLinearSolveIterations(snes, &linear_its);
1236 (void)SNESGetFunctionNorm(snes, &final_norm);
1237 }
1238 if (restore_entry && entry_backup) {
1239 cleanup_ierr = VecCopy(entry_backup, user->Ucont);
1240 if (!ierr) ierr = cleanup_ierr;
1241 cleanup_ierr = SynchronizePeriodicStaggeredFields(user, 1, staggered_fields);
1242 if (!ierr) ierr = cleanup_ierr;
1243 cleanup_ierr = ApplyBoundaryConditions(user);
1244 if (!ierr) ierr = cleanup_ierr;
1245 simCtx->mom_last_converged = PETSC_FALSE;
1246 committed = PETSC_FALSE;
1247 }
1248 if (ctx.history_file) {
1249 (void)fclose(ctx.history_file);
1250 ctx.history_file = NULL;
1251 }
1252 if (solve_started) {
1253 MomentumNewtonKrylov_WriteSummary(&ctx, reason, nonlinear_its, function_evals,
1254 linear_its, final_norm, committed);
1255 }
1256 if (rhs_created) {
1257 cleanup_ierr = VecDestroy(&user->Rhs);
1258 if (!ierr) ierr = cleanup_ierr;
1259 }
1260 cleanup_ierr = VecDestroy(&entry_backup); if (!ierr) ierr = cleanup_ierr;
1261 cleanup_ierr = VecDestroy(&solution); if (!ierr) ierr = cleanup_ierr;
1262 cleanup_ierr = MomentumPreconditionerEngine_Destroy(&ctx.preconditioning_engine); if (!ierr) ierr = cleanup_ierr;
1263 cleanup_ierr = MomentumNewtonJacobian_Destroy(&ctx.jacobian); if (!ierr) ierr = cleanup_ierr;
1264 cleanup_ierr = SNESDestroy(&snes); if (!ierr) ierr = cleanup_ierr;
1265 PetscFunctionReturn(ierr);
1266}
#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:199
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:30
static PetscErrorCode MomentumNewtonJacobian_Register(SNES snes, MomentumNewtonJacobian *jacobian, MomentumPreconditionerEngine *engine, MomentumNewtonKrylovContext *ctx)
Registers the application orchestration callback and both SNES matrices.
static PetscErrorCode MomentumPreconditionerEngine_ConfigurePetscPC(MomentumPreconditionerEngine *engine, PC pc)
Applies the validated model/structure-to-PETSc-PC mapping.
static PetscErrorCode MomentumPreconditionerEngine_ValidatePetscPC(MomentumPreconditionerEngine *engine, PC pc)
Rejects raw options that select an unvalidated PETSc PC backend.
static PetscErrorCode MomentumPreconditionerEngine_Create(UserCtx *user, Mat jacobian_operator, const MomentumPreconditionerDescription *requested, MomentumPreconditionerEngine *engine)
Validates a model/structure and creates or aliases its matrix.
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.
static PetscErrorCode MomentumNewtonKrylov_ReadLinearizationConfig(MomentumNewtonJacobian *jacobian, MomentumPreconditionerDescription *description)
Reads application-owned Jacobian and preconditioner mathematics.
static PetscErrorCode MomentumNewtonJacobian_Destroy(MomentumNewtonJacobian *jacobian)
Destroys a partially or fully created Jacobian operator.
static void MomentumNewtonKrylov_OpenHistory(MomentumNewtonKrylovContext *ctx)
Opens the optional rank-zero Newton iteration-history file.
static PetscErrorCode MomentumNewtonJacobian_Create(SNES snes, MomentumNewtonJacobian *jacobian)
Creates the selected Jacobian operator; currently PETSc MFFD only.
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.
static PetscErrorCode MomentumNewtonKrylov_FormResidual(SNES snes, Vec X, Vec F, void *ctx)
Adapts a PETSc trial vector to the existing momentum residual path.
static PetscErrorCode MomentumNewtonKrylov_Monitor(SNES snes, PetscInt iteration, PetscReal norm, void *ctx)
Captures SNES iteration norms and optionally writes PICurv history rows.
PetscBool mom_last_converged
Definition variables.h:738
Here is the call graph for this function:

Variable Documentation

◆ frozen_momentum_point_block_ops

const MomentumPreconditionerModelOps frozen_momentum_point_block_ops
static
Initial value:
= {
}
static PetscErrorCode FrozenMomentumJacobian_DescribePointBlock(UserCtx *user, MomentumPreconditionerDescription *description)
Describes the audited frozen-coefficient point-block model.
static PetscErrorCode FrozenMomentumJacobian_AssemblePointBlocks(UserCtx *user, Vec current_solution, Mat preconditioning_matrix)
Inserts only the audited interior frozen-momentum point blocks.

Definition at line 587 of file momentum_newton_krylov.c.