xref: /petsc/src/ksp/pc/impls/deflation/deflation.c (revision fcb31d998e9a4b4c0e7669003213f8c0db327f88)
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 PCDeflationSpaceTypes[] = {
54   "haar",
55   "jacket-haar",
56   "db2",
57   "db4",
58   "db8",
59   "db16",
60   "biorth22",
61   "meyer",
62   "aggregation",
63   "slepc",
64   "slepc-cheap",
65   "user",
66   "DdefSpaceType",
67   "Ddef_SPACE_",
68   0
69 };
70 
71 
72 static PetscErrorCode PCDeflationSetSpace_Deflation(PC pc,Mat W,PetscBool transpose)
73 {
74   PC_Deflation   *def = (PC_Deflation*)pc->data;
75   PetscErrorCode ierr;
76 
77   PetscFunctionBegin;
78   if (transpose) {
79     def->Wt = W;
80     def->W = NULL;
81   } else {
82     def->W = W;
83   }
84   ierr = PetscObjectReference((PetscObject)W);CHKERRQ(ierr);
85   PetscFunctionReturn(0);
86 }
87 
88 /* TODO create PCDeflationSetSpaceTranspose? */
89 /*@
90    PCDeflationSetSpace - Set deflation space matrix (or its transpose).
91 
92    Logically Collective on PC
93 
94    Input Parameters:
95 +  pc - the preconditioner context
96 .  W  - deflation matrix
97 -  tranpose - indicates that W is an explicit transpose of the deflation matrix
98 
99    Level: intermediate
100 
101 .seealso: PCDEFLATION
102 @*/
103 PetscErrorCode PCDeflationSetSpace(PC pc,Mat W,PetscBool transpose)
104 {
105   PetscErrorCode ierr;
106 
107   PetscFunctionBegin;
108   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
109   PetscValidHeaderSpecific(W,MAT_CLASSID,2);
110   PetscValidLogicalCollectiveBool(pc,transpose,3);
111   ierr = PetscTryMethod(pc,"PCDeflationSetSpace_C",(PC,Mat,PetscBool),(pc,W,transpose));CHKERRQ(ierr);
112   PetscFunctionReturn(0);
113 }
114 
115 static PetscErrorCode PCDeflationSetLvl_Deflation(PC pc,PetscInt current,PetscInt max)
116 {
117   PC_Deflation   *def = (PC_Deflation*)pc->data;
118 
119   PetscFunctionBegin;
120   if (current) def->nestedlvl = current;
121   def->maxnestedlvl = max;
122   PetscFunctionReturn(0);
123 }
124 
125 /*@
126    PCDeflationSetMaxLvl - Set maximum level of deflation.
127 
128    Logically Collective on PC
129 
130    Input Parameters:
131 +  pc  - the preconditioner context
132 -  max - maximum deflation level
133 
134    Level: intermediate
135 
136 .seealso: PCDEFLATION
137 @*/
138 PetscErrorCode PCDeflationSetMaxLvl(PC pc,PetscInt max)
139 {
140   PetscErrorCode ierr;
141 
142   PetscFunctionBegin;
143   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
144   PetscValidLogicalCollectiveInt(pc,max,2);
145   ierr = PetscTryMethod(pc,"PCDeflationSetLvl_C",(PC,PetscInt,PetscInt),(pc,0,max));CHKERRQ(ierr);
146   PetscFunctionReturn(0);
147 }
148 
149 static PetscErrorCode PCDeflationSetPC_Deflation(PC pc,PC apc)
150 {
151   PC_Deflation   *def = (PC_Deflation*)pc->data;
152   PetscErrorCode ierr;
153 
154   PetscFunctionBegin;
155   ierr = PCDestroy(&def->pc);CHKERRQ(ierr);
156   def->pc = apc;
157   ierr = PetscObjectReference((PetscObject)apc);CHKERRQ(ierr);
158   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->pc);CHKERRQ(ierr);
159   PetscFunctionReturn(0);
160 }
161 
162 /*@
163    PCDeflationSetPC - Set additional preconditioner.
164 
165    Logically Collective on PC
166 
167    Input Parameters:
168 +  pc  - the preconditioner context
169 -  apc - additional preconditioner
170 
171    Level: advanced
172 
173 .seealso: PCDEFLATION
174 @*/
175 PetscErrorCode PCDeflationSetPC(PC pc,PC apc)
176 {
177   PetscErrorCode ierr;
178 
179   PetscFunctionBegin;
180   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
181   PetscValidHeaderSpecific(apc,PC_CLASSID,2);
182   PetscCheckSameComm(pc,1,apc,2);
183   ierr = PetscTryMethod(pc,"PCDeflationSetPC_C",(PC,PC),(pc,apc));CHKERRQ(ierr);
184   PetscFunctionReturn(0);
185 }
186 
187 static PetscErrorCode PCDeflationGetCoarseKSP_Deflation(PC pc,KSP *ksp)
188 {
189   PC_Deflation     *def = (PC_Deflation*)pc->data;
190 
191   PetscFunctionBegin;
192   *ksp = def->WtAWinv;
193   PetscFunctionReturn(0);
194 }
195 
196 /*@
197    PCDeflationGetCoarseKSP - Returns a pointer to the coarse problem KSP.
198 
199    Not Collective
200 
201    Input Parameters:
202 .  pc - preconditioner context
203 
204    Output Parameter:
205 .  ksp - coarse problem KSP context
206 
207    Level: developer
208 
209 .seealso: PCDEFLATION
210 @*/
211 PetscErrorCode  PCDeflationGetCoarseKSP(PC pc,KSP *ksp)
212 {
213   PetscErrorCode ierr;
214 
215   PetscFunctionBegin;
216   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
217   PetscValidPointer(ksp,2);
218   ierr = PetscTryMethod(pc,"PCDeflationGetCoarseKSP_C",(PC,KSP*),(pc,ksp));CHKERRQ(ierr);
219   PetscFunctionReturn(0);
220 }
221 
222 /*
223   x <- x + W*(W'*A*W)^{-1}*W'*r  = x + Q*r
224 */
225 static PetscErrorCode PCPreSolve_Deflation(PC pc,KSP ksp,Vec b, Vec x)
226 {
227   PC_Deflation     *def = (PC_Deflation*)pc->data;
228   Mat              A;
229   Vec              r,w1,w2;
230   PetscBool        nonzero;
231   PetscErrorCode   ierr;
232 
233   PetscFunctionBegin;
234   w1 = def->workcoarse[0];
235   w2 = def->workcoarse[1];
236   r  = def->work;
237   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
238 
239   ierr = KSPGetInitialGuessNonzero(ksp,&nonzero);CHKERRQ(ierr);
240   ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
241   if (nonzero) {
242     ierr = MatMult(A,x,r);CHKERRQ(ierr);               /*    r  <- b - Ax              */
243     ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr);
244   } else {
245     ierr = VecCopy(b,r);CHKERRQ(ierr);                 /*    r  <- b (x is 0)          */
246   }
247 
248   ierr = MatMultTranspose(def->W,r,w1);CHKERRQ(ierr);  /*    w1 <- W'*r                */
249   ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);   /*    w2 <- (W'*A*W)^{-1}*w1    */
250   ierr = MatMult(def->W,w2,r);CHKERRQ(ierr);           /*    r  <- W*w2                */
251   ierr = VecAYPX(x,1.0,r);CHKERRQ(ierr);
252   PetscFunctionReturn(0);
253 }
254 
255 /*
256   if (def->correct) {
257     z <- r - W*(W'*A*W)^{-1}*W'*(A*r -r) = (P-Q)*M^{-1}*r
258   } else {
259     z <- r - W*(W'*A*W)^{-1}*W'*A*r = P*M^{-1}*r
260   }
261 */
262 static PetscErrorCode PCApply_Deflation(PC pc,Vec r,Vec z)
263 {
264   PC_Deflation     *def = (PC_Deflation*)pc->data;
265   Mat              A;
266   Vec              u,w1,w2;
267   PetscErrorCode   ierr;
268 
269   PetscFunctionBegin;
270   w1 = def->workcoarse[0];
271   w2 = def->workcoarse[1];
272   u  = def->work;
273   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
274 
275   ierr = PCApply(def->pc,r,z);CHKERRQ(ierr);
276   if (!def->init) {
277     if (!def->AW) {
278       ierr = MatMult(A,z,u);CHKERRQ(ierr);                                        /*    u  <- A*z                 */
279       if (def->correct) ierr = VecAXPY(u,-1.0*def->correctfact,z);CHKERRQ(ierr);  /*    u  <- A*z -z              */
280       ierr = MatMultTranspose(def->W,u,w1);CHKERRQ(ierr);                         /*    w1 <- W'*u                */
281     } else {
282       /* ONLY if A SYM */
283       ierr = MatMultTranspose(def->AW,z,w1);CHKERRQ(ierr);                        /*    w1  <- W'*A*r             */
284       if (def->correct) {
285         ierr = MatMultTranspose(def->W,z,w2);CHKERRQ(ierr);                       /*    w2 <- W'*u                */
286         ierr = VecAXPY(w1,-1.0*def->correctfact,w2);CHKERRQ(ierr);                /*    w1 <- w1 - w2             */
287       }
288     }
289     ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);                            /*    w2 <- (W'*A*W)^{-1}*w1    */
290     ierr = MatMult(def->W,w2,u);CHKERRQ(ierr);                                    /*    u  <- W*w2                */
291     ierr = VecAXPY(z,-1.0,u);CHKERRQ(ierr);                                       /*    z  <- z - u               */
292   }
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     if (!transp) {
339       if (def->nestedlvl < def->maxnestedlvl) {
340         ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
341         for (i=0; i<size; i++) {
342           ierr = MatCompositeGetMat(def->W,i,&mats[i]);CHKERRQ(ierr);
343         }
344         size -= 1;
345         ierr = MatDestroy(&def->W);CHKERRQ(ierr);
346         def->W = mats[size];
347         ierr = PetscObjectReference((PetscObject)mats[size]);CHKERRQ(ierr);
348         if (size > 1) {
349           ierr = MatCreateComposite(comm,size,mats,&nextDef);CHKERRQ(ierr);
350           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
351         } else {
352           nextDef = mats[0];
353           ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
354         }
355         ierr = PetscFree(mats);CHKERRQ(ierr);
356       } else {
357         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
358         ierr = MatCompositeMerge(def->W);CHKERRQ(ierr);
359       }
360     } else {
361       if (def->nestedlvl < def->maxnestedlvl) {
362         ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
363         for (i=0; i<size; i++) {
364           ierr = MatCompositeGetMat(def->Wt,i,&mats[i]);CHKERRQ(ierr);
365         }
366         size -= 1;
367         ierr = MatDestroy(&def->Wt);CHKERRQ(ierr);
368         def->Wt = mats[0];
369         ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
370         if (size > 1) {
371           ierr = MatCreateComposite(comm,size,&mats[1],&nextDef);CHKERRQ(ierr);
372           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
373         } else {
374           nextDef = mats[1];
375           ierr = PetscObjectReference((PetscObject)mats[1]);CHKERRQ(ierr);
376         }
377         ierr = PetscFree(mats);CHKERRQ(ierr);
378       } else {
379         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
380         ierr = MatCompositeMerge(def->Wt);CHKERRQ(ierr);
381       }
382     }
383   }
384 
385   if (transp) {
386     ierr = MatDestroy(&def->W);CHKERRQ(ierr);
387     ierr = MatTranspose(def->Wt,MAT_INITIAL_MATRIX,&def->W);CHKERRQ(ierr);
388   }
389 
390 
391   ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
392 
393   /* setup coarse problem */
394   if (!def->WtAWinv) {
395     ierr = MatGetSize(def->W,NULL,&m);CHKERRQ(ierr);
396     if (!def->WtAW) {
397       /* TODO add implicit product version ? */
398       if (!def->AW) {
399         ierr = MatPtAP(Amat,def->W,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr);
400       } else {
401         ierr = MatTransposeMatMult(def->W,def->AW,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr);
402       }
403       /* TODO create MatInheritOption(Mat,MatOption) */
404       ierr = MatGetOption(Amat,MAT_SPD,&flgspd);CHKERRQ(ierr);
405       ierr = MatSetOption(def->WtAW,MAT_SPD,flgspd);CHKERRQ(ierr);
406 #if defined(PETSC_USE_DEBUG)
407       /* Check WtAW is not sigular */
408       PetscReal *norms;
409       ierr = PetscMalloc1(m,&norms);CHKERRQ(ierr);
410       ierr = MatGetColumnNorms(def->WtAW,NORM_INFINITY,norms);CHKERRQ(ierr);
411       for (i=0; i<m; i++) {
412         if (norms[i] < 100*PETSC_MACHINE_EPSILON) {
413           SETERRQ1(comm,PETSC_ERR_SUP,"Column %D of W is in kernel of A.",i);
414         }
415       }
416       ierr = PetscFree(norms);CHKERRQ(ierr);
417 #endif
418     } else {
419       ierr = MatGetOption(def->WtAW,MAT_SPD,&flgspd);CHKERRQ(ierr);
420     }
421     /* TODO use MATINV */
422     ierr = KSPCreate(comm,&def->WtAWinv);CHKERRQ(ierr);
423     ierr = KSPSetOperators(def->WtAWinv,def->WtAW,def->WtAW);CHKERRQ(ierr);
424     ierr = KSPGetPC(def->WtAWinv,&pcinner);CHKERRQ(ierr);
425     /* Setup KSP and PC */
426     if (nextDef) { /* next level for multilevel deflation */
427       innerksp = def->WtAWinv;
428       /* set default KSPtype */
429       if (!def->ksptype) {
430         def->ksptype = KSPFGMRES;
431         if (flgspd) { /* SPD system */
432           def->ksptype = KSPFCG;
433         }
434       }
435       ierr = KSPSetType(innerksp,def->ksptype);CHKERRQ(ierr); /* TODO iherit from KSP */
436       ierr = PCSetType(pcinner,PCDEFLATION);CHKERRQ(ierr); /* TODO create coarse preconditinoner M_c = WtMW ? */
437       ierr = PCDeflationSetSpace(pcinner,nextDef,transp);CHKERRQ(ierr);
438       ierr = PCDeflationSetLvl_Deflation(pcinner,def->nestedlvl+1,def->maxnestedlvl);CHKERRQ(ierr);
439       /* inherit options TODO if not set */
440       ((PC_Deflation*)(pcinner->data))->ksptype = def->ksptype;
441       ((PC_Deflation*)(pcinner->data))->correct = def->correct;
442       ierr = MatDestroy(&nextDef);CHKERRQ(ierr);
443     } else { /* the last level */
444       ierr = KSPSetType(def->WtAWinv,KSPPREONLY);CHKERRQ(ierr);
445       ierr = PCSetType(pcinner,PCTELESCOPE);CHKERRQ(ierr);
446       /* ugly hack to not have overwritten PCTELESCOPE */
447       if (prefix) {
448         ierr = KSPSetOptionsPrefix(def->WtAWinv,prefix);CHKERRQ(ierr);
449       }
450       ierr = KSPAppendOptionsPrefix(def->WtAWinv,"tel_");CHKERRQ(ierr);
451       ierr = PCSetFromOptions(pcinner);CHKERRQ(ierr);
452       /* Reduction factor choice */
453       red = def->reductionfact;
454       if (red < 0) {
455         ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
456         red  = ceil((float)commsize/ceil((float)m/commsize));
457         ierr = PetscObjectTypeCompareAny((PetscObject)(def->WtAW),&match,MATSEQDENSE,MATMPIDENSE,MATDENSE,"");CHKERRQ(ierr);
458         if (match) red = commsize;
459         ierr = PetscInfo1(pc,"Auto choosing reduction factor %D\n",red);CHKERRQ(ierr); /* TODO add level? */
460       }
461       ierr = PCTelescopeSetReductionFactor(pcinner,red);CHKERRQ(ierr);
462       ierr = PCSetUp(pcinner);CHKERRQ(ierr);
463       ierr = PCTelescopeGetKSP(pcinner,&innerksp);CHKERRQ(ierr);
464       if (innerksp) {
465         ierr = KSPGetPC(innerksp,&pcinner);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     }
476 
477     if (innerksp) {
478       /* TODO use def_[lvl]_ if lvl > 0? */
479       if (prefix) {
480         ierr = KSPSetOptionsPrefix(innerksp,prefix);CHKERRQ(ierr);
481       }
482       ierr = KSPAppendOptionsPrefix(innerksp,"def_");CHKERRQ(ierr);
483       ierr = KSPSetFromOptions(innerksp);CHKERRQ(ierr);
484       ierr = KSPSetUp(innerksp);CHKERRQ(ierr);
485     }
486   }
487   ierr = KSPSetFromOptions(def->WtAWinv);CHKERRQ(ierr);
488   ierr = KSPSetUp(def->WtAWinv);CHKERRQ(ierr);
489 
490   if (!def->pc) {
491     ierr = PCCreate(comm,&def->pc);CHKERRQ(ierr);
492     ierr = PCSetOperators(def->pc,Amat,Amat);CHKERRQ(ierr);
493     ierr = PCSetType(def->pc,PCNONE);CHKERRQ(ierr);
494     if (prefix) {
495       ierr = PCSetOptionsPrefix(def->pc,prefix);CHKERRQ(ierr);
496     }
497     ierr = PCAppendOptionsPrefix(def->pc,"def_pc_");CHKERRQ(ierr);
498     ierr = PCSetFromOptions(def->pc);CHKERRQ(ierr);
499     ierr = PCSetUp(def->pc);CHKERRQ(ierr);
500   }
501 
502   /* create work vecs */
503   ierr = MatCreateVecs(Amat,NULL,&def->work);CHKERRQ(ierr);
504   ierr = KSPCreateVecs(def->WtAWinv,2,&def->workcoarse,0,NULL);CHKERRQ(ierr);
505   PetscFunctionReturn(0);
506 }
507 
508 static PetscErrorCode PCReset_Deflation(PC pc)
509 {
510   PC_Deflation      *def = (PC_Deflation*)pc->data;
511   PetscErrorCode    ierr;
512 
513   PetscFunctionBegin;
514   ierr = VecDestroy(&def->work);CHKERRQ(ierr);
515   ierr = VecDestroyVecs(2,&def->workcoarse);CHKERRQ(ierr);
516   ierr = MatDestroy(&def->W);CHKERRQ(ierr);
517   ierr = MatDestroy(&def->Wt);CHKERRQ(ierr);
518   ierr = MatDestroy(&def->AW);CHKERRQ(ierr);
519   ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr);
520   ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr);
521   ierr = PCDestroy(&def->pc);CHKERRQ(ierr);
522   PetscFunctionReturn(0);
523 }
524 
525 /*
526    PCDestroy_Deflation - Destroys the private context for the Deflation preconditioner
527    that was created with PCCreate_Deflation().
528 
529    Input Parameter:
530 .  pc - the preconditioner context
531 
532    Application Interface Routine: PCDestroy()
533 */
534 static PetscErrorCode PCDestroy_Deflation(PC pc)
535 {
536   PetscErrorCode ierr;
537 
538   PetscFunctionBegin;
539   ierr = PCReset_Deflation(pc);CHKERRQ(ierr);
540   ierr = PetscFree(pc->data);CHKERRQ(ierr);
541   PetscFunctionReturn(0);
542 }
543 
544 static PetscErrorCode PCView_Deflation(PC pc,PetscViewer viewer)
545 {
546   PC_Deflation      *def = (PC_Deflation*)pc->data;
547   PetscBool         iascii;
548   PetscErrorCode    ierr;
549 
550   PetscFunctionBegin;
551   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
552   if (iascii) {
553     //if (cg->adaptiveconv) {
554     //  ierr = PetscViewerASCIIPrintf(viewer,"  DCG: using adaptive precision for inner solve with C=%.1e\n",cg->adaptiveconst);CHKERRQ(ierr);
555     //}
556     if (def->correct) {
557       ierr = PetscViewerASCIIPrintf(viewer,"  Using CP correction\n");CHKERRQ(ierr);
558     }
559     if (!def->nestedlvl) {
560       ierr = PetscViewerASCIIPrintf(viewer,"  Deflation space type: %s\n",PCDeflationSpaceTypes[def->spacetype]);CHKERRQ(ierr);
561       ierr = PetscViewerASCIIPrintf(viewer,"  DCG %s\n",def->extendsp ? "extended" : "truncated");CHKERRQ(ierr);
562     }
563 
564     ierr = PetscViewerASCIIPrintf(viewer,"--- Additional PC\n");CHKERRQ(ierr);
565     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
566     ierr = PCView(def->pc,viewer);CHKERRQ(ierr);
567     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
568 
569     ierr = PetscViewerASCIIPrintf(viewer,"--- Coarse solver\n");CHKERRQ(ierr);
570     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
571     ierr = KSPView(def->WtAWinv,viewer);CHKERRQ(ierr);
572     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
573   }
574   PetscFunctionReturn(0);
575 }
576 
577 static PetscErrorCode PCSetFromOptions_Deflation(PetscOptionItems *PetscOptionsObject,PC pc)
578 {
579   PC_Deflation      *def = (PC_Deflation*)pc->data;
580   PetscErrorCode    ierr;
581 
582   PetscFunctionBegin;
583   ierr = PetscOptionsHead(PetscOptionsObject,"Deflation options");CHKERRQ(ierr);
584   ierr = PetscOptionsEnum("-pc_deflation_compute_space","Compute deflation space","PCDeflationSetSpace",PCDeflationSpaceTypes,(PetscEnum)def->spacetype,(PetscEnum*)&def->spacetype,NULL);CHKERRQ(ierr);
585   ierr = PetscOptionsInt("-pc_deflation_compute_space_size","Set size of the deflation space to compute","PCDeflationSetSpace",def->spacesize,&def->spacesize,NULL);CHKERRQ(ierr);
586   ierr = PetscOptionsBool("-pc_deflation_space_extend","Extend deflation space instead of truncating (wavelets)","PCDeflation",def->extendsp,&def->extendsp,NULL);CHKERRQ(ierr);
587 //TODO add set function and fix manpages
588   ierr = PetscOptionsBool("-pc_deflation_initdef","Use only initialization step - Initdef","PCDeflation",def->init,&def->init,NULL);CHKERRQ(ierr);
589   ierr = PetscOptionsBool("-pc_deflation_correct","Add coarse problem correction Q to P","PCDeflation",def->correct,&def->correct,NULL);CHKERRQ(ierr);
590   ierr = PetscOptionsReal("-pc_deflation_correct_val","Set multiple of Q to use as coarse problem correction","PCDeflation",def->correctfact,&def->correctfact,NULL);CHKERRQ(ierr);
591   ierr = PetscOptionsInt("-pc_deflation_redfact","Reduction factor for coarse problem solution","PCDeflation",def->reductionfact,&def->reductionfact,NULL);CHKERRQ(ierr);
592   ierr = PetscOptionsInt("-pc_deflation_max_nested_lvl","Maximum of nested deflation levels","PCDeflation",def->maxnestedlvl,&def->maxnestedlvl,NULL);CHKERRQ(ierr);
593   ierr = PetscOptionsTail();CHKERRQ(ierr);
594   PetscFunctionReturn(0);
595 }
596 
597 /*MC
598      PCDEFLATION - Deflation preconditioner shifts part of the spectrum to zero (deflates)
599      or to a predefined value
600 
601    Options Database Key:
602 +    -pc_deflation_type <init,pre,post> - selects approach to deflation (default: pre)
603 -    -pc_jacobi_abs - use the absolute value of the diagonal entry
604 
605    Level: beginner
606 
607   Notes:
608     todo
609 
610 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
611            PCDeflationSetType(), PCDeflationSetSpace()
612 M*/
613 
614 PETSC_EXTERN PetscErrorCode PCCreate_Deflation(PC pc)
615 {
616   PC_Deflation   *def;
617   PetscErrorCode ierr;
618 
619   PetscFunctionBegin;
620   ierr     = PetscNewLog(pc,&def);CHKERRQ(ierr);
621   pc->data = (void*)def;
622 
623   def->init          = PETSC_FALSE;
624   def->correct       = PETSC_FALSE;
625   def->correctfact   = 1.0;
626   def->reductionfact = -1;
627   def->spacetype     = PC_DEFLATION_SPACE_HAAR;
628   def->spacesize     = 1;
629   def->extendsp      = PETSC_FALSE;
630   def->nestedlvl     = 0;
631   def->maxnestedlvl  = 0;
632 
633   /*
634       Set the pointers for the functions that are provided above.
635       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
636       are called, they will automatically call these functions.  Note we
637       choose not to provide a couple of these functions since they are
638       not needed.
639   */
640   pc->ops->apply               = PCApply_Deflation;
641   pc->ops->applytranspose      = PCApply_Deflation;
642   pc->ops->presolve            = PCPreSolve_Deflation;
643   pc->ops->postsolve           = 0;
644   pc->ops->setup               = PCSetUp_Deflation;
645   pc->ops->reset               = PCReset_Deflation;
646   pc->ops->destroy             = PCDestroy_Deflation;
647   pc->ops->setfromoptions      = PCSetFromOptions_Deflation;
648   pc->ops->view                = PCView_Deflation;
649   pc->ops->applyrichardson     = 0;
650   pc->ops->applysymmetricleft  = 0;
651   pc->ops->applysymmetricright = 0;
652 
653   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpace_C",PCDeflationSetSpace_Deflation);CHKERRQ(ierr);
654   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetLvl_C",PCDeflationSetLvl_Deflation);CHKERRQ(ierr);
655   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetPC_C",PCDeflationSetPC_Deflation);CHKERRQ(ierr);
656   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetCoarseKSP_C",PCDeflationGetCoarseKSP_Deflation);CHKERRQ(ierr);
657   PetscFunctionReturn(0);
658 }
659 
660