Actual source code: deflation.c

  1: #include <../src/ksp/pc/impls/deflation/deflation.h>

  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:   NULL
 16: };

 18: static PetscErrorCode PCDeflationSetInitOnly_Deflation(PC pc,PetscBool flg)
 19: {
 20:   PC_Deflation   *def = (PC_Deflation*)pc->data;

 23:   def->init = flg;
 24:   return(0);
 25: }

 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.

 32:    Logically Collective

 34:    Input Parameters:
 35: +  pc  - the preconditioner context
 36: -  flg - default PETSC_FALSE

 38:    Options Database Keys:
 39: .    -pc_deflation_init_only <false> - if true computes only the special guess

 41:    Level: intermediate

 43: .seealso: PCDEFLATION
 44: @*/
 45: PetscErrorCode PCDeflationSetInitOnly(PC pc,PetscBool flg)
 46: {

 52:   PetscTryMethod(pc,"PCDeflationSetInitOnly_C",(PC,PetscBool),(pc,flg));
 53:   return(0);
 54: }

 56: static PetscErrorCode PCDeflationSetLevels_Deflation(PC pc,PetscInt current,PetscInt max)
 57: {
 58:   PC_Deflation   *def = (PC_Deflation*)pc->data;

 61:   if (current) def->lvl = current;
 62:   def->maxlvl = max;
 63:   return(0);
 64: }

 66: /*@
 67:    PCDeflationSetLevels - Set the maximum level of deflation nesting.

 69:    Logically Collective

 71:    Input Parameters:
 72: +  pc  - the preconditioner context
 73: -  max - maximum deflation level

 75:    Options Database Keys:
 76: .    -pc_deflation_max_lvl <0> - maximum number of levels for multilevel deflation

 78:    Level: intermediate

 80: .seealso: PCDeflationSetSpaceToCompute(), PCDeflationSetSpace(), PCDEFLATION
 81: @*/
 82: PetscErrorCode PCDeflationSetLevels(PC pc,PetscInt max)
 83: {

 89:   PetscTryMethod(pc,"PCDeflationSetLevels_C",(PC,PetscInt,PetscInt),(pc,0,max));
 90:   return(0);
 91: }

 93: static PetscErrorCode PCDeflationSetReductionFactor_Deflation(PC pc,PetscInt red)
 94: {
 95:   PC_Deflation   *def = (PC_Deflation*)pc->data;

 98:   def->reductionfact = red;
 99:   return(0);
100: }

102: /*@
103:    PCDeflationSetReductionFactor - Set reduction factor for the bottom PCTELESCOPE coarse problem solver.

105:    Logically Collective

107:    Input Parameters:
108: +  pc  - the preconditioner context
109: -  red - reduction factor (or PETSC_DETERMINE)

111:    Options Database Keys:
112: .    -pc_deflation_reduction_factor <\-1> - reduction factor on bottom level coarse problem for PCTELESCOPE

114:    Notes:
115:      Default is computed based on the size of the coarse problem.

117:    Level: intermediate

119: .seealso: PCTELESCOPE, PCDEFLATION
120: @*/
121: PetscErrorCode PCDeflationSetReductionFactor(PC pc,PetscInt red)
122: {

128:   PetscTryMethod(pc,"PCDeflationSetReductionFactor_C",(PC,PetscInt),(pc,red));
129:   return(0);
130: }

132: static PetscErrorCode PCDeflationSetCorrectionFactor_Deflation(PC pc,PetscScalar fact)
133: {
134:   PC_Deflation   *def = (PC_Deflation*)pc->data;

137:   /* TODO PETSC_DETERMINE -> compute max eigenvalue with power method */
138:   def->correct = PETSC_TRUE;
139:   def->correctfact = fact;
140:   if (def->correct == 0.0) {
141:     def->correct = PETSC_FALSE;
142:   }
143:   return(0);
144: }

146: /*@
147:    PCDeflationSetCorrectionFactor - Set coarse problem correction factor.
148:     The Preconditioner becomes P*M^{-1} + fact*Q.

150:    Logically Collective

152:    Input Parameters:
153: +  pc   - the preconditioner context
154: -  fact - correction factor

156:    Options Database Keys:
157: +    -pc_deflation_correction        <false> - if true apply coarse problem correction
158: -    -pc_deflation_correction_factor <1.0>   - sets coarse problem correction factor

160:    Notes:
161:     Any non-zero fact enables the coarse problem correction.

163:    Level: intermediate

165: .seealso: PCDEFLATION
166: @*/
167: PetscErrorCode PCDeflationSetCorrectionFactor(PC pc,PetscScalar fact)
168: {

174:   PetscTryMethod(pc,"PCDeflationSetCorrectionFactor_C",(PC,PetscScalar),(pc,fact));
175:   return(0);
176: }

