xref: /petsc/src/ksp/pc/impls/deflation/deflation.c (revision 5c0c31c5171c0ed0d0162135c9816bb625821204)
137eeb815SJakub Kruzik 
237eeb815SJakub Kruzik /*  --------------------------------------------------------------------
337eeb815SJakub Kruzik 
437eeb815SJakub Kruzik      This file implements a Deflation preconditioner in PETSc as part of PC.
537eeb815SJakub Kruzik      You can use this as a starting point for implementing your own
637eeb815SJakub Kruzik      preconditioner that is not provided with PETSc. (You might also consider
737eeb815SJakub Kruzik      just using PCSHELL)
837eeb815SJakub Kruzik 
937eeb815SJakub Kruzik      The following basic routines are required for each preconditioner.
1037eeb815SJakub Kruzik           PCCreate_XXX()          - Creates a preconditioner context
1137eeb815SJakub Kruzik           PCSetFromOptions_XXX()  - Sets runtime options
1237eeb815SJakub Kruzik           PCApply_XXX()           - Applies the preconditioner
1337eeb815SJakub Kruzik           PCDestroy_XXX()         - Destroys the preconditioner context
1437eeb815SJakub Kruzik      where the suffix "_XXX" denotes a particular implementation, in
1537eeb815SJakub Kruzik      this case we use _Deflation (e.g., PCCreate_Deflation, PCApply_Deflation).
1637eeb815SJakub Kruzik      These routines are actually called via the common user interface
1737eeb815SJakub Kruzik      routines PCCreate(), PCSetFromOptions(), PCApply(), and PCDestroy(),
1837eeb815SJakub Kruzik      so the application code interface remains identical for all
1937eeb815SJakub Kruzik      preconditioners.
2037eeb815SJakub Kruzik 
2137eeb815SJakub Kruzik      Another key routine is:
2237eeb815SJakub Kruzik           PCSetUp_XXX()           - Prepares for the use of a preconditioner
2337eeb815SJakub Kruzik      by setting data structures and options.   The interface routine PCSetUp()
2437eeb815SJakub Kruzik      is not usually called directly by the user, but instead is called by
2537eeb815SJakub Kruzik      PCApply() if necessary.
2637eeb815SJakub Kruzik 
2737eeb815SJakub Kruzik      Additional basic routines are:
2837eeb815SJakub Kruzik           PCView_XXX()            - Prints details of runtime options that
2937eeb815SJakub Kruzik                                     have actually been used.
3037eeb815SJakub Kruzik      These are called by application codes via the interface routines
3137eeb815SJakub Kruzik      PCView().
3237eeb815SJakub Kruzik 
3337eeb815SJakub Kruzik      The various types of solvers (preconditioners, Krylov subspace methods,
3437eeb815SJakub Kruzik      nonlinear solvers, timesteppers) are all organized similarly, so the
3537eeb815SJakub Kruzik      above description applies to these categories also.  One exception is
3637eeb815SJakub Kruzik      that the analogues of PCApply() for these components are KSPSolve(),
3737eeb815SJakub Kruzik      SNESSolve(), and TSSolve().
3837eeb815SJakub Kruzik 
3937eeb815SJakub Kruzik      Additional optional functionality unique to preconditioners is left and
4037eeb815SJakub Kruzik      right symmetric preconditioner application via PCApplySymmetricLeft()
4137eeb815SJakub Kruzik      and PCApplySymmetricRight().  The Deflation implementation is
4237eeb815SJakub Kruzik      PCApplySymmetricLeftOrRight_Deflation().
4337eeb815SJakub Kruzik 
4437eeb815SJakub Kruzik     -------------------------------------------------------------------- */
4537eeb815SJakub Kruzik 
4637eeb815SJakub Kruzik /*
4737eeb815SJakub Kruzik    Include files needed for the Deflation preconditioner:
4837eeb815SJakub Kruzik      pcimpl.h - private include file intended for use by all preconditioners
4937eeb815SJakub Kruzik */
5037eeb815SJakub Kruzik 
5137eeb815SJakub Kruzik #include <petsc/private/pcimpl.h>   /*I "petscpc.h" I*/
5237eeb815SJakub Kruzik 
5337eeb815SJakub Kruzik const char *const PCDeflationTypes[]    = {"INIT","PRE","POST","PCDeflationType","PC_DEFLATION_",0};
5437eeb815SJakub Kruzik 
5537eeb815SJakub Kruzik /*
5637eeb815SJakub Kruzik    Private context (data structure) for the deflation preconditioner.
5737eeb815SJakub Kruzik */
5837eeb815SJakub Kruzik typedef struct {
5937eeb815SJakub Kruzik   PetscBool init;            /* do only init step - error correction of direction is omitted */
6037eeb815SJakub Kruzik   PetscBool pre;             /* start with x0 being the solution in the deflation space */
6137eeb815SJakub Kruzik   PetscBool correct;         /* add CP (Qr) correction to descent direction */
6237eeb815SJakub Kruzik   PetscBool truenorm;
6337eeb815SJakub Kruzik   PetscBool adaptiveconv;
6437eeb815SJakub Kruzik   PetscReal adaptiveconst;
6537eeb815SJakub Kruzik   PetscInt  reductionfact;
6637eeb815SJakub Kruzik   Mat       W,Wt,AW,WtAW;    /* deflation space, coarse problem mats */
6737eeb815SJakub Kruzik   KSP       WtAWinv;         /* deflation coarse problem */
68409a357bSJakub Kruzik   KSPType   ksptype;
6937eeb815SJakub Kruzik   Vec       *work;
7037eeb815SJakub Kruzik 
71409a357bSJakub Kruzik   PCDeflationSpaceType spacetype;
7237eeb815SJakub Kruzik   PetscInt             spacesize;
7337eeb815SJakub Kruzik   PetscInt             nestedlvl;
7437eeb815SJakub Kruzik   PetscInt             maxnestedlvl;
7537eeb815SJakub Kruzik   PetscBool            extendsp;
7637eeb815SJakub Kruzik } PC_Deflation;
7737eeb815SJakub Kruzik 
7837eeb815SJakub Kruzik static PetscErrorCode  PCDeflationSetType_Deflation(PC pc,PCDeflationType type)
7937eeb815SJakub Kruzik {
8037eeb815SJakub Kruzik   PC_Deflation *def = (PC_Deflation*)pc->data;
8137eeb815SJakub Kruzik 
8237eeb815SJakub Kruzik   PetscFunctionBegin;
8337eeb815SJakub Kruzik   def->init = PETSC_FALSE;
8437eeb815SJakub Kruzik   def->pre = PETSC_FALSE;
8537eeb815SJakub Kruzik   if (type == PC_DEFLATION_INIT) {
8637eeb815SJakub Kruzik     def->init = PETSC_TRUE;
8737eeb815SJakub Kruzik     def->pre  = PETSC_TRUE;
8837eeb815SJakub Kruzik   } else if (type == PC_DEFLATION_PRE) {
8937eeb815SJakub Kruzik     def->pre  = PETSC_TRUE;
9037eeb815SJakub Kruzik   }
9137eeb815SJakub Kruzik   PetscFunctionReturn(0);
9237eeb815SJakub Kruzik }
9337eeb815SJakub Kruzik 
94bb9edbfaSJakub Kruzik /*@
95bb9edbfaSJakub Kruzik    PCDeflationSetType - Causes the deflation preconditioner to use only a special
96bb9edbfaSJakub Kruzik     initial gues or pre/post solve solution update
97bb9edbfaSJakub Kruzik 
98bb9edbfaSJakub Kruzik    Logically Collective on PC
99bb9edbfaSJakub Kruzik 
100bb9edbfaSJakub Kruzik    Input Parameters:
101bb9edbfaSJakub Kruzik +  pc - the preconditioner context
102bb9edbfaSJakub Kruzik -  type - PC_DEFLATION_PRE, PC_DEFLATION_INIT, PC_DEFLATION_POST
103bb9edbfaSJakub Kruzik 
104bb9edbfaSJakub Kruzik    Options Database Key:
105bb9edbfaSJakub Kruzik .  -pc_deflation_type <pre,init,post>
106bb9edbfaSJakub Kruzik 
107bb9edbfaSJakub Kruzik    Level: intermediate
108bb9edbfaSJakub Kruzik 
109bb9edbfaSJakub Kruzik    Concepts: Deflation preconditioner
110bb9edbfaSJakub Kruzik 
111bb9edbfaSJakub Kruzik .seealso: PCDeflationGetType()
112bb9edbfaSJakub Kruzik @*/
113bb9edbfaSJakub Kruzik PetscErrorCode  PCDeflationSetType(PC pc,PCDeflationType type)
114bb9edbfaSJakub Kruzik {
115bb9edbfaSJakub Kruzik   PetscErrorCode ierr;
116bb9edbfaSJakub Kruzik 
117bb9edbfaSJakub Kruzik   PetscFunctionBegin;
118bb9edbfaSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
119bb9edbfaSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetType_C",(PC,PCDeflationType),(pc,type));CHKERRQ(ierr);
120bb9edbfaSJakub Kruzik   PetscFunctionReturn(0);
121bb9edbfaSJakub Kruzik }
122bb9edbfaSJakub Kruzik 
12337eeb815SJakub Kruzik static PetscErrorCode  PCDeflationGetType_Deflation(PC pc,PCDeflationType *type)
12437eeb815SJakub Kruzik {
12537eeb815SJakub Kruzik   PC_Deflation *def = (PC_Deflation*)pc->data;
12637eeb815SJakub Kruzik 
12737eeb815SJakub Kruzik   PetscFunctionBegin;
12837eeb815SJakub Kruzik   if (def->init) {
12937eeb815SJakub Kruzik     *type = PC_DEFLATION_INIT;
13037eeb815SJakub Kruzik   } else if (def->pre) {
13137eeb815SJakub Kruzik     *type = PC_DEFLATION_PRE;
13237eeb815SJakub Kruzik   } else {
13337eeb815SJakub Kruzik     *type = PC_DEFLATION_POST;
13437eeb815SJakub Kruzik   }
13537eeb815SJakub Kruzik   PetscFunctionReturn(0);
13637eeb815SJakub Kruzik }
13737eeb815SJakub Kruzik 
138bb9edbfaSJakub Kruzik /*@
139bb9edbfaSJakub Kruzik    PCDeflationGetType - Gets how the diagonal matrix is produced for the preconditioner
140bb9edbfaSJakub Kruzik 
141bb9edbfaSJakub Kruzik    Not Collective on PC
142bb9edbfaSJakub Kruzik 
143bb9edbfaSJakub Kruzik    Input Parameter:
144bb9edbfaSJakub Kruzik .  pc - the preconditioner context
145bb9edbfaSJakub Kruzik 
146bb9edbfaSJakub Kruzik    Output Parameter:
147bb9edbfaSJakub Kruzik -  type - PC_DEFLATION_PRE, PC_DEFLATION_INIT, PC_DEFLATION_POST
148bb9edbfaSJakub Kruzik 
149bb9edbfaSJakub Kruzik    Level: intermediate
150bb9edbfaSJakub Kruzik 
151bb9edbfaSJakub Kruzik    Concepts: Deflation preconditioner
152bb9edbfaSJakub Kruzik 
153bb9edbfaSJakub Kruzik .seealso: PCDeflationSetType()
154bb9edbfaSJakub Kruzik @*/
155bb9edbfaSJakub Kruzik PetscErrorCode  PCDeflationGetType(PC pc,PCDeflationType *type)
156bb9edbfaSJakub Kruzik {
157bb9edbfaSJakub Kruzik   PetscErrorCode ierr;
158bb9edbfaSJakub Kruzik 
159bb9edbfaSJakub Kruzik   PetscFunctionBegin;
160bb9edbfaSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
161bb9edbfaSJakub Kruzik   ierr = PetscUseMethod(pc,"PCDeflationGetType_C",(PC,PCDeflationType*),(pc,type));CHKERRQ(ierr);
162bb9edbfaSJakub Kruzik   PetscFunctionReturn(0);
163bb9edbfaSJakub Kruzik }
164bb9edbfaSJakub Kruzik 
165e662bc50SJakub Kruzik static PetscErrorCode PCDeflationSetSpace_Deflation(PC pc,Mat W,PetscBool transpose)
166e662bc50SJakub Kruzik {
167e662bc50SJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
168e662bc50SJakub Kruzik   PetscErrorCode ierr;
169e662bc50SJakub Kruzik 
170e662bc50SJakub Kruzik   PetscFunctionBegin;
171e662bc50SJakub Kruzik   if (transpose) {
172e662bc50SJakub Kruzik     def->Wt = W;
173e662bc50SJakub Kruzik     def->W = NULL;
174e662bc50SJakub Kruzik   } else {
175e662bc50SJakub Kruzik     def->W = W;
176e662bc50SJakub Kruzik   }
177e662bc50SJakub Kruzik   ierr = PetscObjectReference((PetscObject)W);CHKERRQ(ierr);
178e662bc50SJakub Kruzik   PetscFunctionReturn(0);
179e662bc50SJakub Kruzik }
180e662bc50SJakub Kruzik 
181e662bc50SJakub Kruzik /* TODO create PCDeflationSetSpaceTranspose? */
182e662bc50SJakub Kruzik /*@
183e662bc50SJakub Kruzik    PCDeflationSetSpace - Set deflation space matrix (or its transpose).
184e662bc50SJakub Kruzik 
185e662bc50SJakub Kruzik    Logically Collective on PC
186e662bc50SJakub Kruzik 
187e662bc50SJakub Kruzik    Input Parameters:
188e662bc50SJakub Kruzik +  pc - the preconditioner context
189e662bc50SJakub Kruzik .  W  - deflation matrix
190e662bc50SJakub Kruzik -  tranpose - indicates that W is an explicit transpose of the deflation matrix
191e662bc50SJakub Kruzik 
192e662bc50SJakub Kruzik    Level: intermediate
193e662bc50SJakub Kruzik 
194e662bc50SJakub Kruzik .seealso: PCDEFLATION
195e662bc50SJakub Kruzik @*/
196e662bc50SJakub Kruzik PetscErrorCode PCDeflationSetSpace(PC pc,Mat W,PetscBool transpose)
197e662bc50SJakub Kruzik {
198e662bc50SJakub Kruzik   PetscErrorCode ierr;
199e662bc50SJakub Kruzik 
200e662bc50SJakub Kruzik   PetscFunctionBegin;
201e662bc50SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
202e662bc50SJakub Kruzik   PetscValidHeaderSpecific(W,MAT_CLASSID,2);
203e662bc50SJakub Kruzik   PetscValidLogicalCollectiveBool(pc,transpose,3);
204e662bc50SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetSpace_C",(PC,Mat,PetscBool),(pc,W,transpose));CHKERRQ(ierr);
205e662bc50SJakub Kruzik   PetscFunctionReturn(0);
206e662bc50SJakub Kruzik }
207e662bc50SJakub Kruzik 
208*5c0c31c5SJakub Kruzik static PetscErrorCode PCDeflationSetLvl_Deflation(PC pc,PetscInt current,PetscInt max)
209*5c0c31c5SJakub Kruzik {
210*5c0c31c5SJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
211*5c0c31c5SJakub Kruzik 
212*5c0c31c5SJakub Kruzik   PetscFunctionBegin;
213*5c0c31c5SJakub Kruzik   def->nestedlvl = current;
214*5c0c31c5SJakub Kruzik   def->maxnestedlvl = max;
215*5c0c31c5SJakub Kruzik   PetscFunctionReturn(0);
216*5c0c31c5SJakub Kruzik }
217*5c0c31c5SJakub Kruzik 
218*5c0c31c5SJakub Kruzik /*@
219*5c0c31c5SJakub Kruzik    PCDeflationSetMaxLvl - Set maximum level of deflation.
220*5c0c31c5SJakub Kruzik 
221*5c0c31c5SJakub Kruzik    Logically Collective on PC
222*5c0c31c5SJakub Kruzik 
223*5c0c31c5SJakub Kruzik    Input Parameters:
224*5c0c31c5SJakub Kruzik +  pc  - the preconditioner context
225*5c0c31c5SJakub Kruzik .  max - maximum deflation level
226*5c0c31c5SJakub Kruzik 
227*5c0c31c5SJakub Kruzik    Level: intermediate
228*5c0c31c5SJakub Kruzik 
229*5c0c31c5SJakub Kruzik .seealso: PCDEFLATION
230*5c0c31c5SJakub Kruzik @*/
231*5c0c31c5SJakub Kruzik PetscErrorCode PCDeflationSetMaxLvl(PC pc,PetscInt max)
232*5c0c31c5SJakub Kruzik {
233*5c0c31c5SJakub Kruzik   PetscErrorCode ierr;
234*5c0c31c5SJakub Kruzik 
235*5c0c31c5SJakub Kruzik   PetscFunctionBegin;
236*5c0c31c5SJakub Kruzik   PetscValidLogicalCollectiveInt(pc,max,2);
237*5c0c31c5SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetLvl_C",(PC,PetscInt,PetscInt),(pc,0,max));CHKERRQ(ierr);
238*5c0c31c5SJakub Kruzik   PetscFunctionReturn(0);
239*5c0c31c5SJakub Kruzik }
240e662bc50SJakub Kruzik 
24137eeb815SJakub Kruzik /* -------------------------------------------------------------------------- */
24237eeb815SJakub Kruzik /*
24337eeb815SJakub Kruzik    PCSetUp_Deflation - Prepares for the use of the Deflation preconditioner
24437eeb815SJakub Kruzik                     by setting data structures and options.
24537eeb815SJakub Kruzik 
24637eeb815SJakub Kruzik    Input Parameter:
24737eeb815SJakub Kruzik .  pc - the preconditioner context
24837eeb815SJakub Kruzik 
24937eeb815SJakub Kruzik    Application Interface Routine: PCSetUp()
25037eeb815SJakub Kruzik 
25137eeb815SJakub Kruzik    Notes:
25237eeb815SJakub Kruzik    The interface routine PCSetUp() is not usually called directly by
25337eeb815SJakub Kruzik    the user, but instead is called by PCApply() if necessary.
25437eeb815SJakub Kruzik */
25537eeb815SJakub Kruzik static PetscErrorCode PCSetUp_Deflation(PC pc)
25637eeb815SJakub Kruzik {
257409a357bSJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
258409a357bSJakub Kruzik   KSP              innerksp;
259409a357bSJakub Kruzik   PC               pcinner;
260409a357bSJakub Kruzik   Mat              Amat,nextDef=NULL,*mats;
261409a357bSJakub Kruzik   PetscInt         i,m,red,size,commsize;
262409a357bSJakub Kruzik   PetscBool        match,flgspd,transp=PETSC_FALSE;
263409a357bSJakub Kruzik   MatCompositeType ctype;
264409a357bSJakub Kruzik   MPI_Comm         comm;
265409a357bSJakub Kruzik   const char       *prefix;
26637eeb815SJakub Kruzik   PetscErrorCode   ierr;
26737eeb815SJakub Kruzik 
26837eeb815SJakub Kruzik   PetscFunctionBegin;
269409a357bSJakub Kruzik   if (pc->setupcalled) PetscFunctionReturn(0);
270409a357bSJakub Kruzik   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
271409a357bSJakub Kruzik   if (def->W || def->Wt) {
272409a357bSJakub Kruzik     def->spacetype = PC_DEFLATION_SPACE_USER;
273409a357bSJakub Kruzik   } else {
274409a357bSJakub Kruzik     //ierr = KSPDCGComputeDeflationSpace(ksp);CHKERRQ(ierr);
27537eeb815SJakub Kruzik   }
27637eeb815SJakub Kruzik 
277409a357bSJakub Kruzik   /* nested deflation */
278409a357bSJakub Kruzik   if (def->W) {
279409a357bSJakub Kruzik     ierr = PetscObjectTypeCompare((PetscObject)def->W,MATCOMPOSITE,&match);CHKERRQ(ierr);
280409a357bSJakub Kruzik     if (match) {
281409a357bSJakub Kruzik       ierr = MatCompositeGetType(def->W,&ctype);CHKERRQ(ierr);
282409a357bSJakub Kruzik       ierr = MatCompositeGetNumberMat(def->W,&size);CHKERRQ(ierr);
28337eeb815SJakub Kruzik     }
284409a357bSJakub Kruzik   } else {
285409a357bSJakub Kruzik     ierr = MatCreateTranspose(def->Wt,&def->W);CHKERRQ(ierr);
286409a357bSJakub Kruzik     ierr = PetscObjectTypeCompare((PetscObject)def->Wt,MATCOMPOSITE,&match);CHKERRQ(ierr);
287409a357bSJakub Kruzik     if (match) {
288409a357bSJakub Kruzik       ierr = MatCompositeGetType(def->Wt,&ctype);CHKERRQ(ierr);
289409a357bSJakub Kruzik       ierr = MatCompositeGetNumberMat(def->Wt,&size);CHKERRQ(ierr);
290409a357bSJakub Kruzik     }
291409a357bSJakub Kruzik     transp = PETSC_TRUE;
292409a357bSJakub Kruzik   }
293409a357bSJakub Kruzik   if (match && ctype == MAT_COMPOSITE_MULTIPLICATIVE) {
294409a357bSJakub Kruzik     ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
295409a357bSJakub Kruzik     if (!transp) {
296409a357bSJakub Kruzik       for (i=0; i<size; i++) {
297409a357bSJakub Kruzik         ierr = MatCompositeGetMat(def->W,i,&mats[i]);CHKERRQ(ierr);
298409a357bSJakub Kruzik         //ierr = PetscObjectReference((PetscObject)mats[i]);CHKERRQ(ierr);
299409a357bSJakub Kruzik       }
300409a357bSJakub Kruzik       if (def->nestedlvl < def->maxnestedlvl) {
301409a357bSJakub Kruzik         size -= 1;
302409a357bSJakub Kruzik         ierr = MatDestroy(&def->W);CHKERRQ(ierr);
303409a357bSJakub Kruzik         def->W = mats[size];
304409a357bSJakub Kruzik         ierr = PetscObjectReference((PetscObject)mats[size]);CHKERRQ(ierr);
305409a357bSJakub Kruzik         if (size > 1) {
306409a357bSJakub Kruzik           ierr = MatCreateComposite(comm,size,mats,&nextDef);CHKERRQ(ierr);
307409a357bSJakub Kruzik           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
308409a357bSJakub Kruzik         } else {
309409a357bSJakub Kruzik           nextDef = mats[0];
310409a357bSJakub Kruzik           ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
311409a357bSJakub Kruzik         }
312409a357bSJakub Kruzik       } else {
313409a357bSJakub Kruzik         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
314409a357bSJakub Kruzik         ierr = MatCompositeMerge(def->W);CHKERRQ(ierr);
315409a357bSJakub Kruzik       }
316409a357bSJakub Kruzik     }
317409a357bSJakub Kruzik     ierr = PetscFree(mats);CHKERRQ(ierr);
318409a357bSJakub Kruzik   }
319409a357bSJakub Kruzik 
320409a357bSJakub Kruzik   /* setup coarse problem */
321409a357bSJakub Kruzik   if (!def->WtAWinv) {
322409a357bSJakub Kruzik     ierr = MatGetSize(def->W,NULL,&m);CHKERRQ(ierr); /* TODO works for W MatTranspose? */
323409a357bSJakub Kruzik     if (!def->WtAW) {
324409a357bSJakub Kruzik       ierr = PCGetOperators(pc,&Amat,NULL);CHKERRQ(ierr); /* using Amat! */
325409a357bSJakub Kruzik       /* TODO add implicit product version ? */
326409a357bSJakub Kruzik       if (!def->AW) {
327409a357bSJakub Kruzik         ierr = MatPtAP(Amat,def->W,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr);
328409a357bSJakub Kruzik       } else {
329409a357bSJakub Kruzik         ierr = MatTransposeMatMult(def->W,def->AW,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr);
330409a357bSJakub Kruzik       }
331409a357bSJakub Kruzik       /* TODO create MatInheritOption(Mat,MatOption) */
332409a357bSJakub Kruzik       ierr = MatGetOption(Amat,MAT_SPD,&flgspd);CHKERRQ(ierr);
333409a357bSJakub Kruzik       ierr = MatSetOption(def->WtAW,MAT_SPD,flgspd);CHKERRQ(ierr);
334409a357bSJakub Kruzik #if defined(PETSC_USE_DEBUG)
335409a357bSJakub Kruzik       /* Check WtAW is not sigular */
336409a357bSJakub Kruzik       PetscReal *norms;
337409a357bSJakub Kruzik       ierr = PetscMalloc1(m,&norms);CHKERRQ(ierr);
338409a357bSJakub Kruzik       ierr = MatGetColumnNorms(def->WtAW,NORM_INFINITY,norms);CHKERRQ(ierr);
339409a357bSJakub Kruzik       for (i=0; i<m; i++) {
340409a357bSJakub Kruzik         if (norms[i] < 100*PETSC_MACHINE_EPSILON) {
341409a357bSJakub Kruzik           SETERRQ1(comm,PETSC_ERR_SUP,"Column %D of W is in kernel of A.",i);
342409a357bSJakub Kruzik         }
343409a357bSJakub Kruzik       }
344409a357bSJakub Kruzik       ierr = PetscFree(norms);CHKERRQ(ierr);
345409a357bSJakub Kruzik #endif
346409a357bSJakub Kruzik     } else {
347409a357bSJakub Kruzik       ierr = MatGetOption(def->WtAW,MAT_SPD,&flgspd);CHKERRQ(ierr);
348409a357bSJakub Kruzik     }
349409a357bSJakub Kruzik     /* TODO use MATINV */
350409a357bSJakub Kruzik     ierr = KSPCreate(comm,&def->WtAWinv);CHKERRQ(ierr);
351409a357bSJakub Kruzik     ierr = KSPSetOperators(def->WtAWinv,def->WtAW,def->WtAW);CHKERRQ(ierr);
352409a357bSJakub Kruzik     ierr = KSPSetType(def->WtAWinv,KSPPREONLY);CHKERRQ(ierr);
353409a357bSJakub Kruzik     ierr = KSPGetPC(def->WtAWinv,&pcinner);CHKERRQ(ierr);
354409a357bSJakub Kruzik     ierr = PCSetType(pcinner,PCTELESCOPE);CHKERRQ(ierr);
355409a357bSJakub Kruzik     /* Reduction factor choice */
356409a357bSJakub Kruzik     red = def->reductionfact;
357409a357bSJakub Kruzik     if (red < 0) {
358409a357bSJakub Kruzik       ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
359409a357bSJakub Kruzik       red  = ceil((float)commsize/ceil((float)m/commsize));
360409a357bSJakub Kruzik       ierr = PetscObjectTypeCompareAny((PetscObject)(def->WtAW),&match,MATSEQDENSE,MATMPIDENSE,MATDENSE,"");CHKERRQ(ierr);
361409a357bSJakub Kruzik       if (match) red = commsize;
362409a357bSJakub Kruzik       ierr = PetscInfo1(pc,"Auto choosing reduction factor %D\n",red);CHKERRQ(ierr); /* TODO add level? */
363409a357bSJakub Kruzik     }
364409a357bSJakub Kruzik     ierr = PCTelescopeSetReductionFactor(pcinner,red);CHKERRQ(ierr);
365409a357bSJakub Kruzik     ierr = PCTelescopeGetKSP(pcinner,&innerksp);CHKERRQ(ierr);
366409a357bSJakub Kruzik     ierr = KSPGetPC(innerksp,&pcinner);CHKERRQ(ierr);
367409a357bSJakub Kruzik     /* Setup KSP and PC */
368409a357bSJakub Kruzik     if (nextDef) { /* next level for multilevel deflation */
369409a357bSJakub Kruzik       /* set default KSPtype */
370409a357bSJakub Kruzik       if (!def->ksptype) {
371409a357bSJakub Kruzik         def->ksptype = KSPFGMRES;
372409a357bSJakub Kruzik         if (flgspd) { /* SPD system */
373409a357bSJakub Kruzik           def->ksptype = KSPFCG;
374409a357bSJakub Kruzik         }
375409a357bSJakub Kruzik       }
376409a357bSJakub Kruzik       ierr = KSPSetType(innerksp,def->ksptype);CHKERRQ(ierr); /* TODO iherit from KSP */
377409a357bSJakub Kruzik       ierr = PCSetType(pcinner,PCDEFLATION);CHKERRQ(ierr); /* TODO create coarse preconditinoner M_c = WtMW ? */
378409a357bSJakub Kruzik       ierr = PCDeflationSetSpace(pcinner,nextDef,transp);CHKERRQ(ierr);
379*5c0c31c5SJakub Kruzik       ierr = PCDeflationSetLvl_Deflation(pcinner,def->nestedlvl+1,def->maxnestedlvl);CHKERRQ(ierr);
380409a357bSJakub Kruzik       /* inherit options TODO if not set */
381409a357bSJakub Kruzik       ((PC_Deflation*)(pcinner))->ksptype = def->ksptype;
382409a357bSJakub Kruzik       ((PC_Deflation*)(pcinner))->correct = def->correct;
383409a357bSJakub Kruzik       ((PC_Deflation*)(pcinner))->adaptiveconv = def->adaptiveconv;
384409a357bSJakub Kruzik       ((PC_Deflation*)(pcinner))->adaptiveconst = def->adaptiveconst;
385409a357bSJakub Kruzik       ierr = MatDestroy(&nextDef);CHKERRQ(ierr);
386409a357bSJakub Kruzik     } else { /* the last level */
387409a357bSJakub Kruzik       ierr = KSPSetType(innerksp,KSPPREONLY);CHKERRQ(ierr);
388409a357bSJakub Kruzik       /* TODO Cholesky if flgspd? */
389409a357bSJakub Kruzik       ierr = PCSetType(pc,PCLU);CHKERRQ(ierr);
390409a357bSJakub Kruzik       //TODO remove explicit matSolverPackage
391409a357bSJakub Kruzik       if (commsize == red) {
392409a357bSJakub Kruzik         ierr = PCFactorSetMatSolverType(pc,MATSOLVERSUPERLU);CHKERRQ(ierr);
393409a357bSJakub Kruzik       } else {
394409a357bSJakub Kruzik         ierr = PCFactorSetMatSolverType(pc,MATSOLVERSUPERLU_DIST);CHKERRQ(ierr);
395409a357bSJakub Kruzik       }
396409a357bSJakub Kruzik     }
397409a357bSJakub Kruzik     /* TODO use def_[lvl]_ if lvl > 0? */
398409a357bSJakub Kruzik     ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
399409a357bSJakub Kruzik     if (prefix) {
400409a357bSJakub Kruzik       ierr = KSPSetOptionsPrefix(innerksp,prefix);CHKERRQ(ierr);
401409a357bSJakub Kruzik       ierr = KSPAppendOptionsPrefix(innerksp,"def_");CHKERRQ(ierr);
402409a357bSJakub Kruzik     } else {
403409a357bSJakub Kruzik       ierr = KSPSetOptionsPrefix(innerksp,"def_");CHKERRQ(ierr);
404409a357bSJakub Kruzik     }
405409a357bSJakub Kruzik     /* TODO: check if WtAWinv is KSP and move following from this if */
406409a357bSJakub Kruzik     ierr = KSPSetFromOptions(def->WtAWinv);CHKERRQ(ierr);
407409a357bSJakub Kruzik     //if (def->adaptiveconv) {
408409a357bSJakub Kruzik     //  PetscReal *rnorm;
409409a357bSJakub Kruzik     //  PetscNew(&rnorm);
410409a357bSJakub Kruzik     //  ierr = KSPSetConvergenceTest(def->WtAWinv,KSPDCGConvergedAdaptive_DCG,rnorm,NULL);CHKERRQ(ierr);
411409a357bSJakub Kruzik     //}
412409a357bSJakub Kruzik     ierr = KSPSetUp(def->WtAWinv);CHKERRQ(ierr);
413409a357bSJakub Kruzik   }
414409a357bSJakub Kruzik 
415409a357bSJakub Kruzik   ierr = KSPCreateVecs(def->WtAWinv,2,&def->work,0,NULL);CHKERRQ(ierr);
41637eeb815SJakub Kruzik   PetscFunctionReturn(0);
41737eeb815SJakub Kruzik }
41837eeb815SJakub Kruzik /* -------------------------------------------------------------------------- */
41937eeb815SJakub Kruzik /*
42037eeb815SJakub Kruzik    PCApply_Deflation - Applies the Deflation preconditioner to a vector.
42137eeb815SJakub Kruzik 
42237eeb815SJakub Kruzik    Input Parameters:
42337eeb815SJakub Kruzik .  pc - the preconditioner context
42437eeb815SJakub Kruzik .  x - input vector
42537eeb815SJakub Kruzik 
42637eeb815SJakub Kruzik    Output Parameter:
42737eeb815SJakub Kruzik .  y - output vector
42837eeb815SJakub Kruzik 
42937eeb815SJakub Kruzik    Application Interface Routine: PCApply()
43037eeb815SJakub Kruzik  */
43137eeb815SJakub Kruzik static PetscErrorCode PCApply_Deflation(PC pc,Vec x,Vec y)
43237eeb815SJakub Kruzik {
43337eeb815SJakub Kruzik   PC_Deflation      *jac = (PC_Deflation*)pc->data;
43437eeb815SJakub Kruzik   PetscErrorCode ierr;
43537eeb815SJakub Kruzik 
43637eeb815SJakub Kruzik   PetscFunctionBegin;
43737eeb815SJakub Kruzik   PetscFunctionReturn(0);
43837eeb815SJakub Kruzik }
43937eeb815SJakub Kruzik /* -------------------------------------------------------------------------- */
44037eeb815SJakub Kruzik static PetscErrorCode PCReset_Deflation(PC pc)
44137eeb815SJakub Kruzik {
44237eeb815SJakub Kruzik   PC_Deflation      *jac = (PC_Deflation*)pc->data;
44337eeb815SJakub Kruzik   PetscErrorCode ierr;
44437eeb815SJakub Kruzik 
44537eeb815SJakub Kruzik   PetscFunctionBegin;
44637eeb815SJakub Kruzik   PetscFunctionReturn(0);
44737eeb815SJakub Kruzik }
44837eeb815SJakub Kruzik 
44937eeb815SJakub Kruzik /*
45037eeb815SJakub Kruzik    PCDestroy_Deflation - Destroys the private context for the Deflation preconditioner
45137eeb815SJakub Kruzik    that was created with PCCreate_Deflation().
45237eeb815SJakub Kruzik 
45337eeb815SJakub Kruzik    Input Parameter:
45437eeb815SJakub Kruzik .  pc - the preconditioner context
45537eeb815SJakub Kruzik 
45637eeb815SJakub Kruzik    Application Interface Routine: PCDestroy()
45737eeb815SJakub Kruzik */
45837eeb815SJakub Kruzik static PetscErrorCode PCDestroy_Deflation(PC pc)
45937eeb815SJakub Kruzik {
46037eeb815SJakub Kruzik   PetscErrorCode ierr;
46137eeb815SJakub Kruzik 
46237eeb815SJakub Kruzik   PetscFunctionBegin;
46337eeb815SJakub Kruzik   ierr = PCReset_Deflation(pc);CHKERRQ(ierr);
46437eeb815SJakub Kruzik 
46537eeb815SJakub Kruzik   /*
46637eeb815SJakub Kruzik       Free the private data structure that was hanging off the PC
46737eeb815SJakub Kruzik   */
46837eeb815SJakub Kruzik   ierr = PetscFree(pc->data);CHKERRQ(ierr);
46937eeb815SJakub Kruzik   PetscFunctionReturn(0);
47037eeb815SJakub Kruzik }
47137eeb815SJakub Kruzik 
47237eeb815SJakub Kruzik static PetscErrorCode PCSetFromOptions_Deflation(PetscOptionItems *PetscOptionsObject,PC pc)
47337eeb815SJakub Kruzik {
47437eeb815SJakub Kruzik   PC_Deflation      *jac = (PC_Deflation*)pc->data;
47537eeb815SJakub Kruzik   PetscErrorCode ierr;
47637eeb815SJakub Kruzik   PetscBool      flg;
47737eeb815SJakub Kruzik   PCDeflationType   deflt,type;
47837eeb815SJakub Kruzik 
47937eeb815SJakub Kruzik   PetscFunctionBegin;
48037eeb815SJakub Kruzik   ierr = PCDeflationGetType(pc,&deflt);CHKERRQ(ierr);
48137eeb815SJakub Kruzik   ierr = PetscOptionsHead(PetscOptionsObject,"Deflation options");CHKERRQ(ierr);
48237eeb815SJakub Kruzik   ierr = PetscOptionsEnum("-pc_jacobi_type","How to construct diagonal matrix","PCDeflationSetType",PCDeflationTypes,(PetscEnum)deflt,(PetscEnum*)&type,&flg);CHKERRQ(ierr);
48337eeb815SJakub Kruzik   if (flg) {
48437eeb815SJakub Kruzik     ierr = PCDeflationSetType(pc,type);CHKERRQ(ierr);
48537eeb815SJakub Kruzik   }
48637eeb815SJakub Kruzik   ierr = PetscOptionsTail();CHKERRQ(ierr);
48737eeb815SJakub Kruzik   PetscFunctionReturn(0);
48837eeb815SJakub Kruzik }
48937eeb815SJakub Kruzik 
49037eeb815SJakub Kruzik /*MC
491e361f8b5SJakub Kruzik      PCDEFLATION - Deflation preconditioner shifts part of the spectrum to zero (deflates)
492e361f8b5SJakub Kruzik      or to a predefined value
49337eeb815SJakub Kruzik 
49437eeb815SJakub Kruzik    Options Database Key:
495e361f8b5SJakub Kruzik +    -pc_deflation_type <init,pre,post> - selects approach to deflation (default: pre)
49637eeb815SJakub Kruzik -    -pc_jacobi_abs - use the absolute value of the diagonal entry
49737eeb815SJakub Kruzik 
49837eeb815SJakub Kruzik    Level: beginner
49937eeb815SJakub Kruzik 
50037eeb815SJakub Kruzik   Notes:
501e361f8b5SJakub Kruzik     todo
50237eeb815SJakub Kruzik 
50337eeb815SJakub Kruzik .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
504e662bc50SJakub Kruzik            PCDeflationSetType(), PCDeflationSetSpace()
50537eeb815SJakub Kruzik M*/
50637eeb815SJakub Kruzik 
50737eeb815SJakub Kruzik PETSC_EXTERN PetscErrorCode PCCreate_Deflation(PC pc)
50837eeb815SJakub Kruzik {
50937eeb815SJakub Kruzik   PC_Deflation   *def;
51037eeb815SJakub Kruzik   PetscErrorCode ierr;
51137eeb815SJakub Kruzik 
51237eeb815SJakub Kruzik   PetscFunctionBegin;
51337eeb815SJakub Kruzik   ierr     = PetscNewLog(pc,&def);CHKERRQ(ierr);
51437eeb815SJakub Kruzik   pc->data = (void*)def;
51537eeb815SJakub Kruzik 
516e662bc50SJakub Kruzik   def->init          = PETSC_FALSE;
517e662bc50SJakub Kruzik   def->pre           = PETSC_TRUE;
518e662bc50SJakub Kruzik   def->correct       = PETSC_FALSE;
519e662bc50SJakub Kruzik   def->truenorm      = PETSC_TRUE;
520e662bc50SJakub Kruzik   def->reductionfact = -1;
521e662bc50SJakub Kruzik   def->spacetype     = PC_DEFLATION_SPACE_HAAR;
522e662bc50SJakub Kruzik   def->spacesize     = 1;
523e662bc50SJakub Kruzik   def->extendsp      = PETSC_FALSE;
524e662bc50SJakub Kruzik   def->nestedlvl     = 0;
525e662bc50SJakub Kruzik   def->maxnestedlvl  = 0;
526e662bc50SJakub Kruzik   def->adaptiveconv  = PETSC_FALSE;
527e662bc50SJakub Kruzik   def->adaptiveconst = 1.0;
52837eeb815SJakub Kruzik 
52937eeb815SJakub Kruzik   /*
53037eeb815SJakub Kruzik       Set the pointers for the functions that are provided above.
53137eeb815SJakub Kruzik       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
53237eeb815SJakub Kruzik       are called, they will automatically call these functions.  Note we
53337eeb815SJakub Kruzik       choose not to provide a couple of these functions since they are
53437eeb815SJakub Kruzik       not needed.
53537eeb815SJakub Kruzik   */
53637eeb815SJakub Kruzik   pc->ops->apply               = PCApply_Deflation;
53737eeb815SJakub Kruzik   pc->ops->applytranspose      = PCApply_Deflation;
53837eeb815SJakub Kruzik   pc->ops->setup               = PCSetUp_Deflation;
53937eeb815SJakub Kruzik   pc->ops->reset               = PCReset_Deflation;
54037eeb815SJakub Kruzik   pc->ops->destroy             = PCDestroy_Deflation;
54137eeb815SJakub Kruzik   pc->ops->setfromoptions      = PCSetFromOptions_Deflation;
54237eeb815SJakub Kruzik   pc->ops->view                = 0;
54337eeb815SJakub Kruzik   pc->ops->applyrichardson     = 0;
54437eeb815SJakub Kruzik   pc->ops->applysymmetricleft  = 0;
54537eeb815SJakub Kruzik   pc->ops->applysymmetricright = 0;
54637eeb815SJakub Kruzik 
54737eeb815SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetType_C",PCDeflationSetType_Deflation);CHKERRQ(ierr);
54837eeb815SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetType_C",PCDeflationGetType_Deflation);CHKERRQ(ierr);
549e662bc50SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpace_C",PCDeflationSetSpace_Deflation);CHKERRQ(ierr);
550*5c0c31c5SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetLvl_C",PCDeflationSetLvl_Deflation);CHKERRQ(ierr);
55137eeb815SJakub Kruzik   PetscFunctionReturn(0);
55237eeb815SJakub Kruzik }
55337eeb815SJakub Kruzik 
554