xref: /petsc/src/ksp/pc/impls/deflation/deflation.c (revision e53e0a0d0486bbcc0147c336cd92e1a6a50ba191)
1 
2 /*  --------------------------------------------------------------------
3 
4      This file implements a Deflation preconditioner in PETSc as part of PC.
5      You can use this as a starting point for implementing your own
6      preconditioner that is not provided with PETSc. (You might also consider
7      just using PCSHELL)
8 
9      The following basic routines are required for each preconditioner.
10           PCCreate_XXX()          - Creates a preconditioner context
11           PCSetFromOptions_XXX()  - Sets runtime options
12           PCApply_XXX()           - Applies the preconditioner
13           PCDestroy_XXX()         - Destroys the preconditioner context
14      where the suffix "_XXX" denotes a particular implementation, in
15      this case we use _Deflation (e.g., PCCreate_Deflation, PCApply_Deflation).
16      These routines are actually called via the common user interface
17      routines PCCreate(), PCSetFromOptions(), PCApply(), and PCDestroy(),
18      so the application code interface remains identical for all
19      preconditioners.
20 
21      Another key routine is:
22           PCSetUp_XXX()           - Prepares for the use of a preconditioner
23      by setting data structures and options.   The interface routine PCSetUp()
24      is not usually called directly by the user, but instead is called by
25      PCApply() if necessary.
26 
27      Additional basic routines are:
28           PCView_XXX()            - Prints details of runtime options that
29                                     have actually been used.
30      These are called by application codes via the interface routines
31      PCView().
32 
33      The various types of solvers (preconditioners, Krylov subspace methods,
34      nonlinear solvers, timesteppers) are all organized similarly, so the
35      above description applies to these categories also.  One exception is
36      that the analogues of PCApply() for these components are KSPSolve(),
37      SNESSolve(), and TSSolve().
38 
39      Additional optional functionality unique to preconditioners is left and
40      right symmetric preconditioner application via PCApplySymmetricLeft()
41      and PCApplySymmetricRight().  The Deflation implementation is
42      PCApplySymmetricLeftOrRight_Deflation().
43 
44     -------------------------------------------------------------------- */
45 
46 /*
47    Include files needed for the Deflation preconditioner:
48      pcimpl.h - private include file intended for use by all preconditioners
49 */
50 
51 #include <../src/ksp/pc/impls/deflation/deflation.h> /*I "petscpc.h" I*/  /* includes for fortran wrappers */
52 
53 const char *const PCDeflationTypes[]    = {"INIT","PRE","POST","PCDeflationType","PC_DEFLATION_",0};
54 
55 static PetscErrorCode PCDeflationSetSpace_Deflation(PC pc,Mat W,PetscBool transpose)
56 {
57   PC_Deflation   *def = (PC_Deflation*)pc->data;
58   PetscErrorCode ierr;
59 
60   PetscFunctionBegin;
61   if (transpose) {
62     def->Wt = W;
63     def->W = NULL;
64   } else {
65     def->W = W;
66   }
67   ierr = PetscObjectReference((PetscObject)W);CHKERRQ(ierr);
68   PetscFunctionReturn(0);
69 }
70 
71 /* TODO create PCDeflationSetSpaceTranspose? */
72 /*@
73    PCDeflationSetSpace - Set deflation space matrix (or its transpose).
74 
75    Logically Collective on PC
76 
77    Input Parameters:
78 +  pc - the preconditioner context
79 .  W  - deflation matrix
80 -  tranpose - indicates that W is an explicit transpose of the deflation matrix
81 
82    Level: intermediate
83 
84 .seealso: PCDEFLATION
85 @*/
86 PetscErrorCode PCDeflationSetSpace(PC pc,Mat W,PetscBool transpose)
87 {
88   PetscErrorCode ierr;
89 
90   PetscFunctionBegin;
91   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
92   PetscValidHeaderSpecific(W,MAT_CLASSID,2);
93   PetscValidLogicalCollectiveBool(pc,transpose,3);
94   ierr = PetscTryMethod(pc,"PCDeflationSetSpace_C",(PC,Mat,PetscBool),(pc,W,transpose));CHKERRQ(ierr);
95   PetscFunctionReturn(0);
96 }
97 
98 static PetscErrorCode PCDeflationSetLvl_Deflation(PC pc,PetscInt current,PetscInt max)
99 {
100   PC_Deflation   *def = (PC_Deflation*)pc->data;
101 
102   PetscFunctionBegin;
103   def->nestedlvl = current;
104   def->maxnestedlvl = max;
105   PetscFunctionReturn(0);
106 }
107 
108 /*@
109    PCDeflationSetMaxLvl - Set maximum level of deflation.
110 
111    Logically Collective on PC
112 
113    Input Parameters:
114 +  pc  - the preconditioner context
115 .  max - maximum deflation level
116 
117    Level: intermediate
118 
119 .seealso: PCDEFLATION
120 @*/
121 PetscErrorCode PCDeflationSetMaxLvl(PC pc,PetscInt max)
122 {
123   PetscErrorCode ierr;
124 
125   PetscFunctionBegin;
126   PetscValidLogicalCollectiveInt(pc,max,2);
127   ierr = PetscTryMethod(pc,"PCDeflationSetLvl_C",(PC,PetscInt,PetscInt),(pc,0,max));CHKERRQ(ierr);
128   PetscFunctionReturn(0);
129 }
130 
131 /*
132   TODO CP corection?
133   x <- x + W*(W'*A*W)^{-1}*W'*r  = x + Q*r
134 */
135 static PetscErrorCode PCPreSolve_Deflation(PC pc,KSP ksp,Vec b, Vec x)
136 {
137   PC_Deflation     *def = (PC_Deflation*)pc->data;
138   Mat              A;
139   Vec              r,w1,w2;
140   PetscBool        nonzero;
141   PetscErrorCode   ierr;
142 
143   PetscFunctionBegin;
144   w1 = def->workcoarse[0];
145   w2 = def->workcoarse[1];
146   r  = def->work;
147   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
148 
149   ierr = KSPGetInitialGuessNonzero(ksp,&nonzero);CHKERRQ(ierr);
150   ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
151   if (nonzero) {
152     ierr = MatMult(A,x,r);CHKERRQ(ierr);               /*    r  <- b - Ax              */
153     ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr);
154   } else {
155     ierr = VecCopy(b,r);CHKERRQ(ierr);                 /*    r  <- b (x is 0)          */
156   }
157 
158   ierr = MatMultTranspose(def->W,r,w1);CHKERRQ(ierr);  /*    w1 <- W'*r                */
159   ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);   /*    w2 <- (W'*A*W)^{-1}*w1    */
160   ierr = MatMult(def->W,w2,r);CHKERRQ(ierr);           /*    r  <- W*w2                */
161   ierr = VecAYPX(x,1.0,r);CHKERRQ(ierr);
162   PetscFunctionReturn(0);
163 }
164 
165 /*
166   if (def->correct) {
167     z <- r - W*(W'*A*W)^{-1}*W'*(A*r -r) = (P-Q)*r
168   } else {
169     z <- r - W*(W'*A*W)^{-1}*W'*A*r = P*r
170   }
171 */
172 static PetscErrorCode PCApply_Deflation(PC pc,Vec r, Vec z)
173 {
174   PC_Deflation     *def = (PC_Deflation*)pc->data;
175   Mat              A;
176   Vec              u,w1,w2;
177   PetscErrorCode   ierr;
178 
179   PetscFunctionBegin;
180   w1 = def->workcoarse[0];
181   w2 = def->workcoarse[1];
182   u  = def->work;
183   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
184 
185   if (!def->AW) {
186     ierr = MatMult(A,r,u);CHKERRQ(ierr);                       /*    u  <- A*r                 */
187     if (def->correct) ierr = VecAXPY(u,-1.0,r);CHKERRQ(ierr);  /*    u  <- A*r -r              */
188     ierr = MatMultTranspose(def->W,u,w1);CHKERRQ(ierr);        /*    w1 <- W'*u                */
189   } else {
190     ierr = MatMultTranspose(def->AW,u,w1);CHKERRQ(ierr);       /*    u  <- A*r                 */
191     if (def->correct) {
192       ierr = MatMultTranspose(def->W,r,w2);CHKERRQ(ierr);      /*    w2 <- W'*u                */
193       ierr = VecAXPY(w1,-1.0,w2);CHKERRQ(ierr);                /*    w1 <- w1 - w2             */
194     }
195   }
196   ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);           /*    w2 <- (W'*A*W)^{-1}*w1    */
197   ierr = MatMult(def->W,w2,u);CHKERRQ(ierr);                   /*    u  <- W*w2                */
198   ierr = VecWAXPY(z,-1.0,u,r);CHKERRQ(ierr);                   /*    z  <- r - u               */
199   PetscFunctionReturn(0);
200 }
201 
202 static PetscErrorCode  PCDeflationSetType_Deflation(PC pc,PCDeflationType type)
203 {
204   PC_Deflation *def = (PC_Deflation*)pc->data;
205 
206   PetscFunctionBegin;
207   def->init = PETSC_FALSE;
208   def->pre = PETSC_FALSE;
209   if (type == PC_DEFLATION_POST) {
210     //pc->ops->postsolve = PCPostSolve_Deflation;
211     pc->ops->presolve = 0;
212   } else {
213     pc->ops->presolve = PCPreSolve_Deflation;
214     pc->ops->postsolve = 0;
215     if (type == PC_DEFLATION_INIT) {
216       def->init = PETSC_TRUE;
217       pc->ops->apply = 0;
218     } else {
219       def->pre  = PETSC_TRUE;
220     }
221   }
222   PetscFunctionReturn(0);
223 }
224 
225 /*@
226    PCDeflationSetType - Causes the deflation preconditioner to use only a special
227     initial gues or pre/post solve solution update
228 
229    Logically Collective on PC
230 
231    Input Parameters:
232 +  pc - the preconditioner context
233 -  type - PC_DEFLATION_PRE, PC_DEFLATION_INIT, PC_DEFLATION_POST
234 
235    Options Database Key:
236 .  -pc_deflation_type <pre,init,post>
237 
238    Level: intermediate
239 
240    Concepts: Deflation preconditioner
241 
242 .seealso: PCDeflationGetType()
243 @*/
244 PetscErrorCode  PCDeflationSetType(PC pc,PCDeflationType type)
245 {
246   PetscErrorCode ierr;
247 
248   PetscFunctionBegin;
249   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
250   ierr = PetscTryMethod(pc,"PCDeflationSetType_C",(PC,PCDeflationType),(pc,type));CHKERRQ(ierr);
251   PetscFunctionReturn(0);
252 }
253 
254 static PetscErrorCode  PCDeflationGetType_Deflation(PC pc,PCDeflationType *type)
255 {
256   PC_Deflation *def = (PC_Deflation*)pc->data;
257 
258   PetscFunctionBegin;
259   if (def->init) {
260     *type = PC_DEFLATION_INIT;
261   } else if (def->pre) {
262     *type = PC_DEFLATION_PRE;
263   } else {
264     *type = PC_DEFLATION_POST;
265   }
266   PetscFunctionReturn(0);
267 }
268 
269 /*@
270    PCDeflationGetType - Gets how the diagonal matrix is produced for the preconditioner
271 
272    Not Collective on PC
273 
274    Input Parameter:
275 .  pc - the preconditioner context
276 
277    Output Parameter:
278 -  type - PC_DEFLATION_PRE, PC_DEFLATION_INIT, PC_DEFLATION_POST
279 
280    Level: intermediate
281 
282    Concepts: Deflation preconditioner
283 
284 .seealso: PCDeflationSetType()
285 @*/
286 PetscErrorCode  PCDeflationGetType(PC pc,PCDeflationType *type)
287 {
288   PetscErrorCode ierr;
289 
290   PetscFunctionBegin;
291   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
292   ierr = PetscUseMethod(pc,"PCDeflationGetType_C",(PC,PCDeflationType*),(pc,type));CHKERRQ(ierr);
293   PetscFunctionReturn(0);
294 }
295 
296 static PetscErrorCode PCSetUp_Deflation(PC pc)
297 {
298   PC_Deflation     *def = (PC_Deflation*)pc->data;
299   KSP              innerksp;
300   PC               pcinner;
301   Mat              Amat,nextDef=NULL,*mats;
302   PetscInt         i,m,red,size,commsize;
303   PetscBool        match,flgspd,transp=PETSC_FALSE;
304   MatCompositeType ctype;
305   MPI_Comm         comm;
306   const char       *prefix;
307   PetscErrorCode   ierr;
308 
309   PetscFunctionBegin;
310   if (pc->setupcalled) PetscFunctionReturn(0);
311   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
312   ierr = PCGetOperators(pc,NULL,&Amat);CHKERRQ(ierr);
313 
314   /* compute a deflation space */
315   if (def->W || def->Wt) {
316     def->spacetype = PC_DEFLATION_SPACE_USER;
317   } else {
318     ierr = PCDeflationComputeSpace(pc);CHKERRQ(ierr);
319   }
320 
321   /* nested deflation */
322   if (def->W) {
323     ierr = PetscObjectTypeCompare((PetscObject)def->W,MATCOMPOSITE,&match);CHKERRQ(ierr);
324     if (match) {
325       ierr = MatCompositeGetType(def->W,&ctype);CHKERRQ(ierr);
326       ierr = MatCompositeGetNumberMat(def->W,&size);CHKERRQ(ierr);
327     }
328   } else {
329     ierr = MatCreateTranspose(def->Wt,&def->W);CHKERRQ(ierr);
330     ierr = PetscObjectTypeCompare((PetscObject)def->Wt,MATCOMPOSITE,&match);CHKERRQ(ierr);
331     if (match) {
332       ierr = MatCompositeGetType(def->Wt,&ctype);CHKERRQ(ierr);
333       ierr = MatCompositeGetNumberMat(def->Wt,&size);CHKERRQ(ierr);
334     }
335     transp = PETSC_TRUE;
336   }
337   if (match && ctype == MAT_COMPOSITE_MULTIPLICATIVE) {
338     ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
339     if (!transp) {
340       for (i=0; i<size; i++) {
341         ierr = MatCompositeGetMat(def->W,i,&mats[i]);CHKERRQ(ierr);
342         //ierr = PetscObjectReference((PetscObject)mats[i]);CHKERRQ(ierr);
343       }
344       if (def->nestedlvl < def->maxnestedlvl) {
345         size -= 1;
346         ierr = MatDestroy(&def->W);CHKERRQ(ierr);
347         def->W = mats[size];
348         ierr = PetscObjectReference((PetscObject)mats[size]);CHKERRQ(ierr);
349         if (size > 1) {
350           ierr = MatCreateComposite(comm,size,mats,&nextDef);CHKERRQ(ierr);
351           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
352         } else {
353           nextDef = mats[0];
354           ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
355         }
356       } else {
357         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
358         ierr = MatCompositeMerge(def->W);CHKERRQ(ierr);
359       }
360     }
361     ierr = PetscFree(mats);CHKERRQ(ierr);
362   }
363 
364   /* setup coarse problem */
365   if (!def->WtAWinv) {
366     ierr = MatGetSize(def->W,NULL,&m);CHKERRQ(ierr); /* TODO works for W MatTranspose? */
367     if (!def->WtAW) {
368       /* TODO add implicit product version ? */
369       if (!def->AW) {
370         ierr = MatPtAP(Amat,def->W,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr);
371       } else {
372         ierr = MatTransposeMatMult(def->W,def->AW,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr);
373       }
374       /* TODO create MatInheritOption(Mat,MatOption) */
375       ierr = MatGetOption(Amat,MAT_SPD,&flgspd);CHKERRQ(ierr);
376       ierr = MatSetOption(def->WtAW,MAT_SPD,flgspd);CHKERRQ(ierr);
377 #if defined(PETSC_USE_DEBUG)
378       /* Check WtAW is not sigular */
379       PetscReal *norms;
380       ierr = PetscMalloc1(m,&norms);CHKERRQ(ierr);
381       ierr = MatGetColumnNorms(def->WtAW,NORM_INFINITY,norms);CHKERRQ(ierr);
382       for (i=0; i<m; i++) {
383         if (norms[i] < 100*PETSC_MACHINE_EPSILON) {
384           SETERRQ1(comm,PETSC_ERR_SUP,"Column %D of W is in kernel of A.",i);
385         }
386       }
387       ierr = PetscFree(norms);CHKERRQ(ierr);
388 #endif
389     } else {
390       ierr = MatGetOption(def->WtAW,MAT_SPD,&flgspd);CHKERRQ(ierr);
391     }
392     /* TODO use MATINV */
393     ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
394     ierr = KSPCreate(comm,&def->WtAWinv);CHKERRQ(ierr);
395     ierr = KSPSetOperators(def->WtAWinv,def->WtAW,def->WtAW);CHKERRQ(ierr);
396     ierr = KSPSetType(def->WtAWinv,KSPPREONLY);CHKERRQ(ierr);
397     ierr = KSPGetPC(def->WtAWinv,&pcinner);CHKERRQ(ierr);
398     ierr = PCSetType(pcinner,PCTELESCOPE);CHKERRQ(ierr);
399     /* ugly hack to not have overwritten PCTELESCOPE */
400     if (prefix) {
401       ierr = KSPSetOptionsPrefix(def->WtAWinv,prefix);CHKERRQ(ierr);
402       ierr = KSPAppendOptionsPrefix(def->WtAWinv,"tel_");CHKERRQ(ierr);
403     } else {
404       ierr = KSPSetOptionsPrefix(def->WtAWinv,"tel_");CHKERRQ(ierr);
405     }
406     ierr = PCSetFromOptions(pcinner);CHKERRQ(ierr);
407     /* Reduction factor choice */
408     red = def->reductionfact;
409     if (red < 0) {
410       ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
411       red  = ceil((float)commsize/ceil((float)m/commsize));
412       ierr = PetscObjectTypeCompareAny((PetscObject)(def->WtAW),&match,MATSEQDENSE,MATMPIDENSE,MATDENSE,"");CHKERRQ(ierr);
413       if (match) red = commsize;
414       ierr = PetscInfo1(pc,"Auto choosing reduction factor %D\n",red);CHKERRQ(ierr); /* TODO add level? */
415     }
416     ierr = PCTelescopeSetReductionFactor(pcinner,red);CHKERRQ(ierr);
417     ierr = PCSetUp(pcinner);CHKERRQ(ierr);
418     ierr = PCTelescopeGetKSP(pcinner,&innerksp);CHKERRQ(ierr);
419     if (innerksp) {
420       ierr = KSPGetPC(innerksp,&pcinner);CHKERRQ(ierr);
421       /* Setup KSP and PC */
422       if (nextDef) { /* next level for multilevel deflation */
423         /* set default KSPtype */
424         if (!def->ksptype) {
425           def->ksptype = KSPFGMRES;
426           if (flgspd) { /* SPD system */
427             def->ksptype = KSPFCG;
428           }
429         }
430         ierr = KSPSetType(innerksp,def->ksptype);CHKERRQ(ierr); /* TODO iherit from KSP */
431         ierr = PCSetType(pcinner,PCDEFLATION);CHKERRQ(ierr); /* TODO create coarse preconditinoner M_c = WtMW ? */
432         ierr = PCDeflationSetSpace(pcinner,nextDef,transp);CHKERRQ(ierr);
433         ierr = PCDeflationSetLvl_Deflation(pcinner,def->nestedlvl+1,def->maxnestedlvl);CHKERRQ(ierr);
434         /* inherit options TODO if not set */
435         ((PC_Deflation*)(pcinner))->ksptype = def->ksptype;
436         ((PC_Deflation*)(pcinner))->correct = def->correct;
437         ((PC_Deflation*)(pcinner))->adaptiveconv = def->adaptiveconv;
438         ((PC_Deflation*)(pcinner))->adaptiveconst = def->adaptiveconst;
439         ierr = MatDestroy(&nextDef);CHKERRQ(ierr);
440       } else { /* the last level */
441         ierr = KSPSetType(innerksp,KSPGMRES);CHKERRQ(ierr);
442         /* TODO Cholesky if flgspd? */
443         ierr = PCSetType(pcinner,PCLU);CHKERRQ(ierr);
444         //TODO remove explicit matSolverPackage
445         if (commsize == red) {
446           ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU);CHKERRQ(ierr);
447         } else {
448           ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU_DIST);CHKERRQ(ierr);
449         }
450       }
451       /* TODO use def_[lvl]_ if lvl > 0? */
452       if (prefix) {
453         ierr = KSPSetOptionsPrefix(innerksp,prefix);CHKERRQ(ierr);
454         ierr = KSPAppendOptionsPrefix(innerksp,"def_");CHKERRQ(ierr);
455       } else {
456         ierr = KSPSetOptionsPrefix(innerksp,"def_");CHKERRQ(ierr);
457       }
458     }
459     /* TODO: check if WtAWinv is KSP and move following from this if */
460     ierr = KSPSetFromOptions(def->WtAWinv);CHKERRQ(ierr);
461     //if (def->adaptiveconv) {
462     //  PetscReal *rnorm;
463     //  PetscNew(&rnorm);
464     //  ierr = KSPSetConvergenceTest(def->WtAWinv,KSPDCGConvergedAdaptive_DCG,rnorm,NULL);CHKERRQ(ierr);
465     //}
466     ierr = KSPSetUp(def->WtAWinv);CHKERRQ(ierr);
467   }
468 
469   /* create work vecs */
470   ierr = MatCreateVecs(Amat,NULL,&def->work);CHKERRQ(ierr);
471   ierr = KSPCreateVecs(def->WtAWinv,2,&def->workcoarse,0,NULL);CHKERRQ(ierr);
472   PetscFunctionReturn(0);
473 }
474 /* -------------------------------------------------------------------------- */
475 static PetscErrorCode PCReset_Deflation(PC pc)
476 {
477   PC_Deflation      *jac = (PC_Deflation*)pc->data;
478   PetscErrorCode ierr;
479 
480   PetscFunctionBegin;
481   PetscFunctionReturn(0);
482 }
483 
484 /*
485    PCDestroy_Deflation - Destroys the private context for the Deflation preconditioner
486    that was created with PCCreate_Deflation().
487 
488    Input Parameter:
489 .  pc - the preconditioner context
490 
491    Application Interface Routine: PCDestroy()
492 */
493 static PetscErrorCode PCDestroy_Deflation(PC pc)
494 {
495   PetscErrorCode ierr;
496 
497   PetscFunctionBegin;
498   ierr = PCReset_Deflation(pc);CHKERRQ(ierr);
499 
500   /*
501       Free the private data structure that was hanging off the PC
502   */
503   ierr = PetscFree(pc->data);CHKERRQ(ierr);
504   PetscFunctionReturn(0);
505 }
506 
507 static PetscErrorCode PCSetFromOptions_Deflation(PetscOptionItems *PetscOptionsObject,PC pc)
508 {
509   PC_Deflation      *jac = (PC_Deflation*)pc->data;
510   PetscErrorCode ierr;
511   PetscBool      flg;
512   PCDeflationType   deflt,type;
513 
514   PetscFunctionBegin;
515   ierr = PCDeflationGetType(pc,&deflt);CHKERRQ(ierr);
516   ierr = PetscOptionsHead(PetscOptionsObject,"Deflation options");CHKERRQ(ierr);
517   ierr = PetscOptionsEnum("-pc_jacobi_type","How to construct diagonal matrix","PCDeflationSetType",PCDeflationTypes,(PetscEnum)deflt,(PetscEnum*)&type,&flg);CHKERRQ(ierr);
518   if (flg) {
519     ierr = PCDeflationSetType(pc,type);CHKERRQ(ierr);
520   }
521   ierr = PetscOptionsTail();CHKERRQ(ierr);
522   PetscFunctionReturn(0);
523 }
524 
525 /*MC
526      PCDEFLATION - Deflation preconditioner shifts part of the spectrum to zero (deflates)
527      or to a predefined value
528 
529    Options Database Key:
530 +    -pc_deflation_type <init,pre,post> - selects approach to deflation (default: pre)
531 -    -pc_jacobi_abs - use the absolute value of the diagonal entry
532 
533    Level: beginner
534 
535   Notes:
536     todo
537 
538 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
539            PCDeflationSetType(), PCDeflationSetSpace()
540 M*/
541 
542 PETSC_EXTERN PetscErrorCode PCCreate_Deflation(PC pc)
543 {
544   PC_Deflation   *def;
545   PetscErrorCode ierr;
546 
547   PetscFunctionBegin;
548   ierr     = PetscNewLog(pc,&def);CHKERRQ(ierr);
549   pc->data = (void*)def;
550 
551   def->init          = PETSC_FALSE;
552   def->pre           = PETSC_TRUE;
553   def->correct       = PETSC_FALSE;
554   def->truenorm      = PETSC_TRUE;
555   def->reductionfact = -1;
556   def->spacetype     = PC_DEFLATION_SPACE_HAAR;
557   def->spacesize     = 1;
558   def->extendsp      = PETSC_FALSE;
559   def->nestedlvl     = 0;
560   def->maxnestedlvl  = 0;
561   def->adaptiveconv  = PETSC_FALSE;
562   def->adaptiveconst = 1.0;
563 
564   /*
565       Set the pointers for the functions that are provided above.
566       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
567       are called, they will automatically call these functions.  Note we
568       choose not to provide a couple of these functions since they are
569       not needed.
570   */
571   pc->ops->apply               = PCApply_Deflation;
572   pc->ops->applytranspose      = PCApply_Deflation;
573   pc->ops->presolve            = PCPreSolve_Deflation;
574   pc->ops->postsolve           = 0;
575   pc->ops->setup               = PCSetUp_Deflation;
576   pc->ops->reset               = PCReset_Deflation;
577   pc->ops->destroy             = PCDestroy_Deflation;
578   pc->ops->setfromoptions      = PCSetFromOptions_Deflation;
579   pc->ops->view                = 0;
580   pc->ops->applyrichardson     = 0;
581   pc->ops->applysymmetricleft  = 0;
582   pc->ops->applysymmetricright = 0;
583 
584   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetType_C",PCDeflationSetType_Deflation);CHKERRQ(ierr);
585   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetType_C",PCDeflationGetType_Deflation);CHKERRQ(ierr);
586   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpace_C",PCDeflationSetSpace_Deflation);CHKERRQ(ierr);
587   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetLvl_C",PCDeflationSetLvl_Deflation);CHKERRQ(ierr);
588   PetscFunctionReturn(0);
589 }
590 
591