Actual source code: preonly.c
1: #include <petsc/private/kspimpl.h>
3: static PetscErrorCode KSPSetUp_PREONLY(KSP ksp)
4: {
5: PetscFunctionBegin;
6: PetscFunctionReturn(PETSC_SUCCESS);
7: }
9: static PetscErrorCode KSPSolve_PREONLY(KSP ksp)
10: {
11: PetscReal norm;
12: PetscBool flg;
13: PCFailedReason pcreason;
15: PetscFunctionBegin;
16: if (!ksp->guess_zero) {
17: PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp->pc, &flg, PCREDISTRIBUTE, PCMPI, ""));
18: PetscCheck(flg, PetscObjectComm((PetscObject)ksp), PETSC_ERR_USER, "KSP of type preonly (application of preconditioner only) doesn't make sense with nonzero initial guess you probably want a KSP of type Richardson");
19: }
20: ksp->its = 0;
21: if (ksp->numbermonitors) {
22: PetscCall(VecNorm(ksp->vec_rhs, NORM_2, &norm));
23: PetscCall(KSPMonitor(ksp, 0, norm));
24: }
25: PetscCall(KSP_PCApply(ksp, ksp->vec_rhs, ksp->vec_sol));
26: PetscCall(PCReduceFailedReason(ksp->pc));
27: PetscCall(PCGetFailedReason(ksp->pc, &pcreason));
28: PetscCall(VecFlag(ksp->vec_sol, pcreason));
29: if (pcreason) {
30: PetscCheck(!ksp->errorifnotconverged, PetscObjectComm((PetscObject)ksp), PETSC_ERR_NOT_CONVERGED, "KSPSolve has not converged with PCFailedReason %s", PCFailedReasons[pcreason]);
31: ksp->reason = KSP_DIVERGED_PC_FAILED;
32: } else {
33: ksp->its = 1;
34: ksp->reason = KSP_CONVERGED_ITS;
35: }
36: if (ksp->numbermonitors) {
37: Vec v;
38: Mat A;
40: PetscCall(VecDuplicate(ksp->vec_rhs, &v));
41: PetscCall(PCGetOperators(ksp->pc, &A, NULL));
42: PetscCall(KSP_MatMult(ksp, A, ksp->vec_sol, v));
43: PetscCall(VecAYPX(v, -1.0, ksp->vec_rhs));
44: PetscCall(VecNorm(v, NORM_2, &norm));
45: PetscCall(VecDestroy(&v));
46: PetscCall(KSPMonitor(ksp, 1, norm));
47: }
48: PetscFunctionReturn(PETSC_SUCCESS);
49: }
51: static PetscErrorCode KSPMatSolve_PREONLY(KSP ksp, Mat B, Mat X)
52: {
53: PCFailedReason pcreason;
55: PetscFunctionBegin;
56: PetscCheck(ksp->guess_zero, PetscObjectComm((PetscObject)ksp), PETSC_ERR_USER, "Running KSP of preonly doesn't make sense with nonzero initial guess you probably want a KSP type of Richardson");
57: ksp->its = 0;
58: PetscCall(KSP_PCMatApply(ksp, B, X));
59: PetscCall(PCReduceFailedReason(ksp->pc));
60: PetscCall(PCGetFailedReason(ksp->pc, &pcreason));
61: PetscCall(MatFlag(X, pcreason));
62: if (pcreason) {
63: PetscCheck(!ksp->errorifnotconverged, PetscObjectComm((PetscObject)ksp), PETSC_ERR_NOT_CONVERGED, "KSPMatSolve%s() has not converged with PCFailedReason %s", ksp->transpose.solve_requested ? "Transpose" : "", PCFailedReasons[pcreason]);
64: ksp->reason = KSP_DIVERGED_PC_FAILED;
65: } else {
66: ksp->its = 1;
67: ksp->reason = KSP_CONVERGED_ITS;
68: }
69: PetscFunctionReturn(PETSC_SUCCESS);
70: }
72: /*MC
73: KSPNONE - An alias for `KSPPREONLY`
75: Options Database Key:
76: . -ksp_type none - use a single application of the preconditioner only
78: Level: beginner
80: Note:
81: See `KSPPREONLY` for more details
83: .seealso: [](ch_ksp), `KSPCreate()`, `KSPSetType()`, `KSPType`, `KSPPREONLY`, `KSP`, `KSPRICHARDSON`, `KSPCHEBYSHEV`, `KSPGetPC()`, `KSPSetInitialGuessNonzero()`,
84: `PCREDISTRIBUTE`, `PCRedistributeGetKSP()`
85: M*/
87: /*MC
88: KSPPREONLY - This implements a method that applies ONLY the preconditioner exactly once.
90: It is commonly used with the direct solver preconditioners like `PCLU` and `PCCHOLESKY`, but it may also be used when a single iteration of the
91: preconditioner is needed for smoothing in multigrid, `PCMG` or `PCGAMG` or within some other nested linear solve such as `PCFIELDSPLIT` or `PCBJACOBI`.
93: There is an alias of this with the name `KSPNONE`.
95: Options Database Key:
96: . -ksp_type preonly - use a single application of the preconditioner only
98: Level: beginner
100: Notes:
101: Since this does not involve an iteration the basic `KSP` parameters such as tolerances and maximum iteration counts
102: do not apply
104: To apply the preconditioner multiple times in a simple iteration use `KSPRICHARDSON`
106: This `KSPType` cannot be used with the flag `-ksp_initial_guess_nonzero` or the call `KSPSetInitialGuessNonzero()` since it simply applies
107: the preconditioner to the given right-hand side during `KSPSolve()`. Except when the
108: `PCType` is `PCREDISTRIBUTE`; in that situation pass the nonzero initial guess flag with `-ksp_initial_guess_nonzero` or `KSPSetInitialGuessNonzero()`
109: both to the outer `KSP` (which is `KSPPREONLY`) and the inner `KSP` object obtained with `KSPGetPC()` followed by `PCRedistributedGetKSP()`
110: followed by `KSPSetInitialGuessNonzero()` or the option `-redistribute_ksp_initial_guess_nonzero`.
112: Developer Note:
113: Even though this method does not use any norms, the user is allowed to set the `KSPNormType` to any value.
114: This is so the users does not have to change `KSPNormType` options when they switch from other `KSP` methods to this one.
116: .seealso: [](ch_ksp), `KSPCreate()`, `KSPSetType()`, `KSPType`, `KSP`, `KSPRICHARDSON`, `KSPCHEBYSHEV`, `KSPGetPC()`, `KSPSetInitialGuessNonzero()`,
117: `PCREDISTRIBUTE`, `PCRedistributeGetKSP()`, `KSPNONE`
118: M*/
120: PETSC_EXTERN PetscErrorCode KSPCreate_PREONLY(KSP ksp)
121: {
122: PetscFunctionBegin;
123: PetscCall(KSPSetSupportedNorm(ksp, KSP_NORM_NONE, PC_LEFT, 3));
124: PetscCall(KSPSetSupportedNorm(ksp, KSP_NORM_NONE, PC_RIGHT, 2));
125: PetscCall(KSPSetSupportedNorm(ksp, KSP_NORM_PRECONDITIONED, PC_LEFT, 2));
126: PetscCall(KSPSetSupportedNorm(ksp, KSP_NORM_PRECONDITIONED, PC_RIGHT, 2));
127: PetscCall(KSPSetSupportedNorm(ksp, KSP_NORM_UNPRECONDITIONED, PC_LEFT, 2));
128: PetscCall(KSPSetSupportedNorm(ksp, KSP_NORM_UNPRECONDITIONED, PC_RIGHT, 2));
129: PetscCall(KSPSetSupportedNorm(ksp, KSP_NORM_NATURAL, PC_LEFT, 2));
131: ksp->data = NULL;
132: ksp->ops->setup = KSPSetUp_PREONLY;
133: ksp->ops->solve = KSPSolve_PREONLY;
134: ksp->ops->matsolve = KSPMatSolve_PREONLY;
135: ksp->ops->destroy = KSPDestroyDefault;
136: ksp->ops->buildsolution = KSPBuildSolutionDefault;
137: ksp->ops->buildresidual = KSPBuildResidualDefault;
138: ksp->ops->setfromoptions = NULL;
139: ksp->ops->view = NULL;
140: ksp->guess_not_read = PETSC_TRUE; // A KSP of preonly never needs to zero the input x since PC do not use an initial guess
141: PetscFunctionReturn(PETSC_SUCCESS);
142: }