Actual source code: pcksp.c

petsc-3.7.5 2017-01-01
Report Typos and Errors
  2: #include <petsc/private/pcimpl.h>
  3: #include <petscksp.h>            /*I "petscksp.h" I*/

  5: typedef struct {
  6:   KSP       ksp;
  7:   PetscInt  its;                    /* total number of iterations KSP uses */
  8: } PC_KSP;


 13: static PetscErrorCode  PCKSPCreateKSP_KSP(PC pc)
 14: {
 16:   const char     *prefix;
 17:   PC_KSP         *jac = (PC_KSP*)pc->data;

 20:   KSPCreate(PetscObjectComm((PetscObject)pc),&jac->ksp);
 21:   KSPSetErrorIfNotConverged(jac->ksp,pc->erroriffailure);
 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: }

 29: #include <petsc/private/kspimpl.h>
 32: static PetscErrorCode PCApply_KSP(PC pc,Vec x,Vec y)
 33: {
 35:   PetscInt       its;
 36:   PC_KSP         *jac = (PC_KSP*)pc->data;

 39:   KSPSolve(jac->ksp,x,y);
 40:   KSPGetIterationNumber(jac->ksp,&its);
 41:   jac->its += its;
 42:   if (jac->ksp->reason == KSP_DIVERGED_PCSETUP_FAILED) {
 43:     pc->failedreason = PC_SUBPC_ERROR;
 44:   }
 45:   return(0);
 46: }

 50: static PetscErrorCode PCApplyTranspose_KSP(PC pc,Vec x,Vec y)
 51: {
 53:   PetscInt       its;
 54:   PC_KSP         *jac = (PC_KSP*)pc->data;

 57:   KSPSolveTranspose(jac->ksp,x,y);
 58:   KSPGetIterationNumber(jac->ksp,&its);
 59:   jac->its += its;
 60:   return(0);
 61: }

 65: static PetscErrorCode PCSetUp_KSP(PC pc)
 66: {
 68:   PC_KSP         *jac = (PC_KSP*)pc->data;
 69:   Mat            mat;

 72:   if (!jac->ksp) {PCKSPCreateKSP_KSP(pc);}
 73:   KSPSetFromOptions(jac->ksp);
 74:   if (pc->useAmat) mat = pc->mat;
 75:   else             mat = pc->pmat;

 77:   KSPSetOperators(jac->ksp,mat,pc->pmat);
 78:   KSPSetUp(jac->ksp);
 79:   return(0);
 80: }

 82: /* Default destroy, if it has never been setup */
 85: static PetscErrorCode PCReset_KSP(PC pc)
 86: {
 87:   PC_KSP         *jac = (PC_KSP*)pc->data;

 91:   if (jac->ksp) {KSPReset(jac->ksp);}
 92:   return(0);
 93: }

 97: static PetscErrorCode PCDestroy_KSP(PC pc)
 98: {
 99:   PC_KSP         *jac = (PC_KSP*)pc->data;

103:   PCReset_KSP(pc);
104:   KSPDestroy(&jac->ksp);
105:   PetscFree(pc->data);
106:   return(0);
107: }

111: static PetscErrorCode PCView_KSP(PC pc,PetscViewer viewer)
112: {
113:   PC_KSP         *jac = (PC_KSP*)pc->data;
115:   PetscBool      iascii;

118:   if (!jac->ksp) {PCKSPCreateKSP_KSP(pc);}
119:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
120:   if (iascii) {
121:     if (pc->useAmat) {
122:       PetscViewerASCIIPrintf(viewer,"Using Amat (not Pmat) as operator on inner solve\n");
123:     }
124:     PetscViewerASCIIPrintf(viewer,"KSP and PC on KSP preconditioner follow\n");
125:     PetscViewerASCIIPrintf(viewer,"---------------------------------\n");
126:   }
127:   PetscViewerASCIIPushTab(viewer);
128:   KSPView(jac->ksp,viewer);
129:   PetscViewerASCIIPopTab(viewer);
130:   if (iascii) {
131:     PetscViewerASCIIPrintf(viewer,"---------------------------------\n");
132:   }
133:   return(0);
134: }

