1 #pragma once 2 3 #include <petscksp.h> 4 #include <petscds.h> 5 #include <petsc/private/petscimpl.h> 6 7 /* SUBMANSEC = KSP */ 8 9 PETSC_EXTERN PetscBool KSPRegisterAllCalled; 10 PETSC_EXTERN PetscBool KSPMonitorRegisterAllCalled; 11 PETSC_EXTERN PetscErrorCode KSPRegisterAll(void); 12 PETSC_EXTERN PetscErrorCode KSPMonitorRegisterAll(void); 13 PETSC_EXTERN PetscErrorCode KSPGuessRegisterAll(void); 14 PETSC_EXTERN PetscErrorCode KSPMatRegisterAll(void); 15 16 typedef struct _KSPOps *KSPOps; 17 18 struct _KSPOps { 19 PetscErrorCode (*buildsolution)(KSP, Vec, Vec *); /* Returns a pointer to the solution, or 20 calculates the solution in a 21 user-provided area. */ 22 PetscErrorCode (*buildresidual)(KSP, Vec, Vec, Vec *); /* Returns a pointer to the residual, or 23 calculates the residual in a 24 user-provided area. */ 25 PetscErrorCode (*solve)(KSP); /* actual solver */ 26 PetscErrorCode (*matsolve)(KSP, Mat, Mat); /* multiple dense RHS solver */ 27 PetscErrorCode (*setup)(KSP); 28 PetscErrorCode (*setfromoptions)(KSP, PetscOptionItems *); 29 PetscErrorCode (*publishoptions)(KSP); 30 PetscErrorCode (*computeextremesingularvalues)(KSP, PetscReal *, PetscReal *); 31 PetscErrorCode (*computeeigenvalues)(KSP, PetscInt, PetscReal *, PetscReal *, PetscInt *); 32 PetscErrorCode (*computeritz)(KSP, PetscBool, PetscBool, PetscInt *, Vec[], PetscReal *, PetscReal *); 33 PetscErrorCode (*destroy)(KSP); 34 PetscErrorCode (*view)(KSP, PetscViewer); 35 PetscErrorCode (*reset)(KSP); 36 PetscErrorCode (*load)(KSP, PetscViewer); 37 }; 38 39 typedef struct _KSPGuessOps *KSPGuessOps; 40 41 struct _KSPGuessOps { 42 PetscErrorCode (*formguess)(KSPGuess, Vec, Vec); /* Form initial guess */ 43 PetscErrorCode (*update)(KSPGuess, Vec, Vec); /* Update database */ 44 PetscErrorCode (*setfromoptions)(KSPGuess); 45 PetscErrorCode (*settolerance)(KSPGuess, PetscReal); 46 PetscErrorCode (*setup)(KSPGuess); 47 PetscErrorCode (*destroy)(KSPGuess); 48 PetscErrorCode (*view)(KSPGuess, PetscViewer); 49 PetscErrorCode (*reset)(KSPGuess); 50 }; 51 52 /* 53 Defines the KSPGuess data structure. 54 */ 55 struct _p_KSPGuess { 56 PETSCHEADER(struct _KSPGuessOps); 57 KSP ksp; /* the parent KSP */ 58 Mat A; /* the current linear operator */ 59 PetscObjectState omatstate; /* previous linear operator state */ 60 void *data; /* pointer to the specific implementation */ 61 }; 62 63 PETSC_EXTERN PetscErrorCode KSPGuessCreate_Fischer(KSPGuess); 64 PETSC_EXTERN PetscErrorCode KSPGuessCreate_POD(KSPGuess); 65 66 /* 67 Maximum number of monitors you can run with a single KSP 68 */ 69 #define MAXKSPMONITORS 5 70 #define MAXKSPREASONVIEWS 5 71 typedef enum { 72 KSP_SETUP_NEW = 0, 73 KSP_SETUP_NEWMATRIX, 74 KSP_SETUP_NEWRHS 75 } KSPSetUpStage; 76 77 /* 78 Defines the KSP data structure. 79 */ 80 struct _p_KSP { 81 PETSCHEADER(struct _KSPOps); 82 DM dm; 83 PetscBool dmAuto; /* DM was created automatically by KSP */ 84 PetscBool dmActive; /* KSP should use DM for computing operators */ 85 /*------------------------- User parameters--------------------------*/ 86 PetscObjectParameterDeclare(PetscInt, max_it); /* maximum number of iterations */ 87 PetscInt min_it; /* minimum number of iterations */ 88 KSPGuess guess; 89 PetscBool guess_zero, /* flag for whether initial guess is 0 */ 90 guess_not_read, /* guess is not read, does not need to be zeroed */ 91 calc_sings, /* calculate extreme Singular Values */ 92 calc_ritz, /* calculate (harmonic) Ritz pairs */ 93 guess_knoll; /* use initial guess of PCApply(ksp->B,b */ 94 PCSide pc_side; /* flag for left, right, or symmetric preconditioning */ 95 PetscInt normsupporttable[KSP_NORM_MAX][PC_SIDE_MAX]; /* Table of supported norms and pc_side, see KSPSetSupportedNorm() */ 96 PetscObjectParameterDeclare(PetscReal, rtol); /* relative tolerance */ 97 PetscObjectParameterDeclare(PetscReal, abstol); /* absolute tolerance */ 98 PetscObjectParameterDeclare(PetscReal, ttol); /* (not set by user) */ 99 PetscObjectParameterDeclare(PetscReal, divtol); /* divergence tolerance */ 100 PetscReal rnorm0; /* initial residual norm (used for divergence testing) */ 101 PetscReal rnorm; /* current residual norm */ 102 KSPConvergedReason reason; 103 PetscBool errorifnotconverged; /* create an error if the KSPSolve() does not converge */ 104 105 Vec vec_sol, vec_rhs; /* pointer to where user has stashed 106 the solution and rhs, these are 107 never touched by the code, only 108 passed back to the user */ 109 PetscReal *res_hist; /* If !0 stores residual each at iteration */ 110 PetscReal *res_hist_alloc; /* If !0 means user did not provide buffer, needs deallocation */ 111 size_t res_hist_len; /* current size of residual history array */ 112 size_t res_hist_max; /* actual amount of storage in residual history */ 113 PetscBool res_hist_reset; /* reset history to length zero for each new solve */ 114 PetscReal *err_hist; /* If !0 stores error at each iteration */ 115 PetscReal *err_hist_alloc; /* If !0 means user did not provide buffer, needs deallocation */ 116 size_t err_hist_len; /* current size of error history array */ 117 size_t err_hist_max; /* actual amount of storage in error history */ 118 PetscBool err_hist_reset; /* reset history to length zero for each new solve */ 119 120 PetscInt chknorm; /* only compute/check norm if iterations is great than this */ 121 PetscBool lagnorm; /* Lag the residual norm calculation so that it is computed as part of the 122 MPI_Allreduce() for computing the inner products for the next iteration. */ 123 124 PetscInt nmax; /* maximum number of right-hand sides to be handled simultaneously */ 125 126 /* --------User (or default) routines (most return -1 on error) --------*/ 127 PetscErrorCode (*monitor[MAXKSPMONITORS])(KSP, PetscInt, PetscReal, void *); /* returns control to user after */ 128 PetscErrorCode (*monitordestroy[MAXKSPMONITORS])(void **); /* */ 129 void *monitorcontext[MAXKSPMONITORS]; /* residual calculation, allows user */ 130 PetscInt numbermonitors; /* to, for instance, print residual norm, etc. */ 131 PetscBool pauseFinal; /* Pause all drawing monitor at the final iterate */ 132 133 PetscViewer convergedreasonviewer; 134 PetscViewerFormat convergedreasonformat; 135 PetscErrorCode (*reasonview[MAXKSPREASONVIEWS])(KSP, void *); /* KSP converged reason view */ 136 PetscErrorCode (*reasonviewdestroy[MAXKSPREASONVIEWS])(void **); /* Optional destroy routine */ 137 void *reasonviewcontext[MAXKSPREASONVIEWS]; /* User context */ 138 PetscInt numberreasonviews; /* Number if reason viewers */ 139 140 PetscErrorCode (*converged)(KSP, PetscInt, PetscReal, KSPConvergedReason *, void *); 141 PetscErrorCode (*convergeddestroy)(void *); 142 void *cnvP; 143 144 void *user; /* optional user-defined context */ 145 146 PC pc; 147 148 void *data; /* holder for misc stuff associated 149 with a particular iterative solver */ 150 151 PetscBool view, viewPre, viewRate, viewMat, viewPMat, viewRhs, viewSol, viewMatExp, viewEV, viewSV, viewEVExp, viewFinalRes, viewPOpExp, viewDScale; 152 PetscViewer viewer, viewerPre, viewerRate, viewerMat, viewerPMat, viewerRhs, viewerSol, viewerMatExp, viewerEV, viewerSV, viewerEVExp, viewerFinalRes, viewerPOpExp, viewerDScale; 153 PetscViewerFormat format, formatPre, formatRate, formatMat, formatPMat, formatRhs, formatSol, formatMatExp, formatEV, formatSV, formatEVExp, formatFinalRes, formatPOpExp, formatDScale; 154 155 /* ----------------Default work-area management -------------------- */ 156 PetscInt nwork; 157 Vec *work; 158 159 KSPSetUpStage setupstage; 160 PetscBool setupnewmatrix; /* true if we need to call ksp->ops->setup with KSP_SETUP_NEWMATRIX */ 161 162 PetscInt its; /* number of iterations so far computed in THIS linear solve*/ 163 PetscInt totalits; /* number of iterations used by this KSP object since it was created */ 164 165 PetscBool transpose_solve; /* solve transpose system instead */ 166 struct { 167 Mat AT, BT; 168 PetscBool use_explicittranspose; /* transpose the system explicitly in KSPSolveTranspose */ 169 PetscBool reuse_transpose; /* reuse the previous transposed system */ 170 } transpose; 171 172 KSPNormType normtype; /* type of norm used for convergence tests */ 173 174 PCSide pc_side_set; /* PC type set explicitly by user */ 175 KSPNormType normtype_set; /* Norm type set explicitly by user */ 176 177 /* Allow diagonally scaling the matrix before computing the preconditioner or using 178 the Krylov method. Note this is NOT just Jacobi preconditioning */ 179 180 PetscBool dscale; /* diagonal scale system; used with KSPSetDiagonalScale() */ 181 PetscBool dscalefix; /* unscale system after solve */ 182 PetscBool dscalefix2; /* system has been unscaled */ 183 Vec diagonal; /* 1/sqrt(diag of matrix) */ 184 Vec truediagonal; 185 186 /* Allow declaring convergence when negative curvature is detected */ 187 PetscBool converged_neg_curve; 188 189 PetscInt setfromoptionscalled; 190 PetscBool skippcsetfromoptions; /* if set then KSPSetFromOptions() does not call PCSetFromOptions() */ 191 192 PetscErrorCode (*presolve)(KSP, Vec, Vec, void *); 193 PetscErrorCode (*postsolve)(KSP, Vec, Vec, void *); 194 void *prectx, *postctx; 195 196 PetscInt nestlevel; /* how many levels of nesting does the KSP have */ 197 }; 198 199 typedef struct { /* dummy data structure used in KSPMonitorDynamicTolerance() */ 200 PetscReal coef; 201 PetscReal bnrm; 202 } KSPDynTolCtx; 203 204 typedef struct { 205 PetscBool initialrtol; /* default relative residual decrease is computed from initial residual, not rhs */ 206 PetscBool mininitialrtol; /* default relative residual decrease is computed from min of initial residual and rhs */ 207 PetscBool convmaxits; /* if true, the convergence test returns KSP_CONVERGED_ITS if the maximum number of iterations is reached */ 208 Vec work; 209 } KSPConvergedDefaultCtx; 210 211 static inline PetscErrorCode KSPLogResidualHistory(KSP ksp, PetscReal norm) 212 { 213 PetscFunctionBegin; 214 PetscCall(PetscObjectSAWsTakeAccess((PetscObject)ksp)); 215 if (ksp->res_hist && ksp->res_hist_max > ksp->res_hist_len) ksp->res_hist[ksp->res_hist_len++] = norm; 216 PetscCall(PetscObjectSAWsGrantAccess((PetscObject)ksp)); 217 PetscFunctionReturn(PETSC_SUCCESS); 218 } 219 220 static inline PetscErrorCode KSPLogErrorHistory(KSP ksp) 221 { 222 DM dm; 223 224 PetscFunctionBegin; 225 PetscCall(PetscObjectSAWsTakeAccess((PetscObject)ksp)); 226 PetscCall(KSPGetDM(ksp, &dm)); 227 if (dm && ksp->err_hist && ksp->err_hist_max > ksp->err_hist_len) { 228 PetscSimplePointFn *exactSol; 229 void *exactCtx; 230 PetscDS ds; 231 Vec u; 232 PetscReal error; 233 PetscInt Nf; 234 235 PetscCall(KSPBuildSolution(ksp, NULL, &u)); 236 /* TODO Was needed to correct for Newton solution, but I just need to set a solution */ 237 //PetscCall(VecScale(u, -1.0)); 238 /* TODO Case when I have a solution */ 239 if (0) { 240 PetscCall(DMGetDS(dm, &ds)); 241 PetscCall(PetscDSGetNumFields(ds, &Nf)); 242 PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle number of fields %" PetscInt_FMT " > 1 right now", Nf); 243 PetscCall(PetscDSGetExactSolution(ds, 0, &exactSol, &exactCtx)); 244 PetscCall(DMComputeL2FieldDiff(dm, 0.0, &exactSol, &exactCtx, u, &error)); 245 } else { 246 /* The null solution A 0 = 0 */ 247 PetscCall(VecNorm(u, NORM_2, &error)); 248 } 249 ksp->err_hist[ksp->err_hist_len++] = error; 250 } 251 PetscCall(PetscObjectSAWsGrantAccess((PetscObject)ksp)); 252 PetscFunctionReturn(PETSC_SUCCESS); 253 } 254 255 static inline PetscScalar KSPNoisyHash_Private(PetscInt xx) 256 { 257 unsigned int x = (unsigned int)xx; 258 x = ((x >> 16) ^ x) * 0x45d9f3b; 259 x = ((x >> 16) ^ x) * 0x45d9f3b; 260 x = ((x >> 16) ^ x); 261 return (PetscScalar)(((PetscInt64)x - 2147483648) * 5.e-10); /* center around zero, scaled about -1. to 1.*/ 262 } 263 264 static inline PetscErrorCode KSPSetNoisy_Private(Vec v) 265 { 266 PetscScalar *a; 267 PetscInt n, istart; 268 269 PetscFunctionBegin; 270 PetscCall(VecGetOwnershipRange(v, &istart, NULL)); 271 PetscCall(VecGetLocalSize(v, &n)); 272 PetscCall(VecGetArrayWrite(v, &a)); 273 for (PetscInt i = 0; i < n; ++i) a[i] = KSPNoisyHash_Private(i + istart); 274 PetscCall(VecRestoreArrayWrite(v, &a)); 275 PetscFunctionReturn(PETSC_SUCCESS); 276 } 277 278 PETSC_INTERN PetscErrorCode KSPSetUpNorms_Private(KSP, PetscBool, KSPNormType *, PCSide *); 279 280 PETSC_INTERN PetscErrorCode KSPPlotEigenContours_Private(KSP, PetscInt, const PetscReal *, const PetscReal *); 281 282 typedef struct _p_DMKSP *DMKSP; 283 typedef struct _DMKSPOps *DMKSPOps; 284 struct _DMKSPOps { 285 KSPComputeOperatorsFn *computeoperators; 286 KSPComputeRHSFn *computerhs; 287 KSPComputeInitialGuessFn *computeinitialguess; 288 PetscErrorCode (*destroy)(DMKSP *); 289 PetscErrorCode (*duplicate)(DMKSP, DMKSP); 290 }; 291 292 /*S 293 DMKSP - Object held by a `DM` that contains all the callback functions and their contexts needed by a `KSP` 294 295 Level: developer 296 297 Notes: 298 Users provides callback functions and their contexts to `KSP` using, for example, `KSPSetComputeRHS()`. These values are stored 299 in a `DMKSP` that is contained in the `DM` associated with the `KSP`. If no `DM` was provided by 300 the user with `KSPSetDM()` it is automatically created by `KSPGetDM()` with `DMShellCreate()`. 301 302 Users very rarely need to worked directly with the `DMKSP` object, rather they work with the `KSP` and the `DM` they created 303 304 Multiple `DM` can share a single `DMKSP`, often each `DM` is associated with 305 a grid refinement level. `DMGetDMKSP()` returns the `DMKSP` associated with a `DM`. `DMGetDMKSPWrite()` returns a unique 306 `DMKSP` that is only associated with the current `DM`, making a copy of the shared `DMKSP` if needed (copy-on-write). 307 308 Developer Notes: 309 It is rather subtle why `DMKSP`, `DMSNES`, and `DMTS` are needed instead of simply storing the user callback functions and contexts in `DM` or `KSP`, `SNES`, or `TS`. 310 It is to support composable solvers such as geometric multigrid. We want, by default, the same callback functions and contexts for all the levels in the computation, 311 but we need to also support different callbacks and contexts on each level. The copy-on-write approach of `DMGetDMKSPWrite()` makes this possible. 312 313 The `originaldm` inside the `DMKSP` is NOT reference counted (to prevent a reference count loop between a `DM` and a `DMKSP`). 314 The `DM` on which this context was first created is cached here to implement one-way 315 copy-on-write. When `DMGetDMKSPWrite()` sees a request using a different `DM`, it makes a copy of the `TSDM`. Thus, if a user 316 only interacts directly with one level, e.g., using `TSSetIFunction()`, then coarse levels of a multilevel item 317 integrator are built, then the user changes the routine with another call to `TSSetIFunction()`, it automatically 318 propagates to all the levels. If instead, they get out a specific level and set the function on that level, 319 subsequent changes to the original level will no longer propagate to that level. 320 321 .seealso: [](ch_ts), `KSP`, `KSPCreate()`, `DM`, `DMGetDMKSPWrite()`, `DMGetDMKSP()`, `DMSNES`, `DMTS`, `DMKSPSetComputeOperators()`, `DMKSPGetComputeOperators()`, 322 `DMKSPSetComputeRHS()`, `DMKSPSetComputeInitialGuess()` 323 S*/ 324 struct _p_DMKSP { 325 PETSCHEADER(struct _DMKSPOps); 326 void *operatorsctx; 327 void *rhsctx; 328 void *initialguessctx; 329 void *data; 330 331 /* See developer note for `DMKSP` above */ 332 DM originaldm; 333 334 void (*fortran_func_pointers[3])(void); /* Store our own function pointers so they are associated with the DMKSP instead of the DM */ 335 }; 336 PETSC_EXTERN PetscErrorCode DMGetDMKSP(DM, DMKSP *); 337 PETSC_EXTERN PetscErrorCode DMGetDMKSPWrite(DM, DMKSP *); 338 PETSC_EXTERN PetscErrorCode DMCopyDMKSP(DM, DM); 339 340 /* 341 These allow the various Krylov methods to apply to either the linear system or its transpose. 342 */ 343 static inline PetscErrorCode KSP_RemoveNullSpace(KSP ksp, Vec y) 344 { 345 PetscFunctionBegin; 346 if (ksp->pc_side == PC_LEFT) { 347 Mat A; 348 MatNullSpace nullsp; 349 350 PetscCall(PCGetOperators(ksp->pc, &A, NULL)); 351 PetscCall(MatGetNullSpace(A, &nullsp)); 352 if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, y)); 353 } 354 PetscFunctionReturn(PETSC_SUCCESS); 355 } 356 357 static inline PetscErrorCode KSP_RemoveNullSpaceTranspose(KSP ksp, Vec y) 358 { 359 PetscFunctionBegin; 360 if (ksp->pc_side == PC_LEFT) { 361 Mat A; 362 MatNullSpace nullsp; 363 364 PetscCall(PCGetOperators(ksp->pc, &A, NULL)); 365 PetscCall(MatGetTransposeNullSpace(A, &nullsp)); 366 if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, y)); 367 } 368 PetscFunctionReturn(PETSC_SUCCESS); 369 } 370 371 static inline PetscErrorCode KSP_MatMult(KSP ksp, Mat A, Vec x, Vec y) 372 { 373 PetscFunctionBegin; 374 if (ksp->transpose_solve) PetscCall(MatMultTranspose(A, x, y)); 375 else PetscCall(MatMult(A, x, y)); 376 PetscFunctionReturn(PETSC_SUCCESS); 377 } 378 379 static inline PetscErrorCode KSP_MatMultTranspose(KSP ksp, Mat A, Vec x, Vec y) 380 { 381 PetscFunctionBegin; 382 if (ksp->transpose_solve) PetscCall(MatMult(A, x, y)); 383 else PetscCall(MatMultTranspose(A, x, y)); 384 PetscFunctionReturn(PETSC_SUCCESS); 385 } 386 387 static inline PetscErrorCode KSP_MatMultHermitianTranspose(KSP ksp, Mat A, Vec x, Vec y) 388 { 389 PetscFunctionBegin; 390 if (!ksp->transpose_solve) PetscCall(MatMultHermitianTranspose(A, x, y)); 391 else { 392 Vec w; 393 394 PetscCall(VecDuplicate(x, &w)); 395 PetscCall(VecCopy(x, w)); 396 PetscCall(VecConjugate(w)); 397 PetscCall(MatMult(A, w, y)); 398 PetscCall(VecDestroy(&w)); 399 PetscCall(VecConjugate(y)); 400 } 401 PetscFunctionReturn(PETSC_SUCCESS); 402 } 403 404 static inline PetscErrorCode KSP_PCApply(KSP ksp, Vec x, Vec y) 405 { 406 PetscFunctionBegin; 407 if (ksp->transpose_solve) { 408 PetscCall(PCApplyTranspose(ksp->pc, x, y)); 409 PetscCall(KSP_RemoveNullSpaceTranspose(ksp, y)); 410 } else { 411 PetscCall(PCApply(ksp->pc, x, y)); 412 PetscCall(KSP_RemoveNullSpace(ksp, y)); 413 } 414 PetscFunctionReturn(PETSC_SUCCESS); 415 } 416 417 static inline PetscErrorCode KSP_PCApplyTranspose(KSP ksp, Vec x, Vec y) 418 { 419 PetscFunctionBegin; 420 if (ksp->transpose_solve) { 421 PetscCall(PCApply(ksp->pc, x, y)); 422 PetscCall(KSP_RemoveNullSpace(ksp, y)); 423 } else { 424 PetscCall(PCApplyTranspose(ksp->pc, x, y)); 425 PetscCall(KSP_RemoveNullSpaceTranspose(ksp, y)); 426 } 427 PetscFunctionReturn(PETSC_SUCCESS); 428 } 429 430 static inline PetscErrorCode KSP_PCApplyHermitianTranspose(KSP ksp, Vec x, Vec y) 431 { 432 PetscFunctionBegin; 433 PetscCall(VecConjugate(x)); 434 PetscCall(KSP_PCApplyTranspose(ksp, x, y)); 435 PetscCall(VecConjugate(x)); 436 PetscCall(VecConjugate(y)); 437 PetscFunctionReturn(PETSC_SUCCESS); 438 } 439 440 static inline PetscErrorCode KSP_PCMatApply(KSP ksp, Mat X, Mat Y) 441 { 442 PetscFunctionBegin; 443 if (ksp->transpose_solve) { 444 PetscBool flg; 445 PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp->pc, &flg, PCNONE, PCICC, PCCHOLESKY, "")); 446 PetscCheck(flg, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "PCMatApplyTranspose() not yet implemented for nonsymmetric PC"); 447 } 448 PetscCall(PCMatApply(ksp->pc, X, Y)); 449 PetscFunctionReturn(PETSC_SUCCESS); 450 } 451 452 static inline PetscErrorCode KSP_PCMatApplyTranspose(KSP ksp, Mat X, Mat Y) 453 { 454 PetscFunctionBegin; 455 if (!ksp->transpose_solve) { 456 PetscBool flg; 457 PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp->pc, &flg, PCNONE, PCICC, PCCHOLESKY, "")); 458 PetscCheck(flg, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "PCMatApplyTranspose() not yet implemented for nonsymmetric PC"); 459 } 460 PetscCall(PCMatApply(ksp->pc, X, Y)); 461 PetscFunctionReturn(PETSC_SUCCESS); 462 } 463 464 static inline PetscErrorCode KSP_PCApplyBAorAB(KSP ksp, Vec x, Vec y, Vec w) 465 { 466 PetscFunctionBegin; 467 if (ksp->transpose_solve) { 468 PetscCall(PCApplyBAorABTranspose(ksp->pc, ksp->pc_side, x, y, w)); 469 PetscCall(KSP_RemoveNullSpaceTranspose(ksp, y)); 470 } else { 471 PetscCall(PCApplyBAorAB(ksp->pc, ksp->pc_side, x, y, w)); 472 PetscCall(KSP_RemoveNullSpace(ksp, y)); 473 } 474 PetscFunctionReturn(PETSC_SUCCESS); 475 } 476 477 static inline PetscErrorCode KSP_PCApplyBAorABTranspose(KSP ksp, Vec x, Vec y, Vec w) 478 { 479 PetscFunctionBegin; 480 if (ksp->transpose_solve) PetscCall(PCApplyBAorAB(ksp->pc, ksp->pc_side, x, y, w)); 481 else PetscCall(PCApplyBAorABTranspose(ksp->pc, ksp->pc_side, x, y, w)); 482 PetscFunctionReturn(PETSC_SUCCESS); 483 } 484 485 PETSC_EXTERN PetscLogEvent KSP_GMRESOrthogonalization; 486 PETSC_EXTERN PetscLogEvent KSP_SetUp; 487 PETSC_EXTERN PetscLogEvent KSP_Solve; 488 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_0; 489 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_1; 490 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_2; 491 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_3; 492 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_4; 493 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_S; 494 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_L; 495 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_U; 496 PETSC_EXTERN PetscLogEvent KSP_SolveTranspose; 497 PETSC_EXTERN PetscLogEvent KSP_MatSolve; 498 PETSC_EXTERN PetscLogEvent KSP_MatSolveTranspose; 499 500 PETSC_INTERN PetscErrorCode MatGetSchurComplement_Basic(Mat, IS, IS, IS, IS, MatReuse, Mat *, MatSchurComplementAinvType, MatReuse, Mat *); 501 PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC, PetscBool *); 502 503 /*MC 504 KSPCheckDot - Checks if the result of a dot product used by the corresponding `KSP` contains Inf or NaN. These indicate that the previous 505 application of the preconditioner generated an error. Sets a `KSPConvergedReason` and returns if the `PC` set a `PCFailedReason`. 506 507 Collective 508 509 Input Parameter: 510 . ksp - the linear solver `KSP` context. 511 512 Output Parameter: 513 . beta - the result of the inner product 514 515 Level: developer 516 517 Developer Notes: 518 Used to manage returning from `KSP` solvers collectively whose preconditioners have failed, possibly only a subset of MPI processes, in some way 519 520 It uses the fact that `KSP` piggy-backs the collectivity of certain error conditions on the results of norms and inner products. 521 522 .seealso: `PCFailedReason`, `KSPConvergedReason`, `PCGetFailedReasonRank()`, `KSP`, `KSPCreate()`, `KSPSetType()`, `KSP`, `KSPCheckNorm()`, `KSPCheckSolve()`, 523 `KSPSetErrorIfNotConverged()` 524 M*/ 525 #define KSPCheckDot(ksp, beta) \ 526 do { \ 527 if (PetscIsInfOrNanScalar(beta)) { \ 528 PetscCheck(!ksp->errorifnotconverged, PetscObjectComm((PetscObject)ksp), PETSC_ERR_NOT_CONVERGED, "KSPSolve has not converged due to Nan or Inf inner product"); \ 529 { \ 530 PCFailedReason pcreason; \ 531 PetscCall(PCReduceFailedReason(ksp->pc)); \ 532 PetscCall(PCGetFailedReasonRank(ksp->pc, &pcreason)); \ 533 PetscCall(VecFlag(ksp->vec_sol, pcreason)); \ 534 if (pcreason) { \ 535 ksp->reason = KSP_DIVERGED_PC_FAILED; \ 536 } else { \ 537 ksp->reason = KSP_DIVERGED_NANORINF; \ 538 } \ 539 PetscFunctionReturn(PETSC_SUCCESS); \ 540 } \ 541 } \ 542 } while (0) 543 544 /*MC 545 KSPCheckNorm - Checks if the result of a norm used by the corresponding `KSP` contains `inf` or `NaN`. These indicate that the previous 546 application of the preconditioner generated an error. Sets a `KSPConvergedReason` and returns if the `PC` set a `PCFailedReason`. 547 548 Collective 549 550 Input Parameter: 551 . ksp - the linear solver `KSP` context. 552 553 Output Parameter: 554 . beta - the result of the norm 555 556 Level: developer 557 558 Developer Notes: 559 Used to manage returning from `KSP` solvers collectively whose preconditioners have failed, possibly only a subset of MPI processes, in some way. 560 561 It uses the fact that `KSP` piggy-backs the collectivity of certain error conditions on the results of norms and inner products. 562 563 .seealso: `PCFailedReason`, `KSPConvergedReason`, `PCGetFailedReasonRank()`, `KSP`, `KSPCreate()`, `KSPSetType()`, `KSP`, `KSPCheckDot()`, `KSPCheckSolve()`, 564 `KSPSetErrorIfNotConverged()` 565 M*/ 566 #define KSPCheckNorm(ksp, beta) \ 567 do { \ 568 if (PetscIsInfOrNanReal(beta)) { \ 569 PetscCheck(!ksp->errorifnotconverged, PetscObjectComm((PetscObject)ksp), PETSC_ERR_NOT_CONVERGED, "KSPSolve has not converged due to Nan or Inf norm"); \ 570 { \ 571 PCFailedReason pcreason; \ 572 PetscCall(PCReduceFailedReason(ksp->pc)); \ 573 PetscCall(PCGetFailedReasonRank(ksp->pc, &pcreason)); \ 574 PetscCall(VecFlag(ksp->vec_sol, pcreason)); \ 575 if (pcreason) { \ 576 ksp->reason = KSP_DIVERGED_PC_FAILED; \ 577 } else { \ 578 ksp->reason = KSP_DIVERGED_NANORINF; \ 579 } \ 580 ksp->rnorm = beta; \ 581 PetscFunctionReturn(PETSC_SUCCESS); \ 582 } \ 583 } \ 584 } while (0) 585 586 PETSC_INTERN PetscErrorCode KSPMonitorMakeKey_Internal(const char[], PetscViewerType, PetscViewerFormat, char[]); 587 PETSC_INTERN PetscErrorCode KSPMonitorRange_Private(KSP, PetscInt, PetscReal *); 588