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 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 PetscReal rtol, /* relative tolerance */ 97 abstol, /* absolute tolerance */ 98 ttol, /* (not set by user) */ 99 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 PetscErrorCode (*reasonview[MAXKSPREASONVIEWS])(KSP, void *); /* KSP converged reason view */ 134 PetscErrorCode (*reasonviewdestroy[MAXKSPREASONVIEWS])(void **); /* Optional destroy routine */ 135 void *reasonviewcontext[MAXKSPREASONVIEWS]; /* User context */ 136 PetscInt numberreasonviews; /* Number if reason viewers */ 137 138 PetscErrorCode (*converged)(KSP, PetscInt, PetscReal, KSPConvergedReason *, void *); 139 PetscErrorCode (*convergeddestroy)(void *); 140 void *cnvP; 141 142 void *user; /* optional user-defined context */ 143 144 PC pc; 145 146 void *data; /* holder for misc stuff associated 147 with a particular iterative solver */ 148 149 PetscBool view, viewPre, viewRate, viewMat, viewPMat, viewRhs, viewSol, viewMatExp, viewEV, viewSV, viewEVExp, viewFinalRes, viewPOpExp, viewDScale; 150 PetscViewer viewer, viewerPre, viewerRate, viewerMat, viewerPMat, viewerRhs, viewerSol, viewerMatExp, viewerEV, viewerSV, viewerEVExp, viewerFinalRes, viewerPOpExp, viewerDScale; 151 PetscViewerFormat format, formatPre, formatRate, formatMat, formatPMat, formatRhs, formatSol, formatMatExp, formatEV, formatSV, formatEVExp, formatFinalRes, formatPOpExp, formatDScale; 152 153 /* ----------------Default work-area management -------------------- */ 154 PetscInt nwork; 155 Vec *work; 156 157 KSPSetUpStage setupstage; 158 PetscBool setupnewmatrix; /* true if we need to call ksp->ops->setup with KSP_SETUP_NEWMATRIX */ 159 160 PetscInt its; /* number of iterations so far computed in THIS linear solve*/ 161 PetscInt totalits; /* number of iterations used by this KSP object since it was created */ 162 163 PetscBool transpose_solve; /* solve transpose system instead */ 164 struct { 165 Mat AT, BT; 166 PetscBool use_explicittranspose; /* transpose the system explicitly in KSPSolveTranspose */ 167 PetscBool reuse_transpose; /* reuse the previous transposed system */ 168 } transpose; 169 170 KSPNormType normtype; /* type of norm used for convergence tests */ 171 172 PCSide pc_side_set; /* PC type set explicitly by user */ 173 KSPNormType normtype_set; /* Norm type set explicitly by user */ 174 175 /* Allow diagonally scaling the matrix before computing the preconditioner or using 176 the Krylov method. Note this is NOT just Jacobi preconditioning */ 177 178 PetscBool dscale; /* diagonal scale system; used with KSPSetDiagonalScale() */ 179 PetscBool dscalefix; /* unscale system after solve */ 180 PetscBool dscalefix2; /* system has been unscaled */ 181 Vec diagonal; /* 1/sqrt(diag of matrix) */ 182 Vec truediagonal; 183 184 /* Allow declaring convergence when negative curvature is detected */ 185 PetscBool converged_neg_curve; 186 187 PetscInt setfromoptionscalled; 188 PetscBool skippcsetfromoptions; /* if set then KSPSetFromOptions() does not call PCSetFromOptions() */ 189 190 PetscErrorCode (*presolve)(KSP, Vec, Vec, void *); 191 PetscErrorCode (*postsolve)(KSP, Vec, Vec, void *); 192 void *prectx, *postctx; 193 194 PetscInt nestlevel; /* how many levels of nesting does the KSP have */ 195 }; 196 197 typedef struct { /* dummy data structure used in KSPMonitorDynamicTolerance() */ 198 PetscReal coef; 199 PetscReal bnrm; 200 } KSPDynTolCtx; 201 202 typedef struct { 203 PetscBool initialrtol; /* default relative residual decrease is computed from initial residual, not rhs */ 204 PetscBool mininitialrtol; /* default relative residual decrease is computed from min of initial residual and rhs */ 205 PetscBool convmaxits; /* if true, the convergence test returns KSP_CONVERGED_ITS if the maximum number of iterations is reached */ 206 Vec work; 207 } KSPConvergedDefaultCtx; 208 209 static inline PetscErrorCode KSPLogResidualHistory(KSP ksp, PetscReal norm) 210 { 211 PetscFunctionBegin; 212 PetscCall(PetscObjectSAWsTakeAccess((PetscObject)ksp)); 213 if (ksp->res_hist && ksp->res_hist_max > ksp->res_hist_len) ksp->res_hist[ksp->res_hist_len++] = norm; 214 PetscCall(PetscObjectSAWsGrantAccess((PetscObject)ksp)); 215 PetscFunctionReturn(PETSC_SUCCESS); 216 } 217 218 static inline PetscErrorCode KSPLogErrorHistory(KSP ksp) 219 { 220 DM dm; 221 222 PetscFunctionBegin; 223 PetscCall(PetscObjectSAWsTakeAccess((PetscObject)ksp)); 224 PetscCall(KSPGetDM(ksp, &dm)); 225 if (dm && ksp->err_hist && ksp->err_hist_max > ksp->err_hist_len) { 226 PetscSimplePointFn *exactSol; 227 void *exactCtx; 228 PetscDS ds; 229 Vec u; 230 PetscReal error; 231 PetscInt Nf; 232 233 PetscCall(KSPBuildSolution(ksp, NULL, &u)); 234 /* TODO Was needed to correct for Newton solution, but I just need to set a solution */ 235 //PetscCall(VecScale(u, -1.0)); 236 /* TODO Case when I have a solution */ 237 if (0) { 238 PetscCall(DMGetDS(dm, &ds)); 239 PetscCall(PetscDSGetNumFields(ds, &Nf)); 240 PetscCheck(Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle number of fields %" PetscInt_FMT " > 1 right now", Nf); 241 PetscCall(PetscDSGetExactSolution(ds, 0, &exactSol, &exactCtx)); 242 PetscCall(DMComputeL2FieldDiff(dm, 0.0, &exactSol, &exactCtx, u, &error)); 243 } else { 244 /* The null solution A 0 = 0 */ 245 PetscCall(VecNorm(u, NORM_2, &error)); 246 } 247 ksp->err_hist[ksp->err_hist_len++] = error; 248 } 249 PetscCall(PetscObjectSAWsGrantAccess((PetscObject)ksp)); 250 PetscFunctionReturn(PETSC_SUCCESS); 251 } 252 253 static inline PetscScalar KSPNoisyHash_Private(PetscInt xx) 254 { 255 unsigned int x = (unsigned int)xx; 256 x = ((x >> 16) ^ x) * 0x45d9f3b; 257 x = ((x >> 16) ^ x) * 0x45d9f3b; 258 x = ((x >> 16) ^ x); 259 return (PetscScalar)(((PetscInt64)x - 2147483648) * 5.e-10); /* center around zero, scaled about -1. to 1.*/ 260 } 261 262 static inline PetscErrorCode KSPSetNoisy_Private(Vec v) 263 { 264 PetscScalar *a; 265 PetscInt n, istart; 266 267 PetscFunctionBegin; 268 PetscCall(VecGetOwnershipRange(v, &istart, NULL)); 269 PetscCall(VecGetLocalSize(v, &n)); 270 PetscCall(VecGetArrayWrite(v, &a)); 271 for (PetscInt i = 0; i < n; ++i) a[i] = KSPNoisyHash_Private(i + istart); 272 PetscCall(VecRestoreArrayWrite(v, &a)); 273 PetscFunctionReturn(PETSC_SUCCESS); 274 } 275 276 PETSC_INTERN PetscErrorCode KSPSetUpNorms_Private(KSP, PetscBool, KSPNormType *, PCSide *); 277 278 PETSC_INTERN PetscErrorCode KSPPlotEigenContours_Private(KSP, PetscInt, const PetscReal *, const PetscReal *); 279 280 typedef struct _p_DMKSP *DMKSP; 281 typedef struct _DMKSPOps *DMKSPOps; 282 struct _DMKSPOps { 283 KSPComputeOperatorsFn *computeoperators; 284 KSPComputeRHSFn *computerhs; 285 KSPComputeInitialGuessFn *computeinitialguess; 286 PetscErrorCode (*destroy)(DMKSP *); 287 PetscErrorCode (*duplicate)(DMKSP, DMKSP); 288 }; 289 290 /*S 291 DMKSP - Object held by a `DM` that contains all the callback functions and their contexts needed by a `KSP` 292 293 Level: developer 294 295 Notes: 296 Users provides callback functions and their contexts to `KSP` using, for example, `KSPSetComputeRHS()`. These values are stored 297 in a `DMKSP` that is contained in the `DM` associated with the `KSP`. If no `DM` was provided by 298 the user with `KSPSetDM()` it is automatically created by `KSPGetDM()` with `DMShellCreate()`. 299 300 Users very rarely need to worked directly with the `DMKSP` object, rather they work with the `KSP` and the `DM` they created 301 302 Multiple `DM` can share a single `DMKSP`, often each `DM` is associated with 303 a grid refinement level. `DMGetDMKSP()` returns the `DMKSP` associated with a `DM`. `DMGetDMKSPWrite()` returns a unique 304 `DMKSP` that is only associated with the current `DM`, making a copy of the shared `DMKSP` if needed (copy-on-write). 305 306 Developer Notes: 307 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`. 308 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, 309 but we need to also support different callbacks and contexts on each level. The copy-on-write approach of `DMGetDMKSPWrite()` makes this possible. 310 311 The `originaldm` inside the `DMKSP` is NOT reference counted (to prevent a reference count loop between a `DM` and a `DMKSP`). 312 The `DM` on which this context was first created is cached here to implement one-way 313 copy-on-write. When `DMGetDMKSPWrite()` sees a request using a different `DM`, it makes a copy of the `TSDM`. Thus, if a user 314 only interacts directly with one level, e.g., using `TSSetIFunction()`, then coarse levels of a multilevel item 315 integrator are built, then the user changes the routine with another call to `TSSetIFunction()`, it automatically 316 propagates to all the levels. If instead, they get out a specific level and set the function on that level, 317 subsequent changes to the original level will no longer propagate to that level. 318 319 .seealso: [](ch_ts), `KSP`, `KSPCreate()`, `DM`, `DMGetDMKSPWrite()`, `DMGetDMKSP()`, `DMSNES`, `DMTS`, `DMKSPSetComputeOperators()`, `DMKSPGetComputeOperators()`, 320 `DMKSPSetComputeRHS()`, `DMKSPSetComputeInitialGuess()` 321 S*/ 322 struct _p_DMKSP { 323 PETSCHEADER(struct _DMKSPOps); 324 void *operatorsctx; 325 void *rhsctx; 326 void *initialguessctx; 327 void *data; 328 329 /* See developer note for `DMKSP` above */ 330 DM originaldm; 331 332 void (*fortran_func_pointers[3])(void); /* Store our own function pointers so they are associated with the DMKSP instead of the DM */ 333 }; 334 PETSC_EXTERN PetscErrorCode DMGetDMKSP(DM, DMKSP *); 335 PETSC_EXTERN PetscErrorCode DMGetDMKSPWrite(DM, DMKSP *); 336 PETSC_EXTERN PetscErrorCode DMCopyDMKSP(DM, DM); 337 338 /* 339 These allow the various Krylov methods to apply to either the linear system or its transpose. 340 */ 341 static inline PetscErrorCode KSP_RemoveNullSpace(KSP ksp, Vec y) 342 { 343 PetscFunctionBegin; 344 if (ksp->pc_side == PC_LEFT) { 345 Mat A; 346 MatNullSpace nullsp; 347 348 PetscCall(PCGetOperators(ksp->pc, &A, NULL)); 349 PetscCall(MatGetNullSpace(A, &nullsp)); 350 if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, y)); 351 } 352 PetscFunctionReturn(PETSC_SUCCESS); 353 } 354 355 static inline PetscErrorCode KSP_RemoveNullSpaceTranspose(KSP ksp, Vec y) 356 { 357 PetscFunctionBegin; 358 if (ksp->pc_side == PC_LEFT) { 359 Mat A; 360 MatNullSpace nullsp; 361 362 PetscCall(PCGetOperators(ksp->pc, &A, NULL)); 363 PetscCall(MatGetTransposeNullSpace(A, &nullsp)); 364 if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, y)); 365 } 366 PetscFunctionReturn(PETSC_SUCCESS); 367 } 368 369 static inline PetscErrorCode KSP_MatMult(KSP ksp, Mat A, Vec x, Vec y) 370 { 371 PetscFunctionBegin; 372 if (ksp->transpose_solve) PetscCall(MatMultTranspose(A, x, y)); 373 else PetscCall(MatMult(A, x, y)); 374 PetscFunctionReturn(PETSC_SUCCESS); 375 } 376 377 static inline PetscErrorCode KSP_MatMultTranspose(KSP ksp, Mat A, Vec x, Vec y) 378 { 379 PetscFunctionBegin; 380 if (ksp->transpose_solve) PetscCall(MatMult(A, x, y)); 381 else PetscCall(MatMultTranspose(A, x, y)); 382 PetscFunctionReturn(PETSC_SUCCESS); 383 } 384 385 static inline PetscErrorCode KSP_MatMultHermitianTranspose(KSP ksp, Mat A, Vec x, Vec y) 386 { 387 PetscFunctionBegin; 388 if (!ksp->transpose_solve) PetscCall(MatMultHermitianTranspose(A, x, y)); 389 else { 390 Vec w; 391 392 PetscCall(VecDuplicate(x, &w)); 393 PetscCall(VecCopy(x, w)); 394 PetscCall(VecConjugate(w)); 395 PetscCall(MatMult(A, w, y)); 396 PetscCall(VecDestroy(&w)); 397 PetscCall(VecConjugate(y)); 398 } 399 PetscFunctionReturn(PETSC_SUCCESS); 400 } 401 402 static inline PetscErrorCode KSP_PCApply(KSP ksp, Vec x, Vec y) 403 { 404 PetscFunctionBegin; 405 if (ksp->transpose_solve) { 406 PetscCall(PCApplyTranspose(ksp->pc, x, y)); 407 PetscCall(KSP_RemoveNullSpaceTranspose(ksp, y)); 408 } else { 409 PetscCall(PCApply(ksp->pc, x, y)); 410 PetscCall(KSP_RemoveNullSpace(ksp, y)); 411 } 412 PetscFunctionReturn(PETSC_SUCCESS); 413 } 414 415 static inline PetscErrorCode KSP_PCApplyTranspose(KSP ksp, Vec x, Vec y) 416 { 417 PetscFunctionBegin; 418 if (ksp->transpose_solve) { 419 PetscCall(PCApply(ksp->pc, x, y)); 420 PetscCall(KSP_RemoveNullSpace(ksp, y)); 421 } else { 422 PetscCall(PCApplyTranspose(ksp->pc, x, y)); 423 PetscCall(KSP_RemoveNullSpaceTranspose(ksp, y)); 424 } 425 PetscFunctionReturn(PETSC_SUCCESS); 426 } 427 428 static inline PetscErrorCode KSP_PCApplyHermitianTranspose(KSP ksp, Vec x, Vec y) 429 { 430 PetscFunctionBegin; 431 PetscCall(VecConjugate(x)); 432 PetscCall(KSP_PCApplyTranspose(ksp, x, y)); 433 PetscCall(VecConjugate(x)); 434 PetscCall(VecConjugate(y)); 435 PetscFunctionReturn(PETSC_SUCCESS); 436 } 437 438 static inline PetscErrorCode KSP_PCMatApply(KSP ksp, Mat X, Mat Y) 439 { 440 PetscFunctionBegin; 441 if (ksp->transpose_solve) { 442 PetscBool flg; 443 PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp->pc, &flg, PCNONE, PCICC, PCCHOLESKY, "")); 444 PetscCheck(flg, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "PCMatApplyTranspose() not yet implemented for nonsymmetric PC"); 445 } 446 PetscCall(PCMatApply(ksp->pc, X, Y)); 447 PetscFunctionReturn(PETSC_SUCCESS); 448 } 449 450 static inline PetscErrorCode KSP_PCMatApplyTranspose(KSP ksp, Mat X, Mat Y) 451 { 452 PetscFunctionBegin; 453 if (!ksp->transpose_solve) { 454 PetscBool flg; 455 PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp->pc, &flg, PCNONE, PCICC, PCCHOLESKY, "")); 456 PetscCheck(flg, PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "PCMatApplyTranspose() not yet implemented for nonsymmetric PC"); 457 } 458 PetscCall(PCMatApply(ksp->pc, X, Y)); 459 PetscFunctionReturn(PETSC_SUCCESS); 460 } 461 462 static inline PetscErrorCode KSP_PCApplyBAorAB(KSP ksp, Vec x, Vec y, Vec w) 463 { 464 PetscFunctionBegin; 465 if (ksp->transpose_solve) { 466 PetscCall(PCApplyBAorABTranspose(ksp->pc, ksp->pc_side, x, y, w)); 467 PetscCall(KSP_RemoveNullSpaceTranspose(ksp, y)); 468 } else { 469 PetscCall(PCApplyBAorAB(ksp->pc, ksp->pc_side, x, y, w)); 470 PetscCall(KSP_RemoveNullSpace(ksp, y)); 471 } 472 PetscFunctionReturn(PETSC_SUCCESS); 473 } 474 475 static inline PetscErrorCode KSP_PCApplyBAorABTranspose(KSP ksp, Vec x, Vec y, Vec w) 476 { 477 PetscFunctionBegin; 478 if (ksp->transpose_solve) PetscCall(PCApplyBAorAB(ksp->pc, ksp->pc_side, x, y, w)); 479 else PetscCall(PCApplyBAorABTranspose(ksp->pc, ksp->pc_side, x, y, w)); 480 PetscFunctionReturn(PETSC_SUCCESS); 481 } 482 483 PETSC_EXTERN PetscLogEvent KSP_GMRESOrthogonalization; 484 PETSC_EXTERN PetscLogEvent KSP_SetUp; 485 PETSC_EXTERN PetscLogEvent KSP_Solve; 486 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_0; 487 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_1; 488 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_2; 489 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_3; 490 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_4; 491 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_S; 492 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_L; 493 PETSC_EXTERN PetscLogEvent KSP_Solve_FS_U; 494 PETSC_EXTERN PetscLogEvent KSP_SolveTranspose; 495 PETSC_EXTERN PetscLogEvent KSP_MatSolve; 496 PETSC_EXTERN PetscLogEvent KSP_MatSolveTranspose; 497 498 PETSC_INTERN PetscErrorCode MatGetSchurComplement_Basic(Mat, IS, IS, IS, IS, MatReuse, Mat *, MatSchurComplementAinvType, MatReuse, Mat *); 499 PETSC_INTERN PetscErrorCode PCPreSolveChangeRHS(PC, PetscBool *); 500 501 /*MC 502 KSPCheckDot - Checks if the result of a dot product used by the corresponding `KSP` contains Inf or NaN. These indicate that the previous 503 application of the preconditioner generated an error. Sets a `KSPConvergedReason` and returns if the `PC` set a `PCFailedReason`. 504 505 Collective 506 507 Input Parameter: 508 . ksp - the linear solver `KSP` context. 509 510 Output Parameter: 511 . beta - the result of the inner product 512 513 Level: developer 514 515 Developer Notes: 516 Used to manage returning from `KSP` solvers collectively whose preconditioners have failed, possibly only a subset of MPI processes, in some way 517 518 It uses the fact that `KSP` piggy-backs the collectivity of certain error conditions on the results of norms and inner products. 519 520 .seealso: `PCFailedReason`, `KSPConvergedReason`, `PCGetFailedReasonRank()`, `KSP`, `KSPCreate()`, `KSPSetType()`, `KSP`, `KSPCheckNorm()`, `KSPCheckSolve()`, 521 `KSPSetErrorIfNotConverged()` 522 M*/ 523 #define KSPCheckDot(ksp, beta) \ 524 do { \ 525 if (PetscIsInfOrNanScalar(beta)) { \ 526 PetscCheck(!ksp->errorifnotconverged, PetscObjectComm((PetscObject)ksp), PETSC_ERR_NOT_CONVERGED, "KSPSolve has not converged due to Nan or Inf inner product"); \ 527 { \ 528 PCFailedReason pcreason; \ 529 PetscCall(PCReduceFailedReason(ksp->pc)); \ 530 PetscCall(PCGetFailedReasonRank(ksp->pc, &pcreason)); \ 531 if (pcreason) { \ 532 ksp->reason = KSP_DIVERGED_PC_FAILED; \ 533 PetscCall(VecSetInf(ksp->vec_sol)); \ 534 } else { \ 535 ksp->reason = KSP_DIVERGED_NANORINF; \ 536 } \ 537 PetscFunctionReturn(PETSC_SUCCESS); \ 538 } \ 539 } \ 540 } while (0) 541 542 /*MC 543 KSPCheckNorm - Checks if the result of a norm used by the corresponding `KSP` contains `inf` or `NaN`. These indicate that the previous 544 application of the preconditioner generated an error. Sets a `KSPConvergedReason` and returns if the `PC` set a `PCFailedReason`. 545 546 Collective 547 548 Input Parameter: 549 . ksp - the linear solver `KSP` context. 550 551 Output Parameter: 552 . beta - the result of the norm 553 554 Level: developer 555 556 Developer Notes: 557 Used to manage returning from `KSP` solvers collectively whose preconditioners have failed, possibly only a subset of MPI processes, in some way. 558 559 It uses the fact that `KSP` piggy-backs the collectivity of certain error conditions on the results of norms and inner products. 560 561 .seealso: `PCFailedReason`, `KSPConvergedReason`, `PCGetFailedReasonRank()`, `KSP`, `KSPCreate()`, `KSPSetType()`, `KSP`, `KSPCheckDot()`, `KSPCheckSolve()`, 562 `KSPSetErrorIfNotConverged()` 563 M*/ 564 #define KSPCheckNorm(ksp, beta) \ 565 do { \ 566 if (PetscIsInfOrNanReal(beta)) { \ 567 PetscCheck(!ksp->errorifnotconverged, PetscObjectComm((PetscObject)ksp), PETSC_ERR_NOT_CONVERGED, "KSPSolve has not converged due to Nan or Inf norm"); \ 568 { \ 569 PCFailedReason pcreason; \ 570 PetscCall(PCReduceFailedReason(ksp->pc)); \ 571 PetscCall(PCGetFailedReasonRank(ksp->pc, &pcreason)); \ 572 if (pcreason) { \ 573 ksp->reason = KSP_DIVERGED_PC_FAILED; \ 574 PetscCall(VecSetInf(ksp->vec_sol)); \ 575 ksp->rnorm = beta; \ 576 } else { \ 577 ksp->reason = KSP_DIVERGED_NANORINF; \ 578 ksp->rnorm = beta; \ 579 } \ 580 PetscFunctionReturn(PETSC_SUCCESS); \ 581 } \ 582 } \ 583 } while (0) 584 585 PETSC_INTERN PetscErrorCode KSPMonitorMakeKey_Internal(const char[], PetscViewerType, PetscViewerFormat, char[]); 586 PETSC_INTERN PetscErrorCode KSPMonitorRange_Private(KSP, PetscInt, PetscReal *); 587