178: static PetscErrorCode PCDeflationSetSpaceToCompute_Deflation(PC pc,PCDeflationSpaceType type,PetscInt size)
179: {
180:   PC_Deflation   *def = (PC_Deflation*)pc->data;

183:   if (type) def->spacetype = type;
184:   if (size > 0) def->spacesize = size;
185:   return(0);
186: }

188: /*@
189:    PCDeflationSetSpaceToCompute - Set deflation space type and size to compute.

191:    Logically Collective

193:    Input Parameters:
194: +  pc   - the preconditioner context
195: .  type - deflation space type to compute (or PETSC_IGNORE)
196: -  size - size of the space to compute (or PETSC_DEFAULT)

198:    Options Database Keys:
199: +    -pc_deflation_compute_space      <haar> - compute PCDeflationSpaceType deflation space
200: -    -pc_deflation_compute_space_size <1>    - size of the deflation space

202:    Notes:
203:     For wavelet-based deflation, size represents number of levels.

205:     The deflation space is computed in PCSetUp().

207:    Level: intermediate

209: .seealso: PCDeflationSetLevels(), PCDEFLATION
210: @*/
211: PetscErrorCode PCDeflationSetSpaceToCompute(PC pc,PCDeflationSpaceType type,PetscInt size)
212: {

219:   PetscTryMethod(pc,"PCDeflationSetSpaceToCompute_C",(PC,PCDeflationSpaceType,PetscInt),(pc,type,size));
220:   return(0);
221: }

223: static PetscErrorCode PCDeflationSetSpace_Deflation(PC pc,Mat W,PetscBool transpose)
224: {
225:   PC_Deflation   *def = (PC_Deflation*)pc->data;

229:   /* possibly allows W' = Wt (which is valid but not tested) */
230:   PetscObjectReference((PetscObject)W);
231:   if (transpose) {
232:     MatDestroy(&def->Wt);
233:     def->Wt = W;
234:   } else {
235:     MatDestroy(&def->W);
236:     def->W = W;
237:   }
238:   return(0);
239: }

241: /*@
242:    PCDeflationSetSpace - Set the deflation space matrix (or its (Hermitian) transpose).

244:    Logically Collective

246:    Input Parameters:
247: +  pc        - the preconditioner context
248: .  W         - deflation matrix
249: -  transpose - indicates that W is an explicit transpose of the deflation matrix

251:    Notes:
252:     Setting W as a multipliplicative MATCOMPOSITE enables use of the multilevel
253:     deflation. If W = W0*W1*W2*...*Wn, W0 is taken as the first deflation space and
254:     the coarse problem (W0'*A*W0)^{-1} is again preconditioned by deflation with
255:     W1 as the deflation matrix. This repeats until the maximum level set by
256:     PCDeflationSetLevels() is reached or there are no more matrices available.
257:     If there are matrices left after reaching the maximum level,
258:     they are merged into a deflation matrix ...*W{n-1}*Wn.

260:    Level: intermediate

262: .seealso: PCDeflationSetLevels(), PCDEFLATION
263: @*/
264: PetscErrorCode PCDeflationSetSpace(PC pc,Mat W,PetscBool transpose)
265: {

272:   PetscTryMethod(pc,"PCDeflationSetSpace_C",(PC,Mat,PetscBool),(pc,W,transpose));
273:   return(0);
274: }

276: static PetscErrorCode PCDeflationSetProjectionNullSpaceMat_Deflation(PC pc,Mat mat)
277: {
278:   PC_Deflation     *def = (PC_Deflation*)pc->data;
279:   PetscErrorCode   ierr;

282:   PetscObjectReference((PetscObject)mat);
283:   MatDestroy(&def->WtA);
284:   def->WtA = mat;
285:   PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtA);
286:   return(0);
287: }

289: /*@
290:    PCDeflationSetProjectionNullSpaceMat - Set the projection null space matrix (W'*A).

292:    Collective

294:    Input Parameters:
295: +  pc  - preconditioner context
296: -  mat - projection null space matrix

298:    Level: developer

300: .seealso: PCDEFLATION
301: @*/
302: PetscErrorCode  PCDeflationSetProjectionNullSpaceMat(PC pc,Mat mat)
303: {

309:   PetscTryMethod(pc,"PCDeflationSetProjectionNullSpaceMat_C",(PC,Mat),(pc,mat));
310:   return(0);
311: }

313: static PetscErrorCode PCDeflationSetCoarseMat_Deflation(PC pc,Mat mat)
314: {
315:   PC_Deflation     *def = (PC_Deflation*)pc->data;
316:   PetscErrorCode   ierr;

319:   PetscObjectReference((PetscObject)mat);
320:   MatDestroy(&def->WtAW);
321:   def->WtAW = mat;
322:   PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtAW);
323:   return(0);
324: }

