Actual source code: pcksp.c
2: #include src/ksp/pc/pcimpl.h
3: #include petscksp.h
5: typedef struct {
6: PetscTruth 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;
13: static PetscErrorCode PCApply_KSP(PC pc,Vec x,Vec y)
14: {
16: PetscInt its;
17: PC_KSP *jac = (PC_KSP*)pc->data;
20: KSPSolve(jac->ksp,x,y);
21: KSPGetIterationNumber(jac->ksp,&its);
22: jac->its += its;
23: return(0);
24: }
28: static PetscErrorCode PCApplyTranspose_KSP(PC pc,Vec x,Vec y)
29: {
31: PetscInt its;
32: PC_KSP *jac = (PC_KSP*)pc->data;
35: KSPSolveTranspose(jac->ksp,x,y);
36: KSPGetIterationNumber(jac->ksp,&its);
37: jac->its += its;
38: return(0);
39: }
43: static PetscErrorCode PCSetUp_KSP(PC pc)
44: {
46: PC_KSP *jac = (PC_KSP*)pc->data;
47: Mat mat;
50: KSPSetFromOptions(jac->ksp);
51: if (jac->use_true_matrix) mat = pc->mat;
52: else mat = pc->pmat;
54: KSPSetOperators(jac->ksp,mat,pc->pmat,pc->flag);
55: KSPSetUp(jac->ksp);
56: return(0);
57: }
59: /* Default destroy, if it has never been setup */
62: static PetscErrorCode PCDestroy_KSP(PC pc)
63: {
64: PC_KSP *jac = (PC_KSP*)pc->data;
68: KSPDestroy(jac->ksp);
69: PetscFree(jac);
70: return(0);
71: }
75: static PetscErrorCode PCView_KSP(PC pc,PetscViewer viewer)
76: {
77: PC_KSP *jac = (PC_KSP*)pc->data;
79: PetscTruth iascii;
82: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
83: if (iascii) {
84: if (jac->use_true_matrix) {
85: PetscViewerASCIIPrintf(viewer,"Using true matrix (not preconditioner matrix) on inner solve\n");
86: }
87: PetscViewerASCIIPrintf(viewer,"KSP and PC on KSP preconditioner follow\n");
88: PetscViewerASCIIPrintf(viewer,"---------------------------------\n");
89: } else {
90: SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for this object",((PetscObject)viewer)->type_name);
91: }
92: PetscViewerASCIIPushTab(viewer);
93: KSPView(jac->ksp,viewer);
94: PetscViewerASCIIPopTab(viewer);
95: if (iascii) {
96: PetscViewerASCIIPrintf(viewer,"---------------------------------\n");
97: }
98: return(0);
99: }
103: static PetscErrorCode PCSetFromOptions_KSP(PC pc)
104: {
106: PetscTruth flg;
109: PetscOptionsHead("KSP preconditioner options");
110: PetscOptionsName("-pc_ksp_true","Use true matrix to define inner linear system, not preconditioner matrix","PCKSPSetUseTrue",&flg);
111: if (flg) {
112: PCKSPSetUseTrue(pc);
113: }
114: PetscOptionsTail();
115: return(0);
116: }
118: /* ----------------------------------------------------------------------------------*/
123: PetscErrorCode PCKSPSetUseTrue_KSP(PC pc)
124: {
125: PC_KSP *jac;
128: jac = (PC_KSP*)pc->data;
129: jac->use_true_matrix = PETSC_TRUE;
130: return(0);
131: }
137: PetscErrorCode PCKSPGetKSP_KSP(PC pc,KSP *ksp)
138: {
139: PC_KSP *jac;
142: jac = (PC_KSP*)pc->data;
143: *ksp = jac->ksp;
144: return(0);
145: }
150: /*@
151: PCKSPSetUseTrue - Sets a flag to indicate that the true matrix (rather than
152: the matrix used to define the preconditioner) is used to compute the
153: residual inside the inner solve.
155: Collective on PC
157: Input Parameters:
158: . pc - the preconditioner context
160: Options Database Key:
161: . -pc_ksp_true - Activates PCKSPSetUseTrue()
163: Note:
164: For the common case in which the preconditioning and linear
165: system matrices are identical, this routine is unnecessary.
167: Level: advanced
169: .keywords: PC, KSP, set, true, local, flag
171: .seealso: PCSetOperators(), PCBJacobiSetUseTrueLocal()
172: @*/
173: PetscErrorCode PCKSPSetUseTrue(PC pc)
174: {
175: PetscErrorCode ierr,(*f)(PC);
179: PetscObjectQueryFunction((PetscObject)pc,"PCKSPSetUseTrue_C",(void (**)(void))&f);
180: if (f) {
181: (*f)(pc);
182: }
183: return(0);
184: }
188: /*@C
189: PCKSPGetKSP - Gets the KSP context for a KSP PC.
191: Not Collective but KSP returned is parallel if PC was parallel
193: Input Parameter:
194: . pc - the preconditioner context
196: Output Parameters:
197: . ksp - the PC solver
199: Notes:
200: You must call KSPSetUp() before calling PCKSPGetKSP().
202: Level: advanced
204: .keywords: PC, KSP, get, context
205: @*/
206: PetscErrorCode PCKSPGetKSP(PC pc,KSP *ksp)
207: {
208: PetscErrorCode ierr,(*f)(PC,KSP*);
213: if (!pc->setupcalled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must call KSPSetUp first");
214: PetscObjectQueryFunction((PetscObject)pc,"PCKSPGetKSP_C",(void (**)(void))&f);
215: if (f) {
216: (*f)(pc,ksp);
217: }
218: return(0);
219: }
221: /* ----------------------------------------------------------------------------------*/
223: /*MC
224: PCKSP - Defines a preconditioner that can consist of any KSP solver.
225: This allows, for example, embedding a Krylov method inside a preconditioner.
227: Options Database Key:
228: . -pc_ksp_true - use the matrix that defines the linear system as the matrix for the
229: inner solver, otherwise by default it uses the matrix used to construct
230: the preconditioner (see PCSetOperators())
232: Level: intermediate
234: Concepts: inner iteration
236: Notes: Using a Krylov method inside another Krylov method can be dangerous (you get divergence or
237: the incorrect answer) unless you use KSPFGMRES as the other Krylov method
240: .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC,
241: PCSHELL, PCCOMPOSITE, PCKSPUseTrue(), PCKSPGetKSP()
243: M*/
248: PetscErrorCode PCCreate_KSP(PC pc)
249: {
251: char *prefix;
252: PC_KSP *jac;
255: PetscNew(PC_KSP,&jac);
256: PetscLogObjectMemory(pc,sizeof(PC_KSP));
257: pc->ops->apply = PCApply_KSP;
258: pc->ops->applytranspose = PCApplyTranspose_KSP;
259: pc->ops->setup = PCSetUp_KSP;
260: pc->ops->destroy = PCDestroy_KSP;
261: pc->ops->setfromoptions = PCSetFromOptions_KSP;
262: pc->ops->view = PCView_KSP;
263: pc->ops->applyrichardson = 0;
265: pc->data = (void*)jac;
266: KSPCreate(pc->comm,&jac->ksp);
268: PCGetOptionsPrefix(pc,&prefix);
269: KSPSetOptionsPrefix(jac->ksp,prefix);
270: KSPAppendOptionsPrefix(jac->ksp,"ksp_");
271: jac->use_true_matrix = PETSC_FALSE;
272: jac->its = 0;
274: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCKSPSetUseTrue_C","PCKSPSetUseTrue_KSP",
275: PCKSPSetUseTrue_KSP);
276: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCKSPGetKSP_C","PCKSPGetKSP_KSP",
277: PCKSPGetKSP_KSP);
279: return(0);
280: }