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