326: /*@
327:    PCDeflationSetCoarseMat - Set the coarse problem Mat.

329:    Collective

331:    Input Parameters:
332: +  pc  - preconditioner context
333: -  mat - coarse problem mat

335:    Level: developer

337: .seealso: PCDEFLATION
338: @*/
339: PetscErrorCode  PCDeflationSetCoarseMat(PC pc,Mat mat)
340: {

346:   PetscTryMethod(pc,"PCDeflationSetCoarseMat_C",(PC,Mat),(pc,mat));
347:   return(0);
348: }

350: static PetscErrorCode PCDeflationGetCoarseKSP_Deflation(PC pc,KSP *ksp)
351: {
352:   PC_Deflation     *def = (PC_Deflation*)pc->data;

355:   *ksp = def->WtAWinv;
356:   return(0);
357: }

359: /*@
360:    PCDeflationGetCoarseKSP - Returns the coarse problem KSP.

362:    Not Collective

364:    Input Parameters:
365: .  pc - preconditioner context

367:    Output Parameters:
368: .  ksp - coarse problem KSP context

370:    Level: advanced

372: .seealso: PCDEFLATION
373: @*/
374: PetscErrorCode  PCDeflationGetCoarseKSP(PC pc,KSP *ksp)
375: {

381:   PetscTryMethod(pc,"PCDeflationGetCoarseKSP_C",(PC,KSP*),(pc,ksp));
382:   return(0);
383: }

385: static PetscErrorCode PCDeflationGetPC_Deflation(PC pc,PC *apc)
386: {
387:   PC_Deflation   *def = (PC_Deflation*)pc->data;

390:   *apc = def->pc;
391:   return(0);
392: }

394: /*@
395:    PCDeflationGetPC - Returns the additional preconditioner M^{-1}.

397:    Not Collective

399:    Input Parameters:
400: .  pc  - the preconditioner context

402:    Output Parameters:
403: .  apc - additional preconditioner

405:    Level: advanced

407: .seealso: PCDEFLATION
408: @*/
409: PetscErrorCode PCDeflationGetPC(PC pc,PC *apc)
410: {

416:   PetscTryMethod(pc,"PCDeflationGetPC_C",(PC,PC*),(pc,apc));
417:   return(0);
418: }

420: /*
421:   x <- x + W*(W'*A*W)^{-1}*W'*r  = x + Q*r
422: */
423: static PetscErrorCode PCPreSolve_Deflation(PC pc,KSP ksp,Vec b, Vec x)
424: {
425:   PC_Deflation     *def = (PC_Deflation*)pc->data;
426:   Mat              A;
427:   Vec              r,w1,w2;
428:   PetscBool        nonzero;
429:   PetscErrorCode   ierr;

432:   w1 = def->workcoarse[0];
433:   w2 = def->workcoarse[1];
434:   r  = def->work;
435:   PCGetOperators(pc,NULL,&A);

437:   KSPGetInitialGuessNonzero(ksp,&nonzero);
438:   KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);
439:   if (nonzero) {
440:     MatMult(A,x,r);                          /*    r  <- b - Ax              */
441:     VecAYPX(r,-1.0,b);
442:   } else {
443:     VecCopy(b,r);                            /*    r  <- b (x is 0)          */
444:   }

446:   if (def->Wt) {
447:     MatMult(def->Wt,r,w1);                   /*    w1 <- W'*r                */
448:   } else {
449:     MatMultHermitianTranspose(def->W,r,w1);  /*    w1 <- W'*r                */
450:   }
451:   KSPSolve(def->WtAWinv,w1,w2);              /*    w2 <- (W'*A*W)^{-1}*w1    */
452:   MatMult(def->W,w2,r);                      /*    r  <- W*w2                */
453:   VecAYPX(x,1.0,r);
454:   return(0);
455: }

457: /*
458:   if (def->correct) {
459:     z <- M^{-1}r - W*(W'*A*W)^{-1}*(W'*A*M^{-1}r - l*W'*r) = (P*M^{-1} + l*Q)*r
460:   } else {
461:     z <- M^{-1}*r - W*(W'*A*W)^{-1}*W'*A*M{-1}*r = P*M^{-1}*r
462:   }
463: */
464: static PetscErrorCode PCApply_Deflation(PC pc,Vec r,Vec z)
465: {
466:   PC_Deflation     *def = (PC_Deflation*)pc->data;
467:   Mat              A;
468:   Vec              u,w1,w2;
469:   PetscErrorCode   ierr;

472:   w1 = def->workcoarse[0];
473:   w2 = def->workcoarse[1];
474:   u  = def->work;
475:   PCGetOperators(pc,NULL,&A);

477:   PCApply(def->pc,r,z);                          /*    z <- M^{-1}*r             */
478:   if (!def->init) {
479:     MatMult(def->WtA,z,w1);                      /*    w1 <- W'*A*z              */
480:     if (def->correct) {
481:       if (def->Wt) {
482:         MatMult(def->Wt,r,w2);                   /*    w2 <- W'*r                */
483:       } else {
484:         MatMultHermitianTranspose(def->W,r,w2);  /*    w2 <- W'*r                */
485:       }
486:       VecAXPY(w1,-1.0*def->correctfact,w2);      /*    w1 <- w1 - l*w2           */
487:     }
488:     KSPSolve(def->WtAWinv,w1,w2);                /*    w2 <- (W'*A*W)^{-1}*w1    */
489:     MatMult(def->W,w2,u);                        /*    u  <- W*w2                */
490:     VecAXPY(z,-1.0,u);                           /*    z  <- z - u               */
491:   }
492:   return(0);
493: }

