Runs one per-call matrix-free Newton–Krylov momentum solve.
Solves one physical momentum step with matrix-free Newton–Krylov.
287{
288 PetscErrorCode ierr = PETSC_SUCCESS, cleanup_ierr;
290 SNES snes = NULL;
291 Mat J = NULL;
292 Vec solution = NULL, entry_backup = NULL;
293 KSP ksp = NULL;
294 PC pc = NULL;
295 const char *pc_type = NULL;
296 PetscBool pc_is_none = PETSC_FALSE;
297 PetscBool restore_entry = PETSC_FALSE;
298 PetscBool rhs_created = PETSC_FALSE;
299 SNESConvergedReason reason = SNES_CONVERGED_ITERATING;
300 PetscInt nonlinear_its = 0, function_evals = 0, linear_its = 0;
301 PetscReal final_norm = PETSC_MAX_REAL;
303 const char *staggered_fields[] = {"Ucont"};
304
305 PetscFunctionBeginUser;
307 PetscCheck(ibm == NULL && fsi == NULL, PETSC_COMM_WORLD, PETSC_ERR_SUP,
308 "Newton Krylov version one does not accept IBM or FSI objects.");
309 PetscCheck(user->
Rhs == NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
310 "Newton Krylov requires UserCtx::Rhs to be unallocated on entry.");
312
313 ierr = VecDuplicate(user->
Ucont, &solution);
if (ierr)
goto cleanup;
314 ierr = VecDuplicate(user->
Ucont, &entry_backup);
if (ierr)
goto cleanup;
315 ierr = VecDuplicate(user->
Ucont, &user->
Rhs);
if (ierr)
goto cleanup;
316 rhs_created = PETSC_TRUE;
317 ierr = SNESCreate(PetscObjectComm((PetscObject)user->
Ucont), &snes);
if (ierr)
goto cleanup;
318
321 ierr = VecCopy(user->
Ucont, entry_backup);
if (ierr)
goto cleanup;
322 restore_entry = PETSC_TRUE;
323 ierr = VecCopy(user->
Ucont, solution);
if (ierr)
goto cleanup;
324
326 ierr = SNESSetOptionsPrefix(snes, "mom_nk_"); if (ierr) goto cleanup;
327 ierr = SNESSetType(snes, SNESNEWTONLS); if (ierr) goto cleanup;
328 ierr = SNESSetDM(snes, user->
fda);
if (ierr)
goto cleanup;
330 ierr = MatCreateSNESMF(snes, &J); if (ierr) goto cleanup;
331 ierr = SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL); if (ierr) goto cleanup;
332 ierr = SNESGetKSP(snes, &ksp); if (ierr) goto cleanup;
333 ierr = KSPSetType(ksp, KSPGMRES); if (ierr) goto cleanup;
334 ierr = KSPGetPC(ksp, &pc); if (ierr) goto cleanup;
335 ierr = PCSetType(pc, PCNONE); if (ierr) goto cleanup;
336 ierr = SNESSetFromOptions(snes); if (ierr) goto cleanup;
337 ierr = PCGetType(pc, &pc_type); if (ierr) goto cleanup;
338 ierr = PetscStrcmp(pc_type, PCNONE, &pc_is_none); if (ierr) goto cleanup;
339 if (!pc_is_none) {
341 "Newton Krylov version one requires PCNONE; option processing selected PC type '%s'.\n",
342 pc_type ? pc_type : "(unset)");
343 ierr = PETSC_ERR_SUP;
344 goto cleanup;
345 }
346
347 ierr = SNESSolve(snes, NULL, solution);
348 if (ierr) goto cleanup;
349 ierr = SNESGetConvergedReason(snes, &reason); if (ierr) goto cleanup;
350 ierr = SNESGetIterationNumber(snes, &nonlinear_its); if (ierr) goto cleanup;
351 ierr = SNESGetNumberFunctionEvals(snes, &function_evals); if (ierr) goto cleanup;
352 ierr = SNESGetLinearSolveIterations(snes, &linear_its); if (ierr) goto cleanup;
353 ierr = SNESGetFunctionNorm(snes, &final_norm); if (ierr) goto cleanup;
354
355 if (reason > 0) {
356 ierr = VecCopy(solution, user->
Ucont);
if (ierr)
goto cleanup;
358 } else {
359 ierr = VecCopy(entry_backup, user->
Ucont);
if (ierr)
goto cleanup;
361 }
364 restore_entry = PETSC_FALSE;
365
367 "Newton Krylov momentum solve: reason=%s (%d), Newton iterations=%d, residual evaluations=%d, Krylov iterations=%d, final norm=%.6e, state=%s.\n",
368 SNESConvergedReasons[reason], (PetscInt)reason, nonlinear_its, function_evals,
369 linear_its, (double)final_norm, reason > 0 ? "committed" : "rolled back");
370 if (reason <= 0) ierr = PETSC_ERR_CONV_FAILED;
371
372cleanup:
373 if (restore_entry && entry_backup) {
374 cleanup_ierr = VecCopy(entry_backup, user->
Ucont);
375 if (!ierr) ierr = cleanup_ierr;
377 if (!ierr) ierr = cleanup_ierr;
379 if (!ierr) ierr = cleanup_ierr;
381 }
382 if (rhs_created) {
383 cleanup_ierr = VecDestroy(&user->
Rhs);
384 if (!ierr) ierr = cleanup_ierr;
385 }
386 cleanup_ierr = VecDestroy(&entry_backup); if (!ierr) ierr = cleanup_ierr;
387 cleanup_ierr = VecDestroy(&solution); if (!ierr) ierr = cleanup_ierr;
388 cleanup_ierr = MatDestroy(&J); if (!ierr) ierr = cleanup_ierr;
389 cleanup_ierr = SNESDestroy(&snes); if (!ierr) ierr = cleanup_ierr;
390 PetscFunctionReturn(ierr);
391}
#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_ERROR
Critical errors that may halt the program.
@ LOG_INFO
Informational messages about program execution.
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 *ctx)
Adapts a PETSc trial vector to the existing momentum residual path.
PetscBool mom_last_converged