xref: /petsc/src/ksp/pc/impls/deflation/deflation.c (revision 0a78af2228aa9a5baa3b5a8e3872e699fa117360)
1 #include <../src/ksp/pc/impls/deflation/deflation.h> /*I "petscpc.h" I*/  /* includes for fortran wrappers */
2 
3 const char *const PCDeflationSpaceTypes[] = {
4   "haar",
5   "jacket-haar",
6   "db2",
7   "db4",
8   "db8",
9   "db16",
10   "biorth22",
11   "meyer",
12   "aggregation",
13   "slepc",
14   "slepc-cheap",
15   "user",
16   "PCDeflationSpaceType",
17   "PC_DEFLATION_SPACE_",
18   0
19 };
20 
21 static PetscErrorCode PCDeflationSetInitOnly_Deflation(PC pc,PetscBool flg)
22 {
23   PC_Deflation   *def = (PC_Deflation*)pc->data;
24 
25   PetscFunctionBegin;
26   def->init = flg;
27   PetscFunctionReturn(0);
28 }
29 
30 /*@
31    PCDeflationSetInitOnly - Do only initialization step.
32     Sets initial guess to the solution on the deflation space but do not apply deflation preconditioner.
33     The additional preconditioner is still applied.
34 
35    Logically Collective on PC
36 
37    Input Parameters:
38 +  pc  - the preconditioner context
39 -  flg - default PETSC_FALSE
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 PCDeflationSetLvl_Deflation(PC pc,PetscInt current,PetscInt max)
58 {
59   PC_Deflation   *def = (PC_Deflation*)pc->data;
60 
61   PetscFunctionBegin;
62   if (current) def->nestedlvl = current;
63   def->maxnestedlvl = max;
64   PetscFunctionReturn(0);
65 }
66 
67 /*@
68    PCDeflationSetMaxLvl - Set maximum level of deflation.
69 
70    Logically Collective on PC
71 
72    Input Parameters:
73 +  pc  - the preconditioner context
74 -  max - maximum deflation level
75 
76    Level: intermediate
77 
78 .seealso: PCDEFLATION
79 @*/
80 PetscErrorCode PCDeflationSetMaxLvl(PC pc,PetscInt max)
81 {
82   PetscErrorCode ierr;
83 
84   PetscFunctionBegin;
85   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
86   PetscValidLogicalCollectiveInt(pc,max,2);
87   ierr = PetscTryMethod(pc,"PCDeflationSetLvl_C",(PC,PetscInt,PetscInt),(pc,0,max));CHKERRQ(ierr);
88   PetscFunctionReturn(0);
89 }
90 
91 static PetscErrorCode PCDeflationSetReductionFactor_Deflation(PC pc,PetscInt red)
92 {
93   PC_Deflation   *def = (PC_Deflation*)pc->data;
94 
95   PetscFunctionBegin;
96   def->reductionfact = red;
97   PetscFunctionReturn(0);
98 }
99 
100 /*@
101    PCDeflationSetReductionFactor - Set reduction factor for PCTELESCOPE coarse problem solver.
102 
103    Logically Collective on PC
104 
105    Input Parameters:
106 +  pc  - the preconditioner context
107 -  red - reduction factor (or PETSC_DETERMINE)
108 
109    Level: intermediate
110 
111 .seealso: PCDEFLATION
112 @*/
113 PetscErrorCode PCDeflationSetReductionFactor(PC pc,PetscInt red)
114 {
115   PetscErrorCode ierr;
116 
117   PetscFunctionBegin;
118   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
119   PetscValidLogicalCollectiveInt(pc,red,2);
120   ierr = PetscTryMethod(pc,"PCDeflationSetReductionFactor_C",(PC,PetscInt),(pc,red));CHKERRQ(ierr);
121   PetscFunctionReturn(0);
122 }
123 
124 static PetscErrorCode PCDeflationSetCorrectionFactor_Deflation(PC pc,PetscScalar fact)
125 {
126   PC_Deflation   *def = (PC_Deflation*)pc->data;
127 
128   PetscFunctionBegin;
129   /* TODO PETSC_DETERMINE -> compute max eigenvalue with power method */
130   def->correct = PETSC_TRUE;
131   def->correctfact = fact;
132   if (fact == PETSC_DEFAULT) {
133     def->correctfact = 1.0;
134   } else if (def->correct == 0.0) {
135     def->correct = PETSC_FALSE;
136   }
137   PetscFunctionReturn(0);
138 }
139 
140 /*@
141    PCDeflationSetCorrectionFactor - Set coarse problem correction factor.
142     The Preconditioner becomes P*M^{-1} + factor*Q.
143 
144    Logically Collective on PC
145 
146    Input Parameters:
147 +  pc   - the preconditioner context
148 -  fact - correction factor (set 0.0 to disable, PETSC_DEFAULT = 1.0)
149 
150    Level: intermediate
151 
152 .seealso: PCDEFLATION
153 @*/
154 PetscErrorCode PCDeflationSetCorrectionFactor(PC pc,PetscScalar fact)
155 {
156   PetscErrorCode ierr;
157 
158   PetscFunctionBegin;
159   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
160   PetscValidLogicalCollectiveScalar(pc,fact,2);
161   ierr = PetscTryMethod(pc,"PCDeflationSetCorrectionFactor_C",(PC,PetscScalar),(pc,fact));CHKERRQ(ierr);
162   PetscFunctionReturn(0);
163 }
164 
165 static PetscErrorCode PCDeflationSetSpaceToCompute_Deflation(PC pc,PCDeflationSpaceType type,PetscInt size)
166 {
167   PC_Deflation   *def = (PC_Deflation*)pc->data;
168 
169   PetscFunctionBegin;
170   if (type) def->spacetype = type;
171   if (size > 0) def->spacesize = size;
172   PetscFunctionReturn(0);
173 }
174 
175 /*@
176    PCDeflationSetSpaceToCompute - Set deflation space type and size to compute.
177 
178    Logically Collective on PC
179 
180    Input Parameters:
181 +  pc   - the preconditioner context
182 .  type - deflation space type to compute (or PETSC_IGNORE)
183 -  size - size of the space to compute (or PETSC_DEFAULT)
184 
185    Notes:
186     For wavelet-based deflation, size represents number of levels.
187     The deflation space is computed in PCSetUP().
188 
189    Level: intermediate
190 
191 .seealso: PCDEFLATION
192 @*/
193 PetscErrorCode PCDeflationSetSpaceToCompute(PC pc,PCDeflationSpaceType type,PetscInt size)
194 {
195   PetscErrorCode ierr;
196 
197   PetscFunctionBegin;
198   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
199   if (type) PetscValidLogicalCollectiveEnum(pc,type,2);
200   if (size > 0) PetscValidLogicalCollectiveInt(pc,size,3);
201   ierr = PetscTryMethod(pc,"PCDeflationSetSpaceToCompute_C",(PC,PCDeflationSpaceType,PetscInt),(pc,type,size));CHKERRQ(ierr);
202   PetscFunctionReturn(0);
203 }
204 
205 static PetscErrorCode PCDeflationSetSpace_Deflation(PC pc,Mat W,PetscBool transpose)
206 {
207   PC_Deflation   *def = (PC_Deflation*)pc->data;
208   PetscErrorCode ierr;
209 
210   PetscFunctionBegin;
211   if (transpose) {
212     def->Wt = W;
213     def->W = NULL;
214   } else {
215     def->W = W;
216   }
217   ierr = PetscObjectReference((PetscObject)W);CHKERRQ(ierr);
218   PetscFunctionReturn(0);
219 }
220 
221 /*@
222    PCDeflationSetSpace - Set deflation space matrix (or its transpose).
223 
224    Logically Collective on PC
225 
226    Input Parameters:
227 +  pc - the preconditioner context
228 .  W  - deflation matrix
229 -  tranpose - indicates that W is an explicit transpose of the deflation matrix
230 
231    Level: intermediate
232 
233 .seealso: PCDEFLATION
234 @*/
235 PetscErrorCode PCDeflationSetSpace(PC pc,Mat W,PetscBool transpose)
236 {
237   PetscErrorCode ierr;
238 
239   PetscFunctionBegin;
240   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
241   PetscValidHeaderSpecific(W,MAT_CLASSID,2);
242   PetscValidLogicalCollectiveBool(pc,transpose,3);
243   ierr = PetscTryMethod(pc,"PCDeflationSetSpace_C",(PC,Mat,PetscBool),(pc,W,transpose));CHKERRQ(ierr);
244   PetscFunctionReturn(0);
245 }
246 
247 static PetscErrorCode PCDeflationSetProjectionNullSpaceMat_Deflation(PC pc,Mat mat)
248 {
249   PC_Deflation     *def = (PC_Deflation*)pc->data;
250   PetscErrorCode   ierr;
251 
252   PetscFunctionBegin;
253   ierr = MatDestroy(&def->WtA);CHKERRQ(ierr);
254   def->WtA = mat;
255   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
256   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtA);CHKERRQ(ierr);
257   PetscFunctionReturn(0);
258 }
259 
260 /*@
261    PCDeflationSetProjectionNullSpaceMat - Set projection null space matrix (W'*A).
262 
263    Not Collective
264 
265    Input Parameters:
266 +  pc  - preconditioner context
267 -  mat - projection null space matrix
268 
269    Level: developer
270 
271 .seealso: PCDEFLATION
272 @*/
273 PetscErrorCode  PCDeflationSetProjectionNullSpaceMat(PC pc,Mat mat)
274 {
275   PetscErrorCode ierr;
276 
277   PetscFunctionBegin;
278   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
279   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
280   ierr = PetscTryMethod(pc,"PCDeflationSetProjectionNullSpaceMat_C",(PC,Mat),(pc,mat));CHKERRQ(ierr);
281   PetscFunctionReturn(0);
282 }
283 
284 static PetscErrorCode PCDeflationSetCoarseMat_Deflation(PC pc,Mat mat)
285 {
286   PC_Deflation     *def = (PC_Deflation*)pc->data;
287   PetscErrorCode   ierr;
288 
289   PetscFunctionBegin;
290   ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr);
291   def->WtAW = mat;
292   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
293   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtAW);CHKERRQ(ierr);
294   PetscFunctionReturn(0);
295 }
296 
297 /*@
298    PCDeflationSetCoarseMat - Set coarse problem Mat.
299 
300    Not Collective
301 
302    Input Parameters:
303 +  pc - preconditioner context
304 -  mat - coarse problem mat
305 
306    Level: developer
307 
308 .seealso: PCDEFLATION
309 @*/
310 PetscErrorCode  PCDeflationSetCoarseMat(PC pc,Mat mat)
311 {
312   PetscErrorCode ierr;
313 
314   PetscFunctionBegin;
315   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
316   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
317   ierr = PetscTryMethod(pc,"PCDeflationSetCoarseMat_C",(PC,Mat),(pc,mat));CHKERRQ(ierr);
318   PetscFunctionReturn(0);
319 }
320 
321 static PetscErrorCode PCDeflationGetCoarseKSP_Deflation(PC pc,KSP *ksp)
322 {
323   PC_Deflation     *def = (PC_Deflation*)pc->data;
324 
325   PetscFunctionBegin;
326   *ksp = def->WtAWinv;
327   PetscFunctionReturn(0);
328 }
329 
330 /*@
331    PCDeflationGetCoarseKSP - Returns a pointer to the coarse problem KSP.
332 
333    Not Collective
334 
335    Input Parameters:
336 .  pc - preconditioner context
337 
338    Output Parameter:
339 .  ksp - coarse problem KSP context
340 
341    Level: developer
342 
343 .seealso: PCDeflationSetCoarseKSP(), PCDEFLATION
344 @*/
345 PetscErrorCode  PCDeflationGetCoarseKSP(PC pc,KSP *ksp)
346 {
347   PetscErrorCode ierr;
348 
349   PetscFunctionBegin;
350   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
351   PetscValidPointer(ksp,2);
352   ierr = PetscTryMethod(pc,"PCDeflationGetCoarseKSP_C",(PC,KSP*),(pc,ksp));CHKERRQ(ierr);
353   PetscFunctionReturn(0);
354 }
355 
356 static PetscErrorCode PCDeflationSetCoarseKSP_Deflation(PC pc,KSP ksp)
357 {
358   PC_Deflation     *def = (PC_Deflation*)pc->data;
359   PetscErrorCode   ierr;
360 
361   PetscFunctionBegin;
362   ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr);
363   def->WtAWinv = ksp;
364   ierr = PetscObjectReference((PetscObject)ksp);CHKERRQ(ierr);
365   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtAWinv);CHKERRQ(ierr);
366   PetscFunctionReturn(0);
367 }
368 
369 /*@
370    PCDeflationSetCoarseKSP - Set coarse problem KSP.
371 
372    Collective on PC
373 
374    Input Parameters:
375 +  pc - preconditioner context
376 -  ksp - coarse problem KSP context
377 
378    Level: developer
379 
380 .seealso: PCDeflationGetCoarseKSP(), PCDEFLATION
381 @*/
382 PetscErrorCode  PCDeflationSetCoarseKSP(PC pc,KSP ksp)
383 {
384   PetscErrorCode ierr;
385 
386   PetscFunctionBegin;
387   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
388   PetscValidHeaderSpecific(ksp,KSP_CLASSID,2);
389   PetscCheckSameComm(pc,1,ksp,2);
390   ierr = PetscTryMethod(pc,"PCDeflationSetCoarseKSP_C",(PC,KSP),(pc,ksp));CHKERRQ(ierr);
391   PetscFunctionReturn(0);
392 }
393 
394 static PetscErrorCode PCDeflationGetPC_Deflation(PC pc,PC *apc)
395 {
396   PC_Deflation   *def = (PC_Deflation*)pc->data;
397 
398   PetscFunctionBegin;
399   *apc = def->pc;
400   PetscFunctionReturn(0);
401 }
402 
403 /*@
404    PCDeflationGetPC - Returns a pointer to additional preconditioner.
405 
406    Not Collective
407 
408    Input Parameters:
409 .  pc  - the preconditioner context
410 
411    Output Parameter:
412 .  apc - additional preconditioner
413 
414    Level: advanced
415 
416 .seealso: PCDeflationSetPC(), PCDEFLATION
417 @*/
418 PetscErrorCode PCDeflationGetPC(PC pc,PC *apc)
419 {
420   PetscErrorCode ierr;
421 
422   PetscFunctionBegin;
423   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
424   PetscValidPointer(pc,2);
425   ierr = PetscTryMethod(pc,"PCDeflationGetPC_C",(PC,PC*),(pc,apc));CHKERRQ(ierr);
426   PetscFunctionReturn(0);
427 }
428 
429 static PetscErrorCode PCDeflationSetPC_Deflation(PC pc,PC apc)
430 {
431   PC_Deflation   *def = (PC_Deflation*)pc->data;
432   PetscErrorCode ierr;
433 
434   PetscFunctionBegin;
435   ierr = PCDestroy(&def->pc);CHKERRQ(ierr);
436   def->pc = apc;
437   ierr = PetscObjectReference((PetscObject)apc);CHKERRQ(ierr);
438   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->pc);CHKERRQ(ierr);
439   PetscFunctionReturn(0);
440 }
441 
442 /*@
443    PCDeflationSetPC - Set additional preconditioner.
444 
445    Collective on PC
446 
447    Input Parameters:
448 +  pc  - the preconditioner context
449 -  apc - additional preconditioner
450 
451    Level: developer
452 
453 .seealso: PCDeflationGetPC(), PCDEFLATION
454 @*/
455 PetscErrorCode PCDeflationSetPC(PC pc,PC apc)
456 {
457   PetscErrorCode ierr;
458 
459   PetscFunctionBegin;
460   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
461   PetscValidHeaderSpecific(apc,PC_CLASSID,2);
462   PetscCheckSameComm(pc,1,apc,2);
463   ierr = PetscTryMethod(pc,"PCDeflationSetPC_C",(PC,PC),(pc,apc));CHKERRQ(ierr);
464   PetscFunctionReturn(0);
465 }
466 
467 /*
468   x <- x + W*(W'*A*W)^{-1}*W'*r  = x + Q*r
469 */
470 static PetscErrorCode PCPreSolve_Deflation(PC pc,KSP ksp,Vec b, Vec x)
471 {
472   PC_Deflation     *def = (PC_Deflation*)pc->data;
473   Mat              A;
474   Vec              r,w1,w2;
475   PetscBool        nonzero;
476   PetscErrorCode   ierr;
477 
478   PetscFunctionBegin;
479   w1 = def->workcoarse[0];
480   w2 = def->workcoarse[1];
481   r  = def->work;
482   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
483 
484   ierr = KSPGetInitialGuessNonzero(ksp,&nonzero);CHKERRQ(ierr);
485   ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
486   if (nonzero) {
487     ierr = MatMult(A,x,r);CHKERRQ(ierr);                          /*    r  <- b - Ax              */
488     ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr);
489   } else {
490     ierr = VecCopy(b,r);CHKERRQ(ierr);                            /*    r  <- b (x is 0)          */
491   }
492 
493   if (def->Wt) {
494     ierr = MatMult(def->Wt,r,w1);CHKERRQ(ierr);                   /*    w1 <- W'*r                */
495   } else {
496     ierr = MatMultHermitianTranspose(def->W,r,w1);CHKERRQ(ierr);  /*    w1 <- W'*r                */
497   }
498   ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);              /*    w2 <- (W'*A*W)^{-1}*w1    */
499   ierr = MatMult(def->W,w2,r);CHKERRQ(ierr);                      /*    r  <- W*w2                */
500   ierr = VecAYPX(x,1.0,r);CHKERRQ(ierr);
501   PetscFunctionReturn(0);
502 }
503 
504 /*
505   if (def->correct) {
506     z <- M^{-1}r - W*(W'*A*W)^{-1}*(W'*A*M^{-1}r - l*W'*r) = (P*M^{-1} + l*Q)*r
507   } else {
508     z <- M^{-1}*r - W*(W'*A*W)^{-1}*W'*A*M{-1}*r = P*M^{-1}*r
509   }
510 */
511 static PetscErrorCode PCApply_Deflation(PC pc,Vec r,Vec z)
512 {
513   PC_Deflation     *def = (PC_Deflation*)pc->data;
514   Mat              A;
515   Vec              u,w1,w2;
516   PetscErrorCode   ierr;
517 
518   PetscFunctionBegin;
519   w1 = def->workcoarse[0];
520   w2 = def->workcoarse[1];
521   u  = def->work;
522   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
523 
524   ierr = PCApply(def->pc,r,z);CHKERRQ(ierr);                          /*    z <- M^{-1}*r             */
525   if (!def->init) {
526     ierr = MatMult(def->WtA,z,w1);CHKERRQ(ierr);                      /*    w1 <- W'*A*z              */
527     if (def->correct) {
528       if (def->Wt) {
529         ierr = MatMult(def->Wt,r,w2);CHKERRQ(ierr);                   /*    w2 <- W'*r                */
530       } else {
531         ierr = MatMultHermitianTranspose(def->W,r,w2);CHKERRQ(ierr);  /*    w2 <- W'*r                */
532       }
533       ierr = VecAXPY(w1,-1.0*def->correctfact,w2);CHKERRQ(ierr);      /*    w1 <- w1 - l*w2           */
534     }
535     ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);                /*    w2 <- (W'*A*W)^{-1}*w1    */
536     ierr = MatMult(def->W,w2,u);CHKERRQ(ierr);                        /*    u  <- W*w2                */
537     ierr = VecAXPY(z,-1.0,u);CHKERRQ(ierr);                           /*    z  <- z - u               */
538   }
539   PetscFunctionReturn(0);
540 }
541 
542 static PetscErrorCode PCSetUp_Deflation(PC pc)
543 {
544   PC_Deflation     *def = (PC_Deflation*)pc->data;
545   KSP              innerksp;
546   PC               pcinner;
547   Mat              Amat,nextDef=NULL,*mats;
548   PetscInt         i,m,red,size,commsize;
549   PetscBool        match,flgspd,transp=PETSC_FALSE;
550   MatCompositeType ctype;
551   MPI_Comm         comm;
552   const char       *prefix;
553   PetscErrorCode   ierr;
554 
555   PetscFunctionBegin;
556   if (pc->setupcalled) PetscFunctionReturn(0);
557   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
558   ierr = PCGetOperators(pc,NULL,&Amat);CHKERRQ(ierr);
559   ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
560 
561   /* compute a deflation space */
562   if (def->W || def->Wt) {
563     def->spacetype = PC_DEFLATION_SPACE_USER;
564   } else {
565     ierr = PCDeflationComputeSpace(pc);CHKERRQ(ierr);
566   }
567 
568   /* nested deflation */
569   if (def->W) {
570     ierr = PetscObjectTypeCompare((PetscObject)def->W,MATCOMPOSITE,&match);CHKERRQ(ierr);
571     if (match) {
572       ierr = MatCompositeGetType(def->W,&ctype);CHKERRQ(ierr);
573       ierr = MatCompositeGetNumberMat(def->W,&size);CHKERRQ(ierr);
574     }
575   } else {
576     ierr = MatCreateHermitianTranspose(def->Wt,&def->W);CHKERRQ(ierr);
577     ierr = PetscObjectTypeCompare((PetscObject)def->Wt,MATCOMPOSITE,&match);CHKERRQ(ierr);
578     if (match) {
579       ierr = MatCompositeGetType(def->Wt,&ctype);CHKERRQ(ierr);
580       ierr = MatCompositeGetNumberMat(def->Wt,&size);CHKERRQ(ierr);
581     }
582     transp = PETSC_TRUE;
583   }
584   if (match && ctype == MAT_COMPOSITE_MULTIPLICATIVE) {
585     if (!transp) {
586       if (def->nestedlvl < def->maxnestedlvl) {
587         ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
588         for (i=0; i<size; i++) {
589           ierr = MatCompositeGetMat(def->W,i,&mats[i]);CHKERRQ(ierr);
590         }
591         size -= 1;
592         ierr = MatDestroy(&def->W);CHKERRQ(ierr);
593         def->W = mats[size];
594         ierr = PetscObjectReference((PetscObject)mats[size]);CHKERRQ(ierr);
595         if (size > 1) {
596           ierr = MatCreateComposite(comm,size,mats,&nextDef);CHKERRQ(ierr);
597           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
598         } else {
599           nextDef = mats[0];
600           ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
601         }
602         ierr = PetscFree(mats);CHKERRQ(ierr);
603       } else {
604         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
605         ierr = MatCompositeMerge(def->W);CHKERRQ(ierr);
606       }
607     } else {
608       if (def->nestedlvl < def->maxnestedlvl) {
609         ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
610         for (i=0; i<size; i++) {
611           ierr = MatCompositeGetMat(def->Wt,i,&mats[i]);CHKERRQ(ierr);
612         }
613         size -= 1;
614         ierr = MatDestroy(&def->Wt);CHKERRQ(ierr);
615         def->Wt = mats[0];
616         ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
617         if (size > 1) {
618           ierr = MatCreateComposite(comm,size,&mats[1],&nextDef);CHKERRQ(ierr);
619           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
620         } else {
621           nextDef = mats[1];
622           ierr = PetscObjectReference((PetscObject)mats[1]);CHKERRQ(ierr);
623         }
624         ierr = PetscFree(mats);CHKERRQ(ierr);
625       } else {
626         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
627         ierr = MatCompositeMerge(def->Wt);CHKERRQ(ierr);
628       }
629     }
630   }
631 
632   if (transp) {
633     ierr = MatDestroy(&def->W);CHKERRQ(ierr);
634     ierr = MatHermitianTranspose(def->Wt,MAT_INITIAL_MATRIX,&def->W);CHKERRQ(ierr);
635   }
636 
637   /* assemble WtA */
638   if (!def->WtA) {
639     if (def->Wt) {
640       ierr = MatMatMult(def->Wt,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr);
641     } else {
642 #if defined(PETSC_USE_COMPLEX)
643       ierr = MatHermitianTranspose(def->W,MAT_INITIAL_MATRIX,&def->Wt);CHKERRQ(ierr);
644       ierr = MatMatMult(def->W,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr);
645 #else
646       ierr = MatTransposeMatMult(def->W,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr);
647 #endif
648     }
649   }
650   /* setup coarse problem */
651   if (!def->WtAWinv) {
652     ierr = MatGetSize(def->W,NULL,&m);CHKERRQ(ierr);
653     if (!def->WtAW) {
654       ierr = MatMatMult(def->WtA,def->W,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr);
655       /* TODO create MatInheritOption(Mat,MatOption) */
656       ierr = MatGetOption(Amat,MAT_SPD,&flgspd);CHKERRQ(ierr);
657       ierr = MatSetOption(def->WtAW,MAT_SPD,flgspd);CHKERRQ(ierr);
658 #if defined(PETSC_USE_DEBUG)
659       /* Check columns of W are not in kernel of A */
660       PetscReal *norms;
661       ierr = PetscMalloc1(m,&norms);CHKERRQ(ierr);
662       ierr = MatGetColumnNorms(def->WtAW,NORM_INFINITY,norms);CHKERRQ(ierr);
663       for (i=0; i<m; i++) {
664         if (norms[i] < 100*PETSC_MACHINE_EPSILON) {
665           SETERRQ1(comm,PETSC_ERR_SUP,"Column %D of W is in kernel of A.",i);
666         }
667       }
668       ierr = PetscFree(norms);CHKERRQ(ierr);
669 #endif
670     } else {
671       ierr = MatGetOption(def->WtAW,MAT_SPD,&flgspd);CHKERRQ(ierr);
672     }
673     /* TODO use MATINV */
674     ierr = KSPCreate(comm,&def->WtAWinv);CHKERRQ(ierr);
675     ierr = KSPSetOperators(def->WtAWinv,def->WtAW,def->WtAW);CHKERRQ(ierr);
676     ierr = KSPGetPC(def->WtAWinv,&pcinner);CHKERRQ(ierr);
677     /* Setup KSP and PC */
678     if (nextDef) { /* next level for multilevel deflation */
679       innerksp = def->WtAWinv;
680       /* set default KSPtype */
681       if (!def->ksptype) {
682         def->ksptype = KSPFGMRES;
683         if (flgspd) { /* SPD system */
684           def->ksptype = KSPFCG;
685         }
686       }
687       ierr = KSPSetType(innerksp,def->ksptype);CHKERRQ(ierr); /* TODO iherit from KSP + tolerances */
688       ierr = PCSetType(pcinner,PCDEFLATION);CHKERRQ(ierr); /* TODO create coarse preconditinoner M_c = WtMW ? */
689       ierr = PCDeflationSetSpace(pcinner,nextDef,transp);CHKERRQ(ierr);
690       ierr = PCDeflationSetLvl_Deflation(pcinner,def->nestedlvl+1,def->maxnestedlvl);CHKERRQ(ierr);
691       /* inherit options */
692       ((PC_Deflation*)(pcinner->data))->ksptype = def->ksptype;
693       ((PC_Deflation*)(pcinner->data))->correct = def->correct;
694       ierr = MatDestroy(&nextDef);CHKERRQ(ierr);
695     } else { /* the last level */
696       ierr = KSPSetType(def->WtAWinv,KSPPREONLY);CHKERRQ(ierr);
697       ierr = PCSetType(pcinner,PCTELESCOPE);CHKERRQ(ierr);
698       /* ugly hack to not have overwritten PCTELESCOPE */
699       if (prefix) {
700         ierr = KSPSetOptionsPrefix(def->WtAWinv,prefix);CHKERRQ(ierr);
701       }
702       ierr = KSPAppendOptionsPrefix(def->WtAWinv,"tel_");CHKERRQ(ierr);
703       ierr = PCSetFromOptions(pcinner);CHKERRQ(ierr);
704       /* Reduction factor choice */
705       red = def->reductionfact;
706       if (red < 0) {
707         ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
708         red  = ceil((float)commsize/ceil((float)m/commsize));
709         ierr = PetscObjectTypeCompareAny((PetscObject)(def->WtAW),&match,MATSEQDENSE,MATMPIDENSE,MATDENSE,"");CHKERRQ(ierr);
710         if (match) red = commsize;
711         ierr = PetscInfo1(pc,"Auto choosing reduction factor %D\n",red);CHKERRQ(ierr); /* TODO add level? */
712       }
713       ierr = PCTelescopeSetReductionFactor(pcinner,red);CHKERRQ(ierr);
714       ierr = PCSetUp(pcinner);CHKERRQ(ierr);
715       ierr = PCTelescopeGetKSP(pcinner,&innerksp);CHKERRQ(ierr);
716       if (innerksp) {
717         ierr = KSPGetPC(innerksp,&pcinner);CHKERRQ(ierr);
718         /* TODO Cholesky if flgspd? */
719         ierr = PCSetType(pcinner,PCLU);CHKERRQ(ierr);
720         //TODO remove explicit matSolverPackage
721         if (commsize == red) {
722           ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU);CHKERRQ(ierr);
723         } else {
724           ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU_DIST);CHKERRQ(ierr);
725         }
726       }
727     }
728 
729     if (innerksp) {
730       /* TODO use def_[lvl]_ if lvl > 0? */
731       if (prefix) {
732         ierr = KSPSetOptionsPrefix(innerksp,prefix);CHKERRQ(ierr);
733       }
734       ierr = KSPAppendOptionsPrefix(innerksp,"def_");CHKERRQ(ierr);
735       ierr = KSPSetFromOptions(innerksp);CHKERRQ(ierr);
736       ierr = KSPSetUp(innerksp);CHKERRQ(ierr);
737     }
738   }
739   ierr = KSPSetFromOptions(def->WtAWinv);CHKERRQ(ierr);
740   ierr = KSPSetUp(def->WtAWinv);CHKERRQ(ierr);
741 
742   if (!def->pc) {
743     ierr = PCCreate(comm,&def->pc);CHKERRQ(ierr);
744     ierr = PCSetOperators(def->pc,Amat,Amat);CHKERRQ(ierr);
745     ierr = PCSetType(def->pc,PCNONE);CHKERRQ(ierr);
746     if (prefix) {
747       ierr = PCSetOptionsPrefix(def->pc,prefix);CHKERRQ(ierr);
748     }
749     ierr = PCAppendOptionsPrefix(def->pc,"def_pc_");CHKERRQ(ierr);
750     ierr = PCSetFromOptions(def->pc);CHKERRQ(ierr);
751     ierr = PCSetUp(def->pc);CHKERRQ(ierr);
752   }
753 
754   /* create work vecs */
755   ierr = MatCreateVecs(Amat,NULL,&def->work);CHKERRQ(ierr);
756   ierr = KSPCreateVecs(def->WtAWinv,2,&def->workcoarse,0,NULL);CHKERRQ(ierr);
757   PetscFunctionReturn(0);
758 }
759 
760 static PetscErrorCode PCReset_Deflation(PC pc)
761 {
762   PC_Deflation      *def = (PC_Deflation*)pc->data;
763   PetscErrorCode    ierr;
764 
765   PetscFunctionBegin;
766   ierr = VecDestroy(&def->work);CHKERRQ(ierr);
767   ierr = VecDestroyVecs(2,&def->workcoarse);CHKERRQ(ierr);
768   ierr = MatDestroy(&def->W);CHKERRQ(ierr);
769   ierr = MatDestroy(&def->Wt);CHKERRQ(ierr);
770   ierr = MatDestroy(&def->WtA);CHKERRQ(ierr);
771   ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr);
772   ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr);
773   ierr = PCDestroy(&def->pc);CHKERRQ(ierr);
774   PetscFunctionReturn(0);
775 }
776 
777 /*
778    PCDestroy_Deflation - Destroys the private context for the Deflation preconditioner
779    that was created with PCCreate_Deflation().
780 
781    Input Parameter:
782 .  pc - the preconditioner context
783 
784    Application Interface Routine: PCDestroy()
785 */
786 static PetscErrorCode PCDestroy_Deflation(PC pc)
787 {
788   PetscErrorCode ierr;
789 
790   PetscFunctionBegin;
791   ierr = PCReset_Deflation(pc);CHKERRQ(ierr);
792   ierr = PetscFree(pc->data);CHKERRQ(ierr);
793   PetscFunctionReturn(0);
794 }
795 
796 static PetscErrorCode PCView_Deflation(PC pc,PetscViewer viewer)
797 {
798   PC_Deflation      *def = (PC_Deflation*)pc->data;
799   PetscInt          its;
800   PetscBool         iascii;
801   PetscErrorCode    ierr;
802 
803   PetscFunctionBegin;
804   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
805   if (iascii) {
806     if (def->correct) {
807       ierr = PetscViewerASCIIPrintf(viewer,"using CP correction, factor = %g+%gi\n",
808                                     (double)PetscRealPart(def->correctfact),
809                                     (double)PetscImaginaryPart(def->correctfact));CHKERRQ(ierr);
810     }
811     if (!def->nestedlvl) {
812       ierr = PetscViewerASCIIPrintf(viewer,"deflation space type: %s\n",PCDeflationSpaceTypes[def->spacetype]);CHKERRQ(ierr);
813     }
814 
815     ierr = PetscViewerASCIIPrintf(viewer,"--- Additional PC:\n");CHKERRQ(ierr);
816     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
817     ierr = PCView(def->pc,viewer);CHKERRQ(ierr);
818     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
819 
820     ierr = PetscViewerASCIIPrintf(viewer,"--- Coarse problem solver:\n");CHKERRQ(ierr);
821     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
822     ierr = KSPGetTotalIterations(def->WtAWinv,&its);CHKERRQ(ierr);
823     ierr = PetscViewerASCIIPrintf(viewer,"total number of iterations: %D\n",its);CHKERRQ(ierr);
824     ierr = KSPView(def->WtAWinv,viewer);CHKERRQ(ierr);
825     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
826   }
827   PetscFunctionReturn(0);
828 }
829 
830 static PetscErrorCode PCSetFromOptions_Deflation(PetscOptionItems *PetscOptionsObject,PC pc)
831 {
832   PC_Deflation      *def = (PC_Deflation*)pc->data;
833   PetscErrorCode    ierr;
834 
835   PetscFunctionBegin;
836   ierr = PetscOptionsHead(PetscOptionsObject,"Deflation options");CHKERRQ(ierr);
837   ierr = PetscOptionsBool("-pc_deflation_init_only","Use only initialization step - Initdef","PCDeflationSetInitOnly",def->init,&def->init,NULL);CHKERRQ(ierr);
838   ierr = PetscOptionsInt("-pc_deflation_max_lvl","Maximum of deflation levels","PCDeflationSetMaxLvl",def->maxnestedlvl,&def->maxnestedlvl,NULL);CHKERRQ(ierr);
839   ierr = PetscOptionsInt("-pc_deflation_reduction_factor","Reduction factor for coarse problem solution using PCTELESCOPE","PCDeflationSetReductionFactor",def->reductionfact,&def->reductionfact,NULL);CHKERRQ(ierr);
840   ierr = PetscOptionsBool("-pc_deflation_correction","Add coarse problem correction Q to P","PCDeflationSetCorrectionFactor",def->correct,&def->correct,NULL);CHKERRQ(ierr);
841   ierr = PetscOptionsScalar("-pc_deflation_correction_factor","Set multiple of Q to use as coarse problem correction","PCDeflationSetCorrectionFactor",def->correctfact,&def->correctfact,NULL);CHKERRQ(ierr);
842   ierr = PetscOptionsEnum("-pc_deflation_compute_space","Compute deflation space","PCDeflationSetSpace",PCDeflationSpaceTypes,(PetscEnum)def->spacetype,(PetscEnum*)&def->spacetype,NULL);CHKERRQ(ierr);
843   ierr = PetscOptionsInt("-pc_deflation_compute_space_size","Set size of the deflation space to compute","PCDeflationSetSpace",def->spacesize,&def->spacesize,NULL);CHKERRQ(ierr);
844   ierr = PetscOptionsBool("-pc_deflation_space_extend","Extend deflation space instead of truncating (wavelets)","PCDeflation",def->extendsp,&def->extendsp,NULL);CHKERRQ(ierr);
845 //TODO add set function and fix manpages
846   ierr = PetscOptionsTail();CHKERRQ(ierr);
847   PetscFunctionReturn(0);
848 }
849 
850 /*MC
851      PCDEFLATION - Deflation preconditioner shifts part of the spectrum to zero (deflates)
852      or to a predefined value
853 
854    Options Database Key:
855 +    -pc_deflation_type <init,pre,post> - selects approach to deflation (default: pre)
856 -    -pc_jacobi_abs - use the absolute value of the diagonal entry
857 
858    Level: beginner
859 
860   Notes:
861     todo
862 
863 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
864            PCDeflationSetType(), PCDeflationSetSpace()
865 M*/
866 
867 PETSC_EXTERN PetscErrorCode PCCreate_Deflation(PC pc)
868 {
869   PC_Deflation   *def;
870   PetscErrorCode ierr;
871 
872   PetscFunctionBegin;
873   ierr     = PetscNewLog(pc,&def);CHKERRQ(ierr);
874   pc->data = (void*)def;
875 
876   def->init          = PETSC_FALSE;
877   def->correct       = PETSC_FALSE;
878   def->correctfact   = 1.0;
879   def->reductionfact = -1;
880   def->spacetype     = PC_DEFLATION_SPACE_HAAR;
881   def->spacesize     = 1;
882   def->extendsp      = PETSC_FALSE;
883   def->nestedlvl     = 0;
884   def->maxnestedlvl  = 0;
885 
886   pc->ops->apply          = PCApply_Deflation;
887   pc->ops->presolve       = PCPreSolve_Deflation;
888   pc->ops->setup          = PCSetUp_Deflation;
889   pc->ops->reset          = PCReset_Deflation;
890   pc->ops->destroy        = PCDestroy_Deflation;
891   pc->ops->setfromoptions = PCSetFromOptions_Deflation;
892   pc->ops->view           = PCView_Deflation;
893 
894   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetInitOnly_C",PCDeflationSetInitOnly_Deflation);CHKERRQ(ierr);
895   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetLvl_C",PCDeflationSetLvl_Deflation);CHKERRQ(ierr);
896   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetReductionFactor_C",PCDeflationSetReductionFactor_Deflation);CHKERRQ(ierr);
897   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCorrectionFactor_C",PCDeflationSetCorrectionFactor_Deflation);CHKERRQ(ierr);
898   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpaceToCompute_C",PCDeflationSetSpaceToCompute_Deflation);CHKERRQ(ierr);
899   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpace_C",PCDeflationSetSpace_Deflation);CHKERRQ(ierr);
900   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetProjectionNullSpaceMat_C",PCDeflationSetProjectionNullSpaceMat_Deflation);CHKERRQ(ierr);
901   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCoarseMat_C",PCDeflationSetCoarseMat_Deflation);CHKERRQ(ierr);
902   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetCoarseKSP_C",PCDeflationGetCoarseKSP_Deflation);CHKERRQ(ierr);
903   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCoarseKSP_C",PCDeflationSetCoarseKSP_Deflation);CHKERRQ(ierr);
904   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetPC_C",PCDeflationGetPC_Deflation);CHKERRQ(ierr);
905   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetPC_C",PCDeflationSetPC_Deflation);CHKERRQ(ierr);
906   PetscFunctionReturn(0);
907 }
908 
909