495: static PetscErrorCode PCSetUp_Deflation(PC pc)
496: {
497:   PC_Deflation     *def = (PC_Deflation*)pc->data;
498:   KSP              innerksp;
499:   PC               pcinner;
500:   Mat              Amat,nextDef=NULL,*mats;
501:   PetscInt         i,m,red,size;
502:   PetscMPIInt      commsize;
503:   PetscBool        match,flgspd,transp=PETSC_FALSE;
504:   MatCompositeType ctype;
505:   MPI_Comm         comm;
506:   char             prefix[128]="";
507:   PetscErrorCode   ierr;

510:   if (pc->setupcalled) return(0);
511:   PetscObjectGetComm((PetscObject)pc,&comm);
512:   PCGetOperators(pc,NULL,&Amat);
513:   if (!def->lvl && !def->prefix) {
514:     PCGetOptionsPrefix(pc,&def->prefix);
515:   }
516:   if (def->lvl) {
517:     PetscSNPrintf(prefix,sizeof(prefix),"%d_",(int)def->lvl);
518:   }

520:   /* compute a deflation space */
521:   if (def->W || def->Wt) {
522:     def->spacetype = PC_DEFLATION_SPACE_USER;
523:   } else {
524:     PCDeflationComputeSpace(pc);
525:   }

527:   /* nested deflation */
528:   if (def->W) {
529:     PetscObjectTypeCompare((PetscObject)def->W,MATCOMPOSITE,&match);
530:     if (match) {
531:       MatCompositeGetType(def->W,&ctype);
532:       MatCompositeGetNumberMat(def->W,&size);
533:     }
534:   } else {
535:     MatCreateHermitianTranspose(def->Wt,&def->W);
536:     PetscObjectTypeCompare((PetscObject)def->Wt,MATCOMPOSITE,&match);
537:     if (match) {
538:       MatCompositeGetType(def->Wt,&ctype);
539:       MatCompositeGetNumberMat(def->Wt,&size);
540:     }
541:     transp = PETSC_TRUE;
542:   }
543:   if (match && ctype == MAT_COMPOSITE_MULTIPLICATIVE) {
544:     if (!transp) {
545:       if (def->lvl < def->maxlvl) {
546:         PetscMalloc1(size,&mats);
547:         for (i=0; i<size; i++) {
548:           MatCompositeGetMat(def->W,i,&mats[i]);
549:         }
550:         size -= 1;
551:         MatDestroy(&def->W);
552:         def->W = mats[size];
553:         PetscObjectReference((PetscObject)mats[size]);
554:         if (size > 1) {
555:           MatCreateComposite(comm,size,mats,&nextDef);
556:           MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);
557:         } else {
558:           nextDef = mats[0];
559:           PetscObjectReference((PetscObject)mats[0]);
560:         }
561:         PetscFree(mats);
562:       } else {
563:         /* TODO test merge side performance */
564:         /* MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT); */
565:         MatCompositeMerge(def->W);
566:       }
567:     } else {
568:       if (def->lvl < def->maxlvl) {
569:         PetscMalloc1(size,&mats);
570:         for (i=0; i<size; i++) {
571:           MatCompositeGetMat(def->Wt,i,&mats[i]);
572:         }
573:         size -= 1;
574:         MatDestroy(&def->Wt);
575:         def->Wt = mats[0];
576:         PetscObjectReference((PetscObject)mats[0]);
577:         if (size > 1) {
578:           MatCreateComposite(comm,size,&mats[1],&nextDef);
579:           MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);
580:         } else {
581:           nextDef = mats[1];
582:           PetscObjectReference((PetscObject)mats[1]);
583:         }
584:         PetscFree(mats);
585:       } else {
586:         /* MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT); */
587:         MatCompositeMerge(def->Wt);
588:       }
589:     }
590:   }

592:   if (transp) {
593:     MatDestroy(&def->W);
594:     MatHermitianTranspose(def->Wt,MAT_INITIAL_MATRIX,&def->W);
595:   }

