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