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: }