597:   /* assemble WtA */
598:   if (!def->WtA) {
599:     if (def->Wt) {
600:       MatMatMult(def->Wt,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);
601:     } else {
602: #if defined(PETSC_USE_COMPLEX)
603:       MatHermitianTranspose(def->W,MAT_INITIAL_MATRIX,&def->Wt);
604:       MatMatMult(def->Wt,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);
605: #else
606:       MatTransposeMatMult(def->W,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);
607: #endif
608:     }
609:   }
610:   /* setup coarse problem */
611:   if (!def->WtAWinv) {
612:     MatGetSize(def->W,NULL,&m);
613:     if (!def->WtAW) {
614:       MatMatMult(def->WtA,def->W,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);
615:       /* TODO create MatInheritOption(Mat,MatOption) */
616:       MatGetOption(Amat,MAT_SPD,&flgspd);
617:       MatSetOption(def->WtAW,MAT_SPD,flgspd);
618:       if (PetscDefined(USE_DEBUG)) {
619:         /* Check columns of W are not in kernel of A */
620:         PetscReal *norms;
621:         PetscMalloc1(m,&norms);
622:         MatGetColumnNorms(def->WtAW,NORM_INFINITY,norms);
623:         for (i=0; i<m; i++) {
624:           if (norms[i] < 100*PETSC_MACHINE_EPSILON) {
625:             SETERRQ1(comm,PETSC_ERR_SUP,"Column %D of W is in kernel of A.",i);
626:           }
627:         }
628:         PetscFree(norms);
629:       }
630:     } else {
631:       MatGetOption(def->WtAW,MAT_SPD,&flgspd);
632:     }
633:     /* TODO use MATINV ? */
634:     KSPCreate(comm,&def->WtAWinv);
635:     KSPSetOperators(def->WtAWinv,def->WtAW,def->WtAW);
636:     KSPGetPC(def->WtAWinv,&pcinner);
637:     /* Setup KSP and PC */
638:     if (nextDef) { /* next level for multilevel deflation */
639:       innerksp = def->WtAWinv;
640:       /* set default KSPtype */
641:       if (!def->ksptype) {
642:         def->ksptype = KSPFGMRES;
643:         if (flgspd) { /* SPD system */
644:           def->ksptype = KSPFCG;
645:         }
646:       }
647:       KSPSetType(innerksp,def->ksptype); /* TODO iherit from KSP + tolerances */
648:       PCSetType(pcinner,PCDEFLATION); /* TODO create coarse preconditinoner M_c = WtMW ? */
649:       PCDeflationSetSpace(pcinner,nextDef,transp);
650:       PCDeflationSetLevels_Deflation(pcinner,def->lvl+1,def->maxlvl);
651:       /* inherit options */
652:       if (def->prefix) ((PC_Deflation*)(pcinner->data))->prefix = def->prefix;
653:       ((PC_Deflation*)(pcinner->data))->init          = def->init;
654:       ((PC_Deflation*)(pcinner->data))->ksptype       = def->ksptype;
655:       ((PC_Deflation*)(pcinner->data))->correct       = def->correct;
656:       ((PC_Deflation*)(pcinner->data))->correctfact   = def->correctfact;
657:       ((PC_Deflation*)(pcinner->data))->reductionfact = def->reductionfact;
658:       MatDestroy(&nextDef);
659:     } else { /* the last level */
660:       KSPSetType(def->WtAWinv,KSPPREONLY);
661:       PCSetType(pcinner,PCTELESCOPE);
662:       /* do not overwrite PCTELESCOPE */
663:       if (def->prefix) {
664:         KSPSetOptionsPrefix(def->WtAWinv,def->prefix);
665:       }
666:       KSPAppendOptionsPrefix(def->WtAWinv,"deflation_tel_");
667:       PCSetFromOptions(pcinner);
668:       PetscObjectTypeCompare((PetscObject)pcinner,PCTELESCOPE,&match);
669:       if (!match) SETERRQ(comm,PETSC_ERR_SUP,"User can not owerwrite PCTELESCOPE on bottom level, use reduction factor = 1 instead.");
670:       /* Reduction factor choice */
671:       red = def->reductionfact;
672:       if (red < 0) {
673:         MPI_Comm_size(comm,&commsize);
674:         red  = ceil((float)commsize/ceil((float)m/commsize));
675:         PetscObjectTypeCompareAny((PetscObject)(def->WtAW),&match,MATSEQDENSE,MATMPIDENSE,MATDENSE,"");
676:         if (match) red = commsize;
677:         PetscInfo1(pc,"Auto choosing reduction factor %D\n",red);
678:       }
679:       PCTelescopeSetReductionFactor(pcinner,red);
680:       PCSetUp(pcinner);
681:       PCTelescopeGetKSP(pcinner,&innerksp);
682:       if (innerksp) {
683:         KSPGetPC(innerksp,&pcinner);
684:         PCSetType(pcinner,PCLU);
685: #if defined(PETSC_HAVE_SUPERLU)
686:         MatGetFactorAvailable(def->WtAW,MATSOLVERSUPERLU,MAT_FACTOR_LU,&match);
687:         if (match) {
688:           PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU);
689:         }
690: #endif
691: #if defined(PETSC_HAVE_SUPERLU_DIST)
692:         MatGetFactorAvailable(def->WtAW,MATSOLVERSUPERLU_DIST,MAT_FACTOR_LU,&match);
693:         if (match) {
694:           PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU_DIST);
695:         }
696: #endif
697:       }
698:     }

