Actual source code: pcksp.c
2: #include <private/pcimpl.h> /*I "petscpc.h" I*/
3: #include <petscksp.h> /*I "petscksp.h" I*/
5: typedef struct {
6: PetscBool use_true_matrix; /* use mat rather than pmat in inner linear solve */
7: KSP ksp;
8: PetscInt its; /* total number of iterations KSP uses */
9: } PC_KSP;
14: static PetscErrorCode PCKSPCreateKSP_KSP(PC pc)
15: {
17: const char *prefix;
18: PC_KSP *jac = (PC_KSP *)pc->data;
21: KSPCreate(((PetscObject)pc)->comm,&jac->ksp);
22: PetscObjectIncrementTabLevel((PetscObject)jac->ksp,(PetscObject)pc,1);
23: PCGetOptionsPrefix(pc,&prefix);
24: KSPSetOptionsPrefix(jac->ksp,prefix);
25: KSPAppendOptionsPrefix(jac->ksp,"ksp_");
26: return(0);
27: }
31: static PetscErrorCode PCApply_KSP(PC pc,Vec x,Vec y)
32: {
34: PetscInt its;
35: PC_KSP *jac = (PC_KSP*)pc->data;
38: KSPSetInitialGuessNonzero(jac->ksp,pc->nonzero_guess);
39: KSPSolve(jac->ksp,x,y);
40: KSPGetIterationNumber(jac->ksp,&its);
41: jac->its += its;
42: return(0);
43: }
47: static PetscErrorCode PCApplyTranspose_KSP(PC pc,Vec x,Vec y)
48: {
50: PetscInt its;
51: PC_KSP *jac = (PC_KSP*)pc->data;
54: KSPSolveTranspose(jac->ksp,x,y);
55: KSPGetIterationNumber(jac->ksp,&its);
56: jac->its += its;
57: return(0);
58: }
62: static PetscErrorCode PCSetUp_KSP(PC pc)
63: {
65: PC_KSP *jac = (PC_KSP*)pc->data;
66: Mat mat;
67: PetscBool A;
70: if (!jac->ksp) {PCKSPCreateKSP_KSP(pc);}
71: KSPSetFromOptions(jac->ksp);
72: if (jac->use_true_matrix) mat = pc->mat;
73: else mat = pc->pmat;
75: KSPGetOperatorsSet(jac->ksp,&A,PETSC_NULL);
76: if (!A) {
77: KSPSetOperators(jac->ksp,mat,pc->pmat,pc->flag);
78: }
79: KSPSetUp(jac->ksp);
80: return(0);
81: }
83: /* Default destroy, if it has never been setup */
86: static PetscErrorCode PCReset_KSP(PC pc)
87: {
88: PC_KSP *jac = (PC_KSP*)pc->data;
92: if (jac->ksp) {KSPReset(jac->ksp);}
93: return(0);
94: }
98: static PetscErrorCode PCDestroy_KSP(PC pc)
99: {
100: PC_KSP *jac = (PC_KSP*)pc->data;
104: PCReset_KSP(pc);
105: KSPDestroy(&jac->ksp);
106: PetscFree(pc->data);
107: return(0);
108: }
112: static PetscErrorCode PCView_KSP(PC pc,PetscViewer viewer)
113: {
114: PC_KSP *jac = (PC_KSP*)pc->data;
116: PetscBool iascii;
119: if (!jac->ksp) {PCKSPCreateKSP_KSP(pc);}
120: PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
121: if (iascii) {
122: if (jac->use_true_matrix) {
123: PetscViewerASCIIPrintf(viewer,"Using true matrix (not preconditioner matrix) on inner solve\n");
124: }
125: PetscViewerASCIIPrintf(viewer,"KSP and PC on KSP preconditioner follow\n");
126: PetscViewerASCIIPrintf(viewer,"---------------------------------\n");
127: } else {
128: SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for this object",((PetscObject)viewer)->type_name);
129: }
130: PetscViewerASCIIPushTab(viewer);
131: KSPView(jac->ksp,viewer);
132: PetscViewerASCIIPopTab(viewer);
133: if (iascii) {
134: PetscViewerASCIIPrintf(viewer,"---------------------------------\n");
135: }
136: return(0);
137: }
141: static PetscErrorCode PCSetFromOptions_KSP(PC pc)
142: {
144: PetscBool flg = PETSC_FALSE;
147: PetscOptionsHead("KSP preconditioner options");
148: PetscOptionsBool("-pc_ksp_true","Use true matrix to define inner linear system, not preconditioner matrix","PCKSPSetUseTrue",flg,&flg,PETSC_NULL);
149: if (flg) {
150: PCKSPSetUseTrue(pc);
151: }
152: PetscOptionsTail();
153: return(0);
154: }
156: /* ----------------------------------------------------------------------------------*/
161: PetscErrorCode PCKSPSetUseTrue_KSP(PC pc)
162: {
163: PC_KSP *jac;
166: jac = (PC_KSP*)pc->data;
167: jac->use_true_matrix = PETSC_TRUE;
168: return(0);
169: }
175: PetscErrorCode PCKSPGetKSP_KSP(PC pc,KSP *ksp)
176: {
177: PC_KSP *jac = (PC_KSP*)pc->data;
181: if (!jac->ksp) {PCKSPCreateKSP_KSP(pc);}
182: *ksp = jac->ksp;
183: return(0);
184: }
189: /*@
190: PCKSPSetUseTrue - Sets a flag to indicate that the true matrix (rather than
191: the matrix used to define the preconditioner) is used to compute the
192: residual inside the inner solve.
194: Logically Collective on PC
196: Input Parameters:
197: . pc - the preconditioner context
199: Options Database Key:
200: . -pc_ksp_true - Activates PCKSPSetUseTrue()
202: Note:
203: For the common case in which the preconditioning and linear
204: system matrices are identical, this routine is unnecessary.
206: Level: advanced
208: .keywords: PC, KSP, set, true, local, flag
210: .seealso: PCSetOperators(), PCBJacobiSetUseTrueLocal()
211: @*/
212: PetscErrorCode PCKSPSetUseTrue(PC pc)
213: {
218: PetscTryMethod(pc,"PCKSPSetUseTrue_C",(PC),(pc));
219: return(0);
220: }
224: /*@
225: PCKSPGetKSP - Gets the KSP context for a KSP PC.
227: Not Collective but KSP returned is parallel if PC was parallel
229: Input Parameter:
230: . pc - the preconditioner context
232: Output Parameters:
233: . ksp - the PC solver
235: Notes:
236: You must call KSPSetUp() before calling PCKSPGetKSP().
238: Level: advanced
240: .keywords: PC, KSP, get, context
241: @*/
242: PetscErrorCode PCKSPGetKSP(PC pc,KSP *ksp)
243: {
249: PetscTryMethod(pc,"PCKSPGetKSP_C",(PC,KSP*),(pc,ksp));
250: return(0);
251: }
253: /* ----------------------------------------------------------------------------------*/
255: /*MC
256: PCKSP - Defines a preconditioner that can consist of any KSP solver.
257: This allows, for example, embedding a Krylov method inside a preconditioner.
259: Options Database Key:
260: . -pc_ksp_true - use the matrix that defines the linear system as the matrix for the
261: inner solver, otherwise by default it uses the matrix used to construct
262: the preconditioner (see PCSetOperators())
264: Level: intermediate
266: Concepts: inner iteration
268: Notes: Using a Krylov method inside another Krylov method can be dangerous (you get divergence or
269: the incorrect answer) unless you use KSPFGMRES as the other Krylov method
271: Developer Notes: PCApply_KSP() uses the flag set by PCSetInitialGuessNonzero(), I think this is totally wrong, because it is then not
272: using this inner KSP as a preconditioner (that is a linear operator applied to some vector), it is actually just using
273: the inner KSP just like the outer KSP.
275: .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC,
276: PCSHELL, PCCOMPOSITE, PCKSPUseTrue(), PCKSPGetKSP()
278: M*/
283: PetscErrorCode PCCreate_KSP(PC pc)
284: {
286: PC_KSP *jac;
289: PetscNewLog(pc,PC_KSP,&jac);
290: pc->ops->apply = PCApply_KSP;
291: pc->ops->applytranspose = PCApplyTranspose_KSP;
292: pc->ops->setup = PCSetUp_KSP;
293: pc->ops->reset = PCReset_KSP;
294: pc->ops->destroy = PCDestroy_KSP;
295: pc->ops->setfromoptions = PCSetFromOptions_KSP;
296: pc->ops->view = PCView_KSP;
297: pc->ops->applyrichardson = 0;
299: pc->data = (void*)jac;
300:
302: jac->use_true_matrix = PETSC_FALSE;
303: jac->its = 0;
305: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCKSPSetUseTrue_C","PCKSPSetUseTrue_KSP",
306: PCKSPSetUseTrue_KSP);
307: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCKSPGetKSP_C","PCKSPGetKSP_KSP",
308: PCKSPGetKSP_KSP);
310: return(0);
311: }