138: static PetscErrorCode  PCKSPGetKSP_KSP(PC pc,KSP *ksp)
139: {
140:   PC_KSP         *jac = (PC_KSP*)pc->data;

144:   if (!jac->ksp) {PCKSPCreateKSP_KSP(pc);}
145:   *ksp = jac->ksp;
146:   return(0);
147: }

151: /*@
152:    PCKSPGetKSP - Gets the KSP context for a KSP PC.

154:    Not Collective but KSP returned is parallel if PC was parallel

156:    Input Parameter:
157: .  pc - the preconditioner context

159:    Output Parameters:
160: .  ksp - the PC solver

162:    Notes:
163:    You must call KSPSetUp() before calling PCKSPGetKSP().

165:    If the PC is not a PCKSP object then a NULL is returned

167:    Level: advanced

169: .keywords:  PC, KSP, get, context
170: @*/
171: PetscErrorCode  PCKSPGetKSP(PC pc,KSP *ksp)
172: {

178:   *ksp = NULL;
179:   PetscTryMethod(pc,"PCKSPGetKSP_C",(PC,KSP*),(pc,ksp));
180:   return(0);
181: }

183: /* ----------------------------------------------------------------------------------*/

185: /*MC
186:      PCKSP -    Defines a preconditioner that can consist of any KSP solver.
187:                  This allows, for example, embedding a Krylov method inside a preconditioner.

189:    Options Database Key:
190: .     -pc_use_amat - use the matrix that defines the linear system, Amat as the matrix for the
191:                     inner solver, otherwise by default it uses the matrix used to construct
192:                     the preconditioner, Pmat (see PCSetOperators())

194:    Level: intermediate

196:    Concepts: inner iteration

198:    Notes: Using a Krylov method inside another Krylov method can be dangerous (you get divergence or
199:           the incorrect answer) unless you use KSPFGMRES as the other Krylov method

201:    Developer Notes: If the outer Krylov method has a nonzero initial guess it will compute a new residual based on that initial guess
202:     and pass that as the right hand side into this KSP (and hence this KSP will always have a zero initial guess). For all outer Krylov methods
203:     except Richardson this is neccessary since Krylov methods, even the flexible ones, need to "see" the result of the action of the preconditioner on the
204:     input (current residual) vector, the action of the preconditioner cannot depend also on some other vector (the "initial guess"). For 
205:     KSPRICHARDSON it is possible to provide a PCApplyRichardson_PCKSP() that short circuits returning to the KSP object at each iteration to compute the 
206:     residual, see for example PCApplyRichardson_SOR(). We do not implement a PCApplyRichardson_PCKSP()  because (1) using a KSP directly inside a Richardson 
207:     is not an efficient algorithm anyways and (2) implementing it for its > 1 would essentially require that we implement Richardson (reimplementing the 
208:     Richardson code) inside the PCApplyRichardson_PCKSP() leading to duplicate code.

210: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
211:            PCSHELL, PCCOMPOSITE, PCSetUseAmat(), PCKSPGetKSP()

213: M*/

217: PETSC_EXTERN PetscErrorCode PCCreate_KSP(PC pc)
218: {
220:   PC_KSP         *jac;

223:   PetscNewLog(pc,&jac);

225:   pc->ops->apply           = PCApply_KSP;
226:   pc->ops->applytranspose  = PCApplyTranspose_KSP;
227:   pc->ops->setup           = PCSetUp_KSP;
228:   pc->ops->reset           = PCReset_KSP;
229:   pc->ops->destroy         = PCDestroy_KSP;
230:   pc->ops->setfromoptions  = 0;
231:   pc->ops->view            = PCView_KSP;
232:   pc->ops->applyrichardson = 0;

234:   pc->data = (void*)jac;


237:   jac->its             = 0;
238:   PetscObjectComposeFunction((PetscObject)pc,"PCKSPGetKSP_C",PCKSPGetKSP_KSP);
239:   return(0);
240: }