700:     if (innerksp) {
701:       if (def->prefix) {
702:         KSPSetOptionsPrefix(innerksp,def->prefix);
703:         KSPAppendOptionsPrefix(innerksp,"deflation_");
704:       } else {
705:         KSPSetOptionsPrefix(innerksp,"deflation_");
706:       }
707:       KSPAppendOptionsPrefix(innerksp,prefix);
708:       KSPSetFromOptions(innerksp);
709:       KSPSetUp(innerksp);
710:     }
711:   }
712:   KSPSetFromOptions(def->WtAWinv);
713:   KSPSetUp(def->WtAWinv);

715:   /* create preconditioner */
716:   if (!def->pc) {
717:     PCCreate(comm,&def->pc);
718:     PCSetOperators(def->pc,Amat,Amat);
719:     PCSetType(def->pc,PCNONE);
720:     if (def->prefix) {
721:       PCSetOptionsPrefix(def->pc,def->prefix);
722:     }
723:     PCAppendOptionsPrefix(def->pc,"deflation_");
724:     PCAppendOptionsPrefix(def->pc,prefix);
725:     PCAppendOptionsPrefix(def->pc,"pc_");
726:     PCSetFromOptions(def->pc);
727:     PCSetUp(def->pc);
728:   }

730:   /* create work vecs */
731:   MatCreateVecs(Amat,NULL,&def->work);
732:   KSPCreateVecs(def->WtAWinv,2,&def->workcoarse,0,NULL);
733:   return(0);
734: }

736: static PetscErrorCode PCReset_Deflation(PC pc)
737: {
738:   PC_Deflation      *def = (PC_Deflation*)pc->data;
739:   PetscErrorCode    ierr;

742:   VecDestroy(&def->work);
743:   VecDestroyVecs(2,&def->workcoarse);
744:   MatDestroy(&def->W);
745:   MatDestroy(&def->Wt);
746:   MatDestroy(&def->WtA);
747:   MatDestroy(&def->WtAW);
748:   KSPDestroy(&def->WtAWinv);
749:   PCDestroy(&def->pc);
750:   return(0);
751: }

753: static PetscErrorCode PCDestroy_Deflation(PC pc)
754: {

758:   PCReset_Deflation(pc);
759:   PetscFree(pc->data);
760:   return(0);
761: }

763: static PetscErrorCode PCView_Deflation(PC pc,PetscViewer viewer)
764: {
765:   PC_Deflation      *def = (PC_Deflation*)pc->data;
766:   PetscInt          its;
767:   PetscBool         iascii;
768:   PetscErrorCode    ierr;

771:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
772:   if (iascii) {
773:     if (def->correct) {
774:       PetscViewerASCIIPrintf(viewer,"using CP correction, factor = %g+%gi\n",
775:                                     (double)PetscRealPart(def->correctfact),
776:                                     (double)PetscImaginaryPart(def->correctfact));
777:     }
778:     if (!def->lvl) {
779:       PetscViewerASCIIPrintf(viewer,"deflation space type: %s\n",PCDeflationSpaceTypes[def->spacetype]);
780:     }

782:     PetscViewerASCIIPrintf(viewer,"--- Additional PC:\n");
783:     PetscViewerASCIIPushTab(viewer);
784:     PCView(def->pc,viewer);
785:     PetscViewerASCIIPopTab(viewer);

787:     PetscViewerASCIIPrintf(viewer,"--- Coarse problem solver:\n");
788:     PetscViewerASCIIPushTab(viewer);
789:     KSPGetTotalIterations(def->WtAWinv,&its);
790:     PetscViewerASCIIPrintf(viewer,"total number of iterations: %D\n",its);
791:     KSPView(def->WtAWinv,viewer);
792:     PetscViewerASCIIPopTab(viewer);
793:   }
794:   return(0);
795: }

