xref: /petsc/src/ksp/pc/impls/deflation/deflation.c (revision d2fd7bfc6f0fd2e1d083decbb7cc7d77e16824f0)
1 #include <../src/ksp/pc/impls/deflation/deflation.h> /*I "petscksp.h" I*/  /* includes for fortran wrappers */
2 
3 const char *const PCDeflationSpaceTypes[] = {
4   "haar",
5   "db2",
6   "db4",
7   "db8",
8   "db16",
9   "biorth22",
10   "meyer",
11   "aggregation",
12   "user",
13   "PCDeflationSpaceType",
14   "PC_DEFLATION_SPACE_",
15   0
16 };
17 
18 static PetscErrorCode PCDeflationSetInitOnly_Deflation(PC pc,PetscBool flg)
19 {
20   PC_Deflation   *def = (PC_Deflation*)pc->data;
21 
22   PetscFunctionBegin;
23   def->init = flg;
24   PetscFunctionReturn(0);
25 }
26 
27 /*@
28    PCDeflationSetInitOnly - Do only initialization step.
29     Sets initial guess to the solution on the deflation space but does not apply
30     the deflation preconditioner. The additional preconditioner is still applied.
31 
32    Logically Collective
33 
34    Input Parameters:
35 +  pc  - the preconditioner context
36 -  flg - default PETSC_FALSE
37 
38    Options Database Keys:
39 .    -pc_deflation_init_only <false> - if true computes only the special guess
40 
41    Level: intermediate
42 
43 .seealso: PCDEFLATION
44 @*/
45 PetscErrorCode PCDeflationSetInitOnly(PC pc,PetscBool flg)
46 {
47   PetscErrorCode ierr;
48 
49   PetscFunctionBegin;
50   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
51   PetscValidLogicalCollectiveBool(pc,flg,2);
52   ierr = PetscTryMethod(pc,"PCDeflationSetInitOnly_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
53   PetscFunctionReturn(0);
54 }
55 
56 
57 static PetscErrorCode PCDeflationSetLevels_Deflation(PC pc,PetscInt current,PetscInt max)
58 {
59   PC_Deflation   *def = (PC_Deflation*)pc->data;
60 
61   PetscFunctionBegin;
62   if (current) def->lvl = current;
63   def->maxlvl = max;
64   PetscFunctionReturn(0);
65 }
66 
67 /*@
68    PCDeflationSetLevels - Set the maximum level of deflation nesting.
69 
70    Logically Collective
71 
72    Input Parameters:
73 +  pc  - the preconditioner context
74 -  max - maximum deflation level
75 
76    Options Database Keys:
77 .    -pc_deflation_max_lvl <0> - maximum number of levels for multilevel deflation
78 
79    Level: intermediate
80 
81 .seealso: PCDeflationSetSpaceToCompute(), PCDeflationSetSpace(), PCDEFLATION
82 @*/
83 PetscErrorCode PCDeflationSetLevels(PC pc,PetscInt max)
84 {
85   PetscErrorCode ierr;
86 
87   PetscFunctionBegin;
88   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
89   PetscValidLogicalCollectiveInt(pc,max,2);
90   ierr = PetscTryMethod(pc,"PCDeflationSetLevels_C",(PC,PetscInt,PetscInt),(pc,0,max));CHKERRQ(ierr);
91   PetscFunctionReturn(0);
92 }
93 
94 static PetscErrorCode PCDeflationSetReductionFactor_Deflation(PC pc,PetscInt red)
95 {
96   PC_Deflation   *def = (PC_Deflation*)pc->data;
97 
98   PetscFunctionBegin;
99   def->reductionfact = red;
100   PetscFunctionReturn(0);
101 }
102 
103 /*@
104    PCDeflationSetReductionFactor - Set reduction factor for the bottom PCTELESCOPE coarse problem solver.
105 
106    Logically Collective
107 
108    Input Parameters:
109 +  pc  - the preconditioner context
110 -  red - reduction factor (or PETSC_DETERMINE)
111 
112    Options Database Keys:
113 .    -pc_deflation_reduction_factor <\-1> - reduction factor on bottom level coarse problem for PCTELESCOPE
114 
115    Notes:
116      Default is computed based on the size of the coarse problem.
117 
118    Level: intermediate
119 
120 .seealso: PCTELESCOPE, PCDEFLATION
121 @*/
122 PetscErrorCode PCDeflationSetReductionFactor(PC pc,PetscInt red)
123 {
124   PetscErrorCode ierr;
125 
126   PetscFunctionBegin;
127   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
128   PetscValidLogicalCollectiveInt(pc,red,2);
129   ierr = PetscTryMethod(pc,"PCDeflationSetReductionFactor_C",(PC,PetscInt),(pc,red));CHKERRQ(ierr);
130   PetscFunctionReturn(0);
131 }
132 
133 static PetscErrorCode PCDeflationSetCorrectionFactor_Deflation(PC pc,PetscScalar fact)
134 {
135   PC_Deflation   *def = (PC_Deflation*)pc->data;
136 
137   PetscFunctionBegin;
138   /* TODO PETSC_DETERMINE -> compute max eigenvalue with power method */
139   def->correct = PETSC_TRUE;
140   def->correctfact = fact;
141   if (def->correct == 0.0) {
142     def->correct = PETSC_FALSE;
143   }
144   PetscFunctionReturn(0);
145 }
146 
147 /*@
148    PCDeflationSetCorrectionFactor - Set coarse problem correction factor.
149     The Preconditioner becomes P*M^{-1} + fact*Q.
150 
151    Logically Collective
152 
153    Input Parameters:
154 +  pc   - the preconditioner context
155 -  fact - correction factor
156 
157    Options Database Keys:
158 +    -pc_deflation_correction        <false> - if true apply coarse problem correction
159 -    -pc_deflation_correction_factor <1.0>   - sets coarse problem correction factor
160 
161    Notes:
162     Any non-zero fact enables the coarse problem correction.
163 
164    Level: intermediate
165 
166 .seealso: PCDEFLATION
167 @*/
168 PetscErrorCode PCDeflationSetCorrectionFactor(PC pc,PetscScalar fact)
169 {
170   PetscErrorCode ierr;
171 
172   PetscFunctionBegin;
173   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
174   PetscValidLogicalCollectiveScalar(pc,fact,2);
175   ierr = PetscTryMethod(pc,"PCDeflationSetCorrectionFactor_C",(PC,PetscScalar),(pc,fact));CHKERRQ(ierr);
176   PetscFunctionReturn(0);
177 }
178 
179 static PetscErrorCode PCDeflationSetSpaceToCompute_Deflation(PC pc,PCDeflationSpaceType type,PetscInt size)
180 {
181   PC_Deflation   *def = (PC_Deflation*)pc->data;
182 
183   PetscFunctionBegin;
184   if (type) def->spacetype = type;
185   if (size > 0) def->spacesize = size;
186   PetscFunctionReturn(0);
187 }
188 
189 /*@
190    PCDeflationSetSpaceToCompute - Set deflation space type and size to compute.
191 
192    Logically Collective
193 
194    Input Parameters:
195 +  pc   - the preconditioner context
196 .  type - deflation space type to compute (or PETSC_IGNORE)
197 -  size - size of the space to compute (or PETSC_DEFAULT)
198 
199    Options Database Keys:
200 +    -pc_deflation_compute_space      <haar> - compute PCDeflationSpaceType deflation space
201 -    -pc_deflation_compute_space_size <1>    - size of the deflation space
202 
203    Notes:
204     For wavelet-based deflation, size represents number of levels.
205 
206     The deflation space is computed in PCSetUp().
207 
208    Level: intermediate
209 
210 .seealso: PCDeflationSetLevels(), PCDEFLATION
211 @*/
212 PetscErrorCode PCDeflationSetSpaceToCompute(PC pc,PCDeflationSpaceType type,PetscInt size)
213 {
214   PetscErrorCode ierr;
215 
216   PetscFunctionBegin;
217   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
218   if (type) PetscValidLogicalCollectiveEnum(pc,type,2);
219   if (size > 0) PetscValidLogicalCollectiveInt(pc,size,3);
220   ierr = PetscTryMethod(pc,"PCDeflationSetSpaceToCompute_C",(PC,PCDeflationSpaceType,PetscInt),(pc,type,size));CHKERRQ(ierr);
221   PetscFunctionReturn(0);
222 }
223 
224 static PetscErrorCode PCDeflationSetSpace_Deflation(PC pc,Mat W,PetscBool transpose)
225 {
226   PC_Deflation   *def = (PC_Deflation*)pc->data;
227   PetscErrorCode ierr;
228 
229   PetscFunctionBegin;
230   /* possibly allows W' = Wt (which is valid but not tested) */
231   ierr = PetscObjectReference((PetscObject)W);CHKERRQ(ierr);
232   if (transpose) {
233     ierr = MatDestroy(&def->Wt);CHKERRQ(ierr);
234     def->Wt = W;
235   } else {
236     ierr = MatDestroy(&def->W);CHKERRQ(ierr);
237     def->W = W;
238   }
239   PetscFunctionReturn(0);
240 }
241 
242 /*@
243    PCDeflationSetSpace - Set the deflation space matrix (or its (Hermitian) transpose).
244 
245    Logically Collective
246 
247    Input Parameters:
248 +  pc        - the preconditioner context
249 .  W         - deflation matrix
250 -  transpose - indicates that W is an explicit transpose of the deflation matrix
251 
252    Notes:
253     Setting W as a multipliplicative MATCOMPOSITE enables use of the multilevel
254     deflation. If W = W0*W1*W2*...*Wn, W0 is taken as the first deflation space and
255     the coarse problem (W0'*A*W0)^{-1} is again preconditioned by deflation with
256     W1 as the deflation matrix. This repeats until the maximum level set by
257     PCDeflationSetLevels() is reached or there are no more matrices available.
258     If there are matrices left after reaching the maximum level,
259     they are merged into a deflation matrix ...*W{n-1}*Wn.
260 
261    Level: intermediate
262 
263 .seealso: PCDeflationSetLevels(), PCDEFLATION
264 @*/
265 PetscErrorCode PCDeflationSetSpace(PC pc,Mat W,PetscBool transpose)
266 {
267   PetscErrorCode ierr;
268 
269   PetscFunctionBegin;
270   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
271   PetscValidHeaderSpecific(W,MAT_CLASSID,2);
272   PetscValidLogicalCollectiveBool(pc,transpose,3);
273   ierr = PetscTryMethod(pc,"PCDeflationSetSpace_C",(PC,Mat,PetscBool),(pc,W,transpose));CHKERRQ(ierr);
274   PetscFunctionReturn(0);
275 }
276 
277 static PetscErrorCode PCDeflationSetProjectionNullSpaceMat_Deflation(PC pc,Mat mat)
278 {
279   PC_Deflation     *def = (PC_Deflation*)pc->data;
280   PetscErrorCode   ierr;
281 
282   PetscFunctionBegin;
283   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
284   ierr = MatDestroy(&def->WtA);CHKERRQ(ierr);
285   def->WtA = mat;
286   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtA);CHKERRQ(ierr);
287   PetscFunctionReturn(0);
288 }
289 
290 /*@
291    PCDeflationSetProjectionNullSpaceMat - Set the projection null space matrix (W'*A).
292 
293    Collective
294 
295    Input Parameters:
296 +  pc  - preconditioner context
297 -  mat - projection null space matrix
298 
299    Level: developer
300 
301 .seealso: PCDEFLATION
302 @*/
303 PetscErrorCode  PCDeflationSetProjectionNullSpaceMat(PC pc,Mat mat)
304 {
305   PetscErrorCode ierr;
306 
307   PetscFunctionBegin;
308   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
309   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
310   ierr = PetscTryMethod(pc,"PCDeflationSetProjectionNullSpaceMat_C",(PC,Mat),(pc,mat));CHKERRQ(ierr);
311   PetscFunctionReturn(0);
312 }
313 
314 static PetscErrorCode PCDeflationSetCoarseMat_Deflation(PC pc,Mat mat)
315 {
316   PC_Deflation     *def = (PC_Deflation*)pc->data;
317   PetscErrorCode   ierr;
318 
319   PetscFunctionBegin;
320   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
321   ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr);
322   def->WtAW = mat;
323   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtAW);CHKERRQ(ierr);
324   PetscFunctionReturn(0);
325 }
326 
327 /*@
328    PCDeflationSetCoarseMat - Set the coarse problem Mat.
329 
330    Collective
331 
332    Input Parameters:
333 +  pc  - preconditioner context
334 -  mat - coarse problem mat
335 
336    Level: developer
337 
338 .seealso: PCDEFLATION
339 @*/
340 PetscErrorCode  PCDeflationSetCoarseMat(PC pc,Mat mat)
341 {
342   PetscErrorCode ierr;
343 
344   PetscFunctionBegin;
345   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
346   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
347   ierr = PetscTryMethod(pc,"PCDeflationSetCoarseMat_C",(PC,Mat),(pc,mat));CHKERRQ(ierr);
348   PetscFunctionReturn(0);
349 }
350 
351 static PetscErrorCode PCDeflationGetCoarseKSP_Deflation(PC pc,KSP *ksp)
352 {
353   PC_Deflation     *def = (PC_Deflation*)pc->data;
354 
355   PetscFunctionBegin;
356   *ksp = def->WtAWinv;
357   PetscFunctionReturn(0);
358 }
359 
360 /*@
361    PCDeflationGetCoarseKSP - Returns the coarse problem KSP.
362 
363    Not Collective
364 
365    Input Parameters:
366 .  pc - preconditioner context
367 
368    Output Parameters:
369 .  ksp - coarse problem KSP context
370 
371    Level: advanced
372 
373 .seealso: PCDEFLATION
374 @*/
375 PetscErrorCode  PCDeflationGetCoarseKSP(PC pc,KSP *ksp)
376 {
377   PetscErrorCode ierr;
378 
379   PetscFunctionBegin;
380   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
381   PetscValidPointer(ksp,2);
382   ierr = PetscTryMethod(pc,"PCDeflationGetCoarseKSP_C",(PC,KSP*),(pc,ksp));CHKERRQ(ierr);
383   PetscFunctionReturn(0);
384 }
385 
386 static PetscErrorCode PCDeflationGetPC_Deflation(PC pc,PC *apc)
387 {
388   PC_Deflation   *def = (PC_Deflation*)pc->data;
389 
390   PetscFunctionBegin;
391   *apc = def->pc;
392   PetscFunctionReturn(0);
393 }
394 
395 /*@
396    PCDeflationGetPC - Returns the additional preconditioner M^{-1}.
397 
398    Not Collective
399 
400    Input Parameters:
401 .  pc  - the preconditioner context
402 
403    Output Parameters:
404 .  apc - additional preconditioner
405 
406    Level: advanced
407 
408 .seealso: PCDEFLATION
409 @*/
410 PetscErrorCode PCDeflationGetPC(PC pc,PC *apc)
411 {
412   PetscErrorCode ierr;
413 
414   PetscFunctionBegin;
415   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
416   PetscValidPointer(pc,2);
417   ierr = PetscTryMethod(pc,"PCDeflationGetPC_C",(PC,PC*),(pc,apc));CHKERRQ(ierr);
418   PetscFunctionReturn(0);
419 }
420 
421 /*
422   x <- x + W*(W'*A*W)^{-1}*W'*r  = x + Q*r
423 */
424 static PetscErrorCode PCPreSolve_Deflation(PC pc,KSP ksp,Vec b, Vec x)
425 {
426   PC_Deflation     *def = (PC_Deflation*)pc->data;
427   Mat              A;
428   Vec              r,w1,w2;
429   PetscBool        nonzero;
430   PetscErrorCode   ierr;
431 
432   PetscFunctionBegin;
433   w1 = def->workcoarse[0];
434   w2 = def->workcoarse[1];
435   r  = def->work;
436   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
437 
438   ierr = KSPGetInitialGuessNonzero(ksp,&nonzero);CHKERRQ(ierr);
439   ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
440   if (nonzero) {
441     ierr = MatMult(A,x,r);CHKERRQ(ierr);                          /*    r  <- b - Ax              */
442     ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr);
443   } else {
444     ierr = VecCopy(b,r);CHKERRQ(ierr);                            /*    r  <- b (x is 0)          */
445   }
446 
447   if (def->Wt) {
448     ierr = MatMult(def->Wt,r,w1);CHKERRQ(ierr);                   /*    w1 <- W'*r                */
449   } else {
450     ierr = MatMultHermitianTranspose(def->W,r,w1);CHKERRQ(ierr);  /*    w1 <- W'*r                */
451   }
452   ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);              /*    w2 <- (W'*A*W)^{-1}*w1    */
453   ierr = MatMult(def->W,w2,r);CHKERRQ(ierr);                      /*    r  <- W*w2                */
454   ierr = VecAYPX(x,1.0,r);CHKERRQ(ierr);
455   PetscFunctionReturn(0);
456 }
457 
458 /*
459   if (def->correct) {
460     z <- M^{-1}r - W*(W'*A*W)^{-1}*(W'*A*M^{-1}r - l*W'*r) = (P*M^{-1} + l*Q)*r
461   } else {
462     z <- M^{-1}*r - W*(W'*A*W)^{-1}*W'*A*M{-1}*r = P*M^{-1}*r
463   }
464 */
465 static PetscErrorCode PCApply_Deflation(PC pc,Vec r,Vec z)
466 {
467   PC_Deflation     *def = (PC_Deflation*)pc->data;
468   Mat              A;
469   Vec              u,w1,w2;
470   PetscErrorCode   ierr;
471 
472   PetscFunctionBegin;
473   w1 = def->workcoarse[0];
474   w2 = def->workcoarse[1];
475   u  = def->work;
476   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
477 
478   ierr = PCApply(def->pc,r,z);CHKERRQ(ierr);                          /*    z <- M^{-1}*r             */
479   if (!def->init) {
480     ierr = MatMult(def->WtA,z,w1);CHKERRQ(ierr);                      /*    w1 <- W'*A*z              */
481     if (def->correct) {
482       if (def->Wt) {
483         ierr = MatMult(def->Wt,r,w2);CHKERRQ(ierr);                   /*    w2 <- W'*r                */
484       } else {
485         ierr = MatMultHermitianTranspose(def->W,r,w2);CHKERRQ(ierr);  /*    w2 <- W'*r                */
486       }
487       ierr = VecAXPY(w1,-1.0*def->correctfact,w2);CHKERRQ(ierr);      /*    w1 <- w1 - l*w2           */
488     }
489     ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);                /*    w2 <- (W'*A*W)^{-1}*w1    */
490     ierr = MatMult(def->W,w2,u);CHKERRQ(ierr);                        /*    u  <- W*w2                */
491     ierr = VecAXPY(z,-1.0,u);CHKERRQ(ierr);                           /*    z  <- z - u               */
492   }
493   PetscFunctionReturn(0);
494 }
495 
496 static PetscErrorCode PCSetUp_Deflation(PC pc)
497 {
498   PC_Deflation     *def = (PC_Deflation*)pc->data;
499   KSP              innerksp;
500   PC               pcinner;
501   Mat              Amat,nextDef=NULL,*mats;
502   PetscInt         i,m,red,size;
503   PetscMPIInt      commsize;
504   PetscBool        match,flgspd,transp=PETSC_FALSE;
505   MatCompositeType ctype;
506   MPI_Comm         comm;
507   char             prefix[128]="";
508   PetscErrorCode   ierr;
509 
510   PetscFunctionBegin;
511   if (pc->setupcalled) PetscFunctionReturn(0);
512   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
513   ierr = PCGetOperators(pc,NULL,&Amat);CHKERRQ(ierr);
514   if (!def->lvl && !def->prefix) {
515     ierr = PCGetOptionsPrefix(pc,&def->prefix);CHKERRQ(ierr);
516   }
517   if (def->lvl) {
518     ierr = PetscSNPrintf(prefix,sizeof(prefix),"%d_",(int)def->lvl);CHKERRQ(ierr);
519   }
520 
521   /* compute a deflation space */
522   if (def->W || def->Wt) {
523     def->spacetype = PC_DEFLATION_SPACE_USER;
524   } else {
525     ierr = PCDeflationComputeSpace(pc);CHKERRQ(ierr);
526   }
527 
528   /* nested deflation */
529   if (def->W) {
530     ierr = PetscObjectTypeCompare((PetscObject)def->W,MATCOMPOSITE,&match);CHKERRQ(ierr);
531     if (match) {
532       ierr = MatCompositeGetType(def->W,&ctype);CHKERRQ(ierr);
533       ierr = MatCompositeGetNumberMat(def->W,&size);CHKERRQ(ierr);
534     }
535   } else {
536     ierr = MatCreateHermitianTranspose(def->Wt,&def->W);CHKERRQ(ierr);
537     ierr = PetscObjectTypeCompare((PetscObject)def->Wt,MATCOMPOSITE,&match);CHKERRQ(ierr);
538     if (match) {
539       ierr = MatCompositeGetType(def->Wt,&ctype);CHKERRQ(ierr);
540       ierr = MatCompositeGetNumberMat(def->Wt,&size);CHKERRQ(ierr);
541     }
542     transp = PETSC_TRUE;
543   }
544   if (match && ctype == MAT_COMPOSITE_MULTIPLICATIVE) {
545     if (!transp) {
546       if (def->lvl < def->maxlvl) {
547         ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
548         for (i=0; i<size; i++) {
549           ierr = MatCompositeGetMat(def->W,i,&mats[i]);CHKERRQ(ierr);
550         }
551         size -= 1;
552         ierr = MatDestroy(&def->W);CHKERRQ(ierr);
553         def->W = mats[size];
554         ierr = PetscObjectReference((PetscObject)mats[size]);CHKERRQ(ierr);
555         if (size > 1) {
556           ierr = MatCreateComposite(comm,size,mats,&nextDef);CHKERRQ(ierr);
557           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
558         } else {
559           nextDef = mats[0];
560           ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
561         }
562         ierr = PetscFree(mats);CHKERRQ(ierr);
563       } else {
564         /* TODO test merge side performance */
565         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
566         ierr = MatCompositeMerge(def->W);CHKERRQ(ierr);
567       }
568     } else {
569       if (def->lvl < def->maxlvl) {
570         ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
571         for (i=0; i<size; i++) {
572           ierr = MatCompositeGetMat(def->Wt,i,&mats[i]);CHKERRQ(ierr);
573         }
574         size -= 1;
575         ierr = MatDestroy(&def->Wt);CHKERRQ(ierr);
576         def->Wt = mats[0];
577         ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
578         if (size > 1) {
579           ierr = MatCreateComposite(comm,size,&mats[1],&nextDef);CHKERRQ(ierr);
580           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
581         } else {
582           nextDef = mats[1];
583           ierr = PetscObjectReference((PetscObject)mats[1]);CHKERRQ(ierr);
584         }
585         ierr = PetscFree(mats);CHKERRQ(ierr);
586       } else {
587         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
588         ierr = MatCompositeMerge(def->Wt);CHKERRQ(ierr);
589       }
590     }
591   }
592 
593   if (transp) {
594     ierr = MatDestroy(&def->W);CHKERRQ(ierr);
595     ierr = MatHermitianTranspose(def->Wt,MAT_INITIAL_MATRIX,&def->W);CHKERRQ(ierr);
596   }
597 
598   /* assemble WtA */
599   if (!def->WtA) {
600     if (def->Wt) {
601       ierr = MatMatMult(def->Wt,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr);
602     } else {
603 #if defined(PETSC_USE_COMPLEX)
604       ierr = MatHermitianTranspose(def->W,MAT_INITIAL_MATRIX,&def->Wt);CHKERRQ(ierr);
605       ierr = MatMatMult(def->Wt,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr);
606 #else
607       ierr = MatTransposeMatMult(def->W,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr);
608 #endif
609     }
610   }
611   /* setup coarse problem */
612   if (!def->WtAWinv) {
613     ierr = MatGetSize(def->W,NULL,&m);CHKERRQ(ierr);
614     if (!def->WtAW) {
615       ierr = MatMatMult(def->WtA,def->W,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr);
616       /* TODO create MatInheritOption(Mat,MatOption) */
617       ierr = MatGetOption(Amat,MAT_SPD,&flgspd);CHKERRQ(ierr);
618       ierr = MatSetOption(def->WtAW,MAT_SPD,flgspd);CHKERRQ(ierr);
619 #if defined(PETSC_USE_DEBUG)
620       /* Check columns of W are not in kernel of A */
621       {
622         PetscReal *norms;
623         ierr = PetscMalloc1(m,&norms);CHKERRQ(ierr);
624         ierr = MatGetColumnNorms(def->WtAW,NORM_INFINITY,norms);CHKERRQ(ierr);
625         for (i=0; i<m; i++) {
626           if (norms[i] < 100*PETSC_MACHINE_EPSILON) {
627             SETERRQ1(comm,PETSC_ERR_SUP,"Column %D of W is in kernel of A.",i);
628           }
629         }
630         ierr = PetscFree(norms);CHKERRQ(ierr);
631       }
632 #endif
633     } else {
634       ierr = MatGetOption(def->WtAW,MAT_SPD,&flgspd);CHKERRQ(ierr);
635     }
636     /* TODO use MATINV ? */
637     ierr = KSPCreate(comm,&def->WtAWinv);CHKERRQ(ierr);
638     ierr = KSPSetOperators(def->WtAWinv,def->WtAW,def->WtAW);CHKERRQ(ierr);
639     ierr = KSPGetPC(def->WtAWinv,&pcinner);CHKERRQ(ierr);
640     /* Setup KSP and PC */
641     if (nextDef) { /* next level for multilevel deflation */
642       innerksp = def->WtAWinv;
643       /* set default KSPtype */
644       if (!def->ksptype) {
645         def->ksptype = KSPFGMRES;
646         if (flgspd) { /* SPD system */
647           def->ksptype = KSPFCG;
648         }
649       }
650       ierr = KSPSetType(innerksp,def->ksptype);CHKERRQ(ierr); /* TODO iherit from KSP + tolerances */
651       ierr = PCSetType(pcinner,PCDEFLATION);CHKERRQ(ierr); /* TODO create coarse preconditinoner M_c = WtMW ? */
652       ierr = PCDeflationSetSpace(pcinner,nextDef,transp);CHKERRQ(ierr);
653       ierr = PCDeflationSetLevels_Deflation(pcinner,def->lvl+1,def->maxlvl);CHKERRQ(ierr);
654       /* inherit options */
655       if (def->prefix) ((PC_Deflation*)(pcinner->data))->prefix = def->prefix;
656       ((PC_Deflation*)(pcinner->data))->init          = def->init;
657       ((PC_Deflation*)(pcinner->data))->ksptype       = def->ksptype;
658       ((PC_Deflation*)(pcinner->data))->correct       = def->correct;
659       ((PC_Deflation*)(pcinner->data))->correctfact   = def->correctfact;
660       ((PC_Deflation*)(pcinner->data))->reductionfact = def->reductionfact;
661       ierr = MatDestroy(&nextDef);CHKERRQ(ierr);
662     } else { /* the last level */
663       ierr = KSPSetType(def->WtAWinv,KSPPREONLY);CHKERRQ(ierr);
664       ierr = PCSetType(pcinner,PCTELESCOPE);CHKERRQ(ierr);
665       /* do not overwrite PCTELESCOPE */
666       if (def->prefix) {
667         ierr = KSPSetOptionsPrefix(def->WtAWinv,def->prefix);CHKERRQ(ierr);
668       }
669       ierr = KSPAppendOptionsPrefix(def->WtAWinv,"deflation_tel_");CHKERRQ(ierr);
670       ierr = PCSetFromOptions(pcinner);CHKERRQ(ierr);
671       ierr = PetscObjectTypeCompare((PetscObject)pcinner,PCTELESCOPE,&match);CHKERRQ(ierr);
672       if (!match) SETERRQ(comm,PETSC_ERR_SUP,"User can not owerwrite PCTELESCOPE on bottom level, use reduction factor = 1 instead.");
673       /* Reduction factor choice */
674       red = def->reductionfact;
675       if (red < 0) {
676         ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
677         red  = ceil((float)commsize/ceil((float)m/commsize));
678         ierr = PetscObjectTypeCompareAny((PetscObject)(def->WtAW),&match,MATSEQDENSE,MATMPIDENSE,MATDENSE,"");CHKERRQ(ierr);
679         if (match) red = commsize;
680         ierr = PetscInfo1(pc,"Auto choosing reduction factor %D\n",red);CHKERRQ(ierr);
681       }
682       ierr = PCTelescopeSetReductionFactor(pcinner,red);CHKERRQ(ierr);
683       ierr = PCSetUp(pcinner);CHKERRQ(ierr);
684       ierr = PCTelescopeGetKSP(pcinner,&innerksp);CHKERRQ(ierr);
685       if (innerksp) {
686         ierr = KSPGetPC(innerksp,&pcinner);CHKERRQ(ierr);
687         ierr = PCSetType(pcinner,PCLU);CHKERRQ(ierr);
688 #if defined(PETSC_HAVE_SUPERLU)
689         ierr = MatGetFactorAvailable(def->WtAW,MATSOLVERSUPERLU,MAT_FACTOR_LU,&match);CHKERRQ(ierr);
690         if (match) {
691           ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU);CHKERRQ(ierr);
692         }
693 #endif
694 #if defined(PETSC_HAVE_SUPERLU_DIST)
695         ierr = MatGetFactorAvailable(def->WtAW,MATSOLVERSUPERLU_DIST,MAT_FACTOR_LU,&match);CHKERRQ(ierr);
696         if (match) {
697           ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU_DIST);CHKERRQ(ierr);
698         }
699 #endif
700       }
701     }
702 
703     if (innerksp) {
704       if (def->prefix) {
705         ierr = KSPSetOptionsPrefix(innerksp,def->prefix);CHKERRQ(ierr);
706         ierr = KSPAppendOptionsPrefix(innerksp,"deflation_");CHKERRQ(ierr);
707       } else {
708         ierr = KSPSetOptionsPrefix(innerksp,"deflation_");CHKERRQ(ierr);
709       }
710       ierr = KSPAppendOptionsPrefix(innerksp,prefix);CHKERRQ(ierr);
711       ierr = KSPSetFromOptions(innerksp);CHKERRQ(ierr);
712       ierr = KSPSetUp(innerksp);CHKERRQ(ierr);
713     }
714   }
715   ierr = KSPSetFromOptions(def->WtAWinv);CHKERRQ(ierr);
716   ierr = KSPSetUp(def->WtAWinv);CHKERRQ(ierr);
717 
718   /* create preconditioner */
719   if (!def->pc) {
720     ierr = PCCreate(comm,&def->pc);CHKERRQ(ierr);
721     ierr = PCSetOperators(def->pc,Amat,Amat);CHKERRQ(ierr);
722     ierr = PCSetType(def->pc,PCNONE);CHKERRQ(ierr);
723     if (def->prefix) {
724       ierr = PCSetOptionsPrefix(def->pc,def->prefix);CHKERRQ(ierr);
725     }
726     ierr = PCAppendOptionsPrefix(def->pc,"deflation_");CHKERRQ(ierr);
727     ierr = PCAppendOptionsPrefix(def->pc,prefix);CHKERRQ(ierr);
728     ierr = PCAppendOptionsPrefix(def->pc,"pc_");CHKERRQ(ierr);
729     ierr = PCSetFromOptions(def->pc);CHKERRQ(ierr);
730     ierr = PCSetUp(def->pc);CHKERRQ(ierr);
731   }
732 
733   /* create work vecs */
734   ierr = MatCreateVecs(Amat,NULL,&def->work);CHKERRQ(ierr);
735   ierr = KSPCreateVecs(def->WtAWinv,2,&def->workcoarse,0,NULL);CHKERRQ(ierr);
736   PetscFunctionReturn(0);
737 }
738 
739 static PetscErrorCode PCReset_Deflation(PC pc)
740 {
741   PC_Deflation      *def = (PC_Deflation*)pc->data;
742   PetscErrorCode    ierr;
743 
744   PetscFunctionBegin;
745   ierr = VecDestroy(&def->work);CHKERRQ(ierr);
746   ierr = VecDestroyVecs(2,&def->workcoarse);CHKERRQ(ierr);
747   ierr = MatDestroy(&def->W);CHKERRQ(ierr);
748   ierr = MatDestroy(&def->Wt);CHKERRQ(ierr);
749   ierr = MatDestroy(&def->WtA);CHKERRQ(ierr);
750   ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr);
751   ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr);
752   ierr = PCDestroy(&def->pc);CHKERRQ(ierr);
753   PetscFunctionReturn(0);
754 }
755 
756 static PetscErrorCode PCDestroy_Deflation(PC pc)
757 {
758   PetscErrorCode ierr;
759 
760   PetscFunctionBegin;
761   ierr = PCReset_Deflation(pc);CHKERRQ(ierr);
762   ierr = PetscFree(pc->data);CHKERRQ(ierr);
763   PetscFunctionReturn(0);
764 }
765 
766 static PetscErrorCode PCView_Deflation(PC pc,PetscViewer viewer)
767 {
768   PC_Deflation      *def = (PC_Deflation*)pc->data;
769   PetscInt          its;
770   PetscBool         iascii;
771   PetscErrorCode    ierr;
772 
773   PetscFunctionBegin;
774   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
775   if (iascii) {
776     if (def->correct) {
777       ierr = PetscViewerASCIIPrintf(viewer,"using CP correction, factor = %g+%gi\n",
778                                     (double)PetscRealPart(def->correctfact),
779                                     (double)PetscImaginaryPart(def->correctfact));CHKERRQ(ierr);
780     }
781     if (!def->lvl) {
782       ierr = PetscViewerASCIIPrintf(viewer,"deflation space type: %s\n",PCDeflationSpaceTypes[def->spacetype]);CHKERRQ(ierr);
783     }
784 
785     ierr = PetscViewerASCIIPrintf(viewer,"--- Additional PC:\n");CHKERRQ(ierr);
786     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
787     ierr = PCView(def->pc,viewer);CHKERRQ(ierr);
788     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
789 
790     ierr = PetscViewerASCIIPrintf(viewer,"--- Coarse problem solver:\n");CHKERRQ(ierr);
791     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
792     ierr = KSPGetTotalIterations(def->WtAWinv,&its);CHKERRQ(ierr);
793     ierr = PetscViewerASCIIPrintf(viewer,"total number of iterations: %D\n",its);CHKERRQ(ierr);
794     ierr = KSPView(def->WtAWinv,viewer);CHKERRQ(ierr);
795     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
796   }
797   PetscFunctionReturn(0);
798 }
799 
800 static PetscErrorCode PCSetFromOptions_Deflation(PetscOptionItems *PetscOptionsObject,PC pc)
801 {
802   PC_Deflation      *def = (PC_Deflation*)pc->data;
803   PetscErrorCode    ierr;
804 
805   PetscFunctionBegin;
806   ierr = PetscOptionsHead(PetscOptionsObject,"Deflation options");CHKERRQ(ierr);
807   ierr = PetscOptionsBool("-pc_deflation_init_only","Use only initialization step - Initdef","PCDeflationSetInitOnly",def->init,&def->init,NULL);CHKERRQ(ierr);
808   ierr = PetscOptionsInt("-pc_deflation_levels","Maximum of deflation levels","PCDeflationSetLevels",def->maxlvl,&def->maxlvl,NULL);CHKERRQ(ierr);
809   ierr = PetscOptionsInt("-pc_deflation_reduction_factor","Reduction factor for coarse problem solution using PCTELESCOPE","PCDeflationSetReductionFactor",def->reductionfact,&def->reductionfact,NULL);CHKERRQ(ierr);
810   ierr = PetscOptionsBool("-pc_deflation_correction","Add coarse problem correction Q to P","PCDeflationSetCorrectionFactor",def->correct,&def->correct,NULL);CHKERRQ(ierr);
811   ierr = PetscOptionsScalar("-pc_deflation_correction_factor","Set multiple of Q to use as coarse problem correction","PCDeflationSetCorrectionFactor",def->correctfact,&def->correctfact,NULL);CHKERRQ(ierr);
812   ierr = PetscOptionsEnum("-pc_deflation_compute_space","Compute deflation space","PCDeflationSetSpace",PCDeflationSpaceTypes,(PetscEnum)def->spacetype,(PetscEnum*)&def->spacetype,NULL);CHKERRQ(ierr);
813   ierr = PetscOptionsInt("-pc_deflation_compute_space_size","Set size of the deflation space to compute","PCDeflationSetSpace",def->spacesize,&def->spacesize,NULL);CHKERRQ(ierr);
814   ierr = PetscOptionsBool("-pc_deflation_space_extend","Extend deflation space instead of truncating (wavelets)","PCDeflation",def->extendsp,&def->extendsp,NULL);CHKERRQ(ierr);
815   ierr = PetscOptionsTail();CHKERRQ(ierr);
816   PetscFunctionReturn(0);
817 }
818 
819 /*MC
820    PCDEFLATION - Deflation preconditioner shifts (deflates) part of the spectrum to zero or to a predefined value.
821 
822    Options Database Keys:
823 +    -pc_deflation_init_only          <false> - if true computes only the special guess
824 .    -pc_deflation_max_lvl            <0>     - maximum number of levels for multilevel deflation
825 .    -pc_deflation_reduction_factor <\-1>     - reduction factor on bottom level coarse problem for PCTELESCOPE (default based on the size of the coarse problem)
826 .    -pc_deflation_correction         <false> - if true apply coarse problem correction
827 .    -pc_deflation_correction_factor  <1.0>   - sets coarse problem correction factor
828 .    -pc_deflation_compute_space      <haar>  - compute PCDeflationSpaceType deflation space
829 -    -pc_deflation_compute_space_size <1>     - size of the deflation space (corresponds to number of levels for wavelet-based deflation)
830 
831    Notes:
832     Given a (complex - transpose is always Hermitian) full rank deflation matrix W, the deflation (introduced in [1,2])
833     preconditioner uses projections Q = W*(W'*A*W)^{-1}*W' and P = I - Q*A, where A is pmat.
834 
835     The deflation computes initial guess x0 = x_{-1} - Q*r_{-1}, which is the solution on the deflation space.
836     If PCDeflationSetInitOnly() or -pc_deflation_init_only is set to PETSC_TRUE (InitDef scheme), the application of the
837     preconditioner consists only of application of the additional preconditioner M^{-1}. Otherwise, the preconditioner
838     application consists of P*M^{-1} + factor*Q. The first part of the preconditioner (PM^{-1}) shifts some eigenvalues
839     to zero while the addition of the coarse problem correction (factor*Q) makes the preconditioner to shift some
840     eigenvalues to the given factor. The InitDef scheme is recommended for deflation using high accuracy estimates
841     of eigenvectors of A when it exhibits similar convergence to the full deflation but is cheaper.
842 
843     The deflation matrix is by default automatically computed. The type of deflation matrix and its size to compute can
844     be controlled by PCDeflationSetSpaceToCompute() or -pc_deflation_compute_space and -pc_deflation_compute_space_size.
845     User can set an arbitrary deflation space matrix with PCDeflationSetSpace(). If the deflation matrix
846     is a multiplicative MATCOMPOSITE, a multilevel deflation [3] is used. The first matrix in the composite is used as the
847     deflation matrix, and the coarse problem (W'*A*W)^{-1} is solved by KSPFCG (if A is MAT_SPD) or KSPFGMRES preconditioned
848     by deflation with deflation matrix being the next matrix in the MATCOMPOSITE. This scheme repeats until the maximum
849     level is reached or there are no more matrices. If the maximum level is reached, the remaining matrices are merged
850     (multiplied) to create the last deflation matrix. The maximum level defaults to 0 and can be set by
851     PCDeflationSetLevels() or by -pc_deflation_levels.
852 
853     The coarse problem KSP can be controlled from the command line with prefix -deflation_ for the first level and -deflation_[lvl-1]
854     from the second level onward. You can also use
855     PCDeflationGetCoarseKSP() to control it from code. The bottom level KSP defaults to
856     KSPPREONLY with PCLU direct solver (MATSOLVERSUPERLU/MATSOLVERSUPERLU_DIST if available) wrapped into PCTELESCOPE.
857     For convenience, the reduction factor can be set by PCDeflationSetReductionFactor()
858     or -pc_deflation_recduction_factor. The default is chosen heuristically based on the coarse problem size.
859 
860     The additional preconditioner can be controlled from command line with prefix -deflation_[lvl]_pc (same rules used for
861     coarse problem KSP apply for [lvl]_ part of prefix), e.g., -deflation_1_pc_pc_type bjacobi. You can also use
862     PCDeflationGetPC() to control the additional preconditioner from code. It defaults to PCNONE.
863 
864     The coarse problem correction term (factor*Q) can be turned on by -pc_deflation_correction and the factor value can
865     be set by pc_deflation_correction_factor or by PCDeflationSetCorrectionFactor(). The coarse problem can
866     significantly improve convergence when the deflation coarse problem is not solved with high enough accuracy. We
867     recommend setting factor to some eigenvalue, e.g., the largest eigenvalue so that the preconditioner does not create
868     an isolated eigenvalue.
869 
870     The options are automatically inherited from the previous deflation level.
871 
872     The preconditioner supports KSPMonitorDynamicTolerance(). This is useful for the multilevel scheme for which we also
873     recommend limiting the number of iterations for the coarse problems.
874 
875     See section 3 of [4] for additional references and decription of the algorithm when used for conjugate gradients.
876     Section 4 describes some possible choices for the deflation space.
877 
878    Developer Notes:
879      Contributed by Jakub Kruzik (PERMON), Institute of Geonics of the Czech
880      Academy of Sciences and VSB - TU Ostrava.
881 
882      Developed from PERMON code used in [4] while on a research stay with
883      Prof. Reinhard Nabben at the Institute of Mathematics, TU Berlin.
884 
885    References:
886 +    [1] - A. Nicolaides. “Deflation of conjugate gradients with applications to boundary valueproblems”, SIAM J. Numer. Anal. 24.2, 1987.
887 .    [2] - Z. Dostal. "Conjugate gradient method with preconditioning by projector", Int J. Comput. Math. 23.3-4, 1988.
888 .    [3] - Y. A. Erlangga and R. Nabben. "Multilevel Projection-Based Nested Krylov Iteration for Boundary Value Problems", SIAM J. Sci. Comput. 30.3, 2008.
889 -    [4] - J. Kruzik "Implementation of the Deflated Variants of the Conjugate Gradient Method", Master's thesis, VSB-TUO, 2018 - http://dspace5.vsb.cz/bitstream/handle/10084/130303/KRU0097_USP_N2658_2612T078_2018.pdf
890 
891    Level: intermediate
892 
893 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
894            PCDeflationSetInitOnly(), PCDeflationSetLevels(), PCDeflationSetReductionFactor(),
895            PCDeflationSetCorrectionFactor(), PCDeflationSetSpaceToCompute(),
896            PCDeflationSetSpace(), PCDeflationSpaceType, PCDeflationSetProjectionNullSpaceMat(),
897            PCDeflationSetCoarseMat(), PCDeflationGetCoarseKSP(), PCDeflationGetPC()
898 M*/
899 
900 PETSC_EXTERN PetscErrorCode PCCreate_Deflation(PC pc)
901 {
902   PC_Deflation   *def;
903   PetscErrorCode ierr;
904 
905   PetscFunctionBegin;
906   ierr     = PetscNewLog(pc,&def);CHKERRQ(ierr);
907   pc->data = (void*)def;
908 
909   def->init          = PETSC_FALSE;
910   def->correct       = PETSC_FALSE;
911   def->correctfact   = 1.0;
912   def->reductionfact = -1;
913   def->spacetype     = PC_DEFLATION_SPACE_HAAR;
914   def->spacesize     = 1;
915   def->extendsp      = PETSC_FALSE;
916   def->lvl           = 0;
917   def->maxlvl        = 0;
918   def->W             = NULL;
919   def->Wt            = NULL;
920 
921   pc->ops->apply          = PCApply_Deflation;
922   pc->ops->presolve       = PCPreSolve_Deflation;
923   pc->ops->setup          = PCSetUp_Deflation;
924   pc->ops->reset          = PCReset_Deflation;
925   pc->ops->destroy        = PCDestroy_Deflation;
926   pc->ops->setfromoptions = PCSetFromOptions_Deflation;
927   pc->ops->view           = PCView_Deflation;
928 
929   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetInitOnly_C",PCDeflationSetInitOnly_Deflation);CHKERRQ(ierr);
930   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetLevels_C",PCDeflationSetLevels_Deflation);CHKERRQ(ierr);
931   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetReductionFactor_C",PCDeflationSetReductionFactor_Deflation);CHKERRQ(ierr);
932   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCorrectionFactor_C",PCDeflationSetCorrectionFactor_Deflation);CHKERRQ(ierr);
933   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpaceToCompute_C",PCDeflationSetSpaceToCompute_Deflation);CHKERRQ(ierr);
934   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpace_C",PCDeflationSetSpace_Deflation);CHKERRQ(ierr);
935   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetProjectionNullSpaceMat_C",PCDeflationSetProjectionNullSpaceMat_Deflation);CHKERRQ(ierr);
936   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCoarseMat_C",PCDeflationSetCoarseMat_Deflation);CHKERRQ(ierr);
937   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetCoarseKSP_C",PCDeflationGetCoarseKSP_Deflation);CHKERRQ(ierr);
938   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetPC_C",PCDeflationGetPC_Deflation);CHKERRQ(ierr);
939   PetscFunctionReturn(0);
940 }
941 
942