797: static PetscErrorCode PCSetFromOptions_Deflation(PetscOptionItems *PetscOptionsObject,PC pc)
798: {
799:   PC_Deflation      *def = (PC_Deflation*)pc->data;
800:   PetscErrorCode    ierr;

803:   PetscOptionsHead(PetscOptionsObject,"Deflation options");
804:   PetscOptionsBool("-pc_deflation_init_only","Use only initialization step - Initdef","PCDeflationSetInitOnly",def->init,&def->init,NULL);
805:   PetscOptionsInt("-pc_deflation_levels","Maximum of deflation levels","PCDeflationSetLevels",def->maxlvl,&def->maxlvl,NULL);
806:   PetscOptionsInt("-pc_deflation_reduction_factor","Reduction factor for coarse problem solution using PCTELESCOPE","PCDeflationSetReductionFactor",def->reductionfact,&def->reductionfact,NULL);
807:   PetscOptionsBool("-pc_deflation_correction","Add coarse problem correction Q to P","PCDeflationSetCorrectionFactor",def->correct,&def->correct,NULL);
808:   PetscOptionsScalar("-pc_deflation_correction_factor","Set multiple of Q to use as coarse problem correction","PCDeflationSetCorrectionFactor",def->correctfact,&def->correctfact,NULL);
809:   PetscOptionsEnum("-pc_deflation_compute_space","Compute deflation space","PCDeflationSetSpace",PCDeflationSpaceTypes,(PetscEnum)def->spacetype,(PetscEnum*)&def->spacetype,NULL);
810:   PetscOptionsInt("-pc_deflation_compute_space_size","Set size of the deflation space to compute","PCDeflationSetSpace",def->spacesize,&def->spacesize,NULL);
811:   PetscOptionsBool("-pc_deflation_space_extend","Extend deflation space instead of truncating (wavelets)","PCDeflation",def->extendsp,&def->extendsp,NULL);
812:   PetscOptionsTail();
813:   return(0);
814: }

816: /*MC
817:    PCDEFLATION - Deflation preconditioner shifts (deflates) part of the spectrum to zero or to a predefined value.

819:    Options Database Keys:
820: +    -pc_deflation_init_only          <false> - if true computes only the special guess
821: .    -pc_deflation_max_lvl            <0>     - maximum number of levels for multilevel deflation
822: .    -pc_deflation_reduction_factor <\-1>     - reduction factor on bottom level coarse problem for PCTELESCOPE (default based on the size of the coarse problem)
823: .    -pc_deflation_correction         <false> - if true apply coarse problem correction
824: .    -pc_deflation_correction_factor  <1.0>   - sets coarse problem correction factor
825: .    -pc_deflation_compute_space      <haar>  - compute PCDeflationSpaceType deflation space
826: -    -pc_deflation_compute_space_size <1>     - size of the deflation space (corresponds to number of levels for wavelet-based deflation)

828:    Notes:
829:     Given a (complex - transpose is always Hermitian) full rank deflation matrix W, the deflation (introduced in [1,2])
830:     preconditioner uses projections Q = W*(W'*A*W)^{-1}*W' and P = I - Q*A, where A is pmat.

832:     The deflation computes initial guess x0 = x_{-1} - Q*r_{-1}, which is the solution on the deflation space.
833:     If PCDeflationSetInitOnly() or -pc_deflation_init_only is set to PETSC_TRUE (InitDef scheme), the application of the
834:     preconditioner consists only of application of the additional preconditioner M^{-1}. Otherwise, the preconditioner
835:     application consists of P*M^{-1} + factor*Q. The first part of the preconditioner (PM^{-1}) shifts some eigenvalues
836:     to zero while the addition of the coarse problem correction (factor*Q) makes the preconditioner to shift some
837:     eigenvalues to the given factor. The InitDef scheme is recommended for deflation using high accuracy estimates
838:     of eigenvectors of A when it exhibits similar convergence to the full deflation but is cheaper.

840:     The deflation matrix is by default automatically computed. The type of deflation matrix and its size to compute can
841:     be controlled by PCDeflationSetSpaceToCompute() or -pc_deflation_compute_space and -pc_deflation_compute_space_size.
842:     User can set an arbitrary deflation space matrix with PCDeflationSetSpace(). If the deflation matrix
843:     is a multiplicative MATCOMPOSITE, a multilevel deflation [3] is used. The first matrix in the composite is used as the
844:     deflation matrix, and the coarse problem (W'*A*W)^{-1} is solved by KSPFCG (if A is MAT_SPD) or KSPFGMRES preconditioned
845:     by deflation with deflation matrix being the next matrix in the MATCOMPOSITE. This scheme repeats until the maximum
846:     level is reached or there are no more matrices. If the maximum level is reached, the remaining matrices are merged
847:     (multiplied) to create the last deflation matrix. The maximum level defaults to 0 and can be set by
848:     PCDeflationSetLevels() or by -pc_deflation_levels.

850:     The coarse problem KSP can be controlled from the command line with prefix -deflation_ for the first level and -deflation_[lvl-1]
851:     from the second level onward. You can also use
852:     PCDeflationGetCoarseKSP() to control it from code. The bottom level KSP defaults to
853:     KSPPREONLY with PCLU direct solver (MATSOLVERSUPERLU/MATSOLVERSUPERLU_DIST if available) wrapped into PCTELESCOPE.
854:     For convenience, the reduction factor can be set by PCDeflationSetReductionFactor()
855:     or -pc_deflation_recduction_factor. The default is chosen heuristically based on the coarse problem size.

857:     The additional preconditioner can be controlled from command line with prefix -deflation_[lvl]_pc (same rules used for
858:     coarse problem KSP apply for [lvl]_ part of prefix), e.g., -deflation_1_pc_pc_type bjacobi. You can also use
859:     PCDeflationGetPC() to control the additional preconditioner from code. It defaults to PCNONE.

861:     The coarse problem correction term (factor*Q) can be turned on by -pc_deflation_correction and the factor value can
862:     be set by pc_deflation_correction_factor or by PCDeflationSetCorrectionFactor(). The coarse problem can
863:     significantly improve convergence when the deflation coarse problem is not solved with high enough accuracy. We
864:     recommend setting factor to some eigenvalue, e.g., the largest eigenvalue so that the preconditioner does not create
865:     an isolated eigenvalue.

867:     The options are automatically inherited from the previous deflation level.

869:     The preconditioner supports KSPMonitorDynamicTolerance(). This is useful for the multilevel scheme for which we also
870:     recommend limiting the number of iterations for the coarse problems.

872:     See section 3 of [4] for additional references and decription of the algorithm when used for conjugate gradients.
873:     Section 4 describes some possible choices for the deflation space.

875:    Developer Notes:
876:      Contributed by Jakub Kruzik (PERMON), Institute of Geonics of the Czech
877:      Academy of Sciences and VSB - TU Ostrava.

879:      Developed from PERMON code used in [4] while on a research stay with
880:      Prof. Reinhard Nabben at the Institute of Mathematics, TU Berlin.

882:    References:
883: +    [1] - A. Nicolaides. "Deflation of conjugate gradients with applications to boundary value problems", SIAM J. Numer. Anal. 24.2, 1987.
884: .    [2] - Z. Dostal. "Conjugate gradient method with preconditioning by projector", Int J. Comput. Math. 23.3-4, 1988.
885: .    [3] - Y. A. Erlangga and R. Nabben. "Multilevel Projection-Based Nested Krylov Iteration for Boundary Value Problems", SIAM J. Sci. Comput. 30.3, 2008.
886: -    [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

888:    Level: intermediate

890: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
891:            PCDeflationSetInitOnly(), PCDeflationSetLevels(), PCDeflationSetReductionFactor(),
892:            PCDeflationSetCorrectionFactor(), PCDeflationSetSpaceToCompute(),
893:            PCDeflationSetSpace(), PCDeflationSpaceType, PCDeflationSetProjectionNullSpaceMat(),
894:            PCDeflationSetCoarseMat(), PCDeflationGetCoarseKSP(), PCDeflationGetPC()
895: M*/

897: PETSC_EXTERN PetscErrorCode PCCreate_Deflation(PC pc)
898: {
899:   PC_Deflation   *def;

903:   PetscNewLog(pc,&def);
904:   pc->data = (void*)def;

906:   def->init          = PETSC_FALSE;
907:   def->correct       = PETSC_FALSE;
908:   def->correctfact   = 1.0;
909:   def->reductionfact = -1;
910:   def->spacetype     = PC_DEFLATION_SPACE_HAAR;
911:   def->spacesize     = 1;
912:   def->extendsp      = PETSC_FALSE;
913:   def->lvl           = 0;
914:   def->maxlvl        = 0;
915:   def->W             = NULL;
916:   def->Wt            = NULL;

918:   pc->ops->apply          = PCApply_Deflation;
919:   pc->ops->presolve       = PCPreSolve_Deflation;
920:   pc->ops->setup          = PCSetUp_Deflation;
921:   pc->ops->reset          = PCReset_Deflation;
922:   pc->ops->destroy        = PCDestroy_Deflation;
923:   pc->ops->setfromoptions = PCSetFromOptions_Deflation;
924:   pc->ops->view           = PCView_Deflation;

926:   PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetInitOnly_C",PCDeflationSetInitOnly_Deflation);
927:   PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetLevels_C",PCDeflationSetLevels_Deflation);
928:   PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetReductionFactor_C",PCDeflationSetReductionFactor_Deflation);
929:   PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCorrectionFactor_C",PCDeflationSetCorrectionFactor_Deflation);
930:   PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpaceToCompute_C",PCDeflationSetSpaceToCompute_Deflation);
931:   PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpace_C",PCDeflationSetSpace_Deflation);
932:   PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetProjectionNullSpaceMat_C",PCDeflationSetProjectionNullSpaceMat_Deflation);
933:   PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCoarseMat_C",PCDeflationSetCoarseMat_Deflation);
934:   PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetCoarseKSP_C",PCDeflationGetCoarseKSP_Deflation);
935:   PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetPC_C",PCDeflationGetPC_Deflation);
936:   return(0);
937: }