xref: /petsc/src/ksp/pc/impls/deflation/deflation.c (revision 81e2347e0c8d4c7b8b7e0abea2b4c8a12f0fcba6)
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 
51292e2e67SJakub Kruzik #include <../src/ksp/pc/impls/deflation/deflation.h> /*I "petscpc.h" I*/  /* includes for fortran wrappers */
5237eeb815SJakub Kruzik 
5337eeb815SJakub Kruzik const char *const PCDeflationTypes[]    = {"INIT","PRE","POST","PCDeflationType","PC_DEFLATION_",0};
5437eeb815SJakub Kruzik 
558513960bSJakub Kruzik const char *const PCDeflationSpaceTypes[] = {
568513960bSJakub Kruzik   "haar",
578513960bSJakub Kruzik   "jacket-haar",
588513960bSJakub Kruzik   "db2",
598513960bSJakub Kruzik   "db4",
608513960bSJakub Kruzik   "db8",
618513960bSJakub Kruzik   "db16",
628513960bSJakub Kruzik   "biorth22",
638513960bSJakub Kruzik   "meyer",
648513960bSJakub Kruzik   "aggregation",
658513960bSJakub Kruzik   "slepc",
668513960bSJakub Kruzik   "slepc-cheap",
678513960bSJakub Kruzik   "user",
688513960bSJakub Kruzik   "DdefSpaceType",
698513960bSJakub Kruzik   "Ddef_SPACE_",
708513960bSJakub Kruzik   0
718513960bSJakub Kruzik };
728513960bSJakub Kruzik 
738513960bSJakub Kruzik 
74e662bc50SJakub Kruzik static PetscErrorCode PCDeflationSetSpace_Deflation(PC pc,Mat W,PetscBool transpose)
75e662bc50SJakub Kruzik {
76e662bc50SJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
77e662bc50SJakub Kruzik   PetscErrorCode ierr;
78e662bc50SJakub Kruzik 
79e662bc50SJakub Kruzik   PetscFunctionBegin;
80e662bc50SJakub Kruzik   if (transpose) {
81e662bc50SJakub Kruzik     def->Wt = W;
82e662bc50SJakub Kruzik     def->W = NULL;
83e662bc50SJakub Kruzik   } else {
84e662bc50SJakub Kruzik     def->W = W;
85e662bc50SJakub Kruzik   }
86e662bc50SJakub Kruzik   ierr = PetscObjectReference((PetscObject)W);CHKERRQ(ierr);
87e662bc50SJakub Kruzik   PetscFunctionReturn(0);
88e662bc50SJakub Kruzik }
89e662bc50SJakub Kruzik 
90e662bc50SJakub Kruzik /* TODO create PCDeflationSetSpaceTranspose? */
91e662bc50SJakub Kruzik /*@
92e662bc50SJakub Kruzik    PCDeflationSetSpace - Set deflation space matrix (or its transpose).
93e662bc50SJakub Kruzik 
94e662bc50SJakub Kruzik    Logically Collective on PC
95e662bc50SJakub Kruzik 
96e662bc50SJakub Kruzik    Input Parameters:
97e662bc50SJakub Kruzik +  pc - the preconditioner context
98e662bc50SJakub Kruzik .  W  - deflation matrix
99e662bc50SJakub Kruzik -  tranpose - indicates that W is an explicit transpose of the deflation matrix
100e662bc50SJakub Kruzik 
101e662bc50SJakub Kruzik    Level: intermediate
102e662bc50SJakub Kruzik 
103e662bc50SJakub Kruzik .seealso: PCDEFLATION
104e662bc50SJakub Kruzik @*/
105e662bc50SJakub Kruzik PetscErrorCode PCDeflationSetSpace(PC pc,Mat W,PetscBool transpose)
106e662bc50SJakub Kruzik {
107e662bc50SJakub Kruzik   PetscErrorCode ierr;
108e662bc50SJakub Kruzik 
109e662bc50SJakub Kruzik   PetscFunctionBegin;
110e662bc50SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
111e662bc50SJakub Kruzik   PetscValidHeaderSpecific(W,MAT_CLASSID,2);
112e662bc50SJakub Kruzik   PetscValidLogicalCollectiveBool(pc,transpose,3);
113e662bc50SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetSpace_C",(PC,Mat,PetscBool),(pc,W,transpose));CHKERRQ(ierr);
114e662bc50SJakub Kruzik   PetscFunctionReturn(0);
115e662bc50SJakub Kruzik }
116e662bc50SJakub Kruzik 
1175c0c31c5SJakub Kruzik static PetscErrorCode PCDeflationSetLvl_Deflation(PC pc,PetscInt current,PetscInt max)
1185c0c31c5SJakub Kruzik {
1195c0c31c5SJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
1205c0c31c5SJakub Kruzik 
1215c0c31c5SJakub Kruzik   PetscFunctionBegin;
122*81e2347eSJakub Kruzik   if (current) def->nestedlvl = current;
1235c0c31c5SJakub Kruzik   def->maxnestedlvl = max;
1245c0c31c5SJakub Kruzik   PetscFunctionReturn(0);
1255c0c31c5SJakub Kruzik }
1265c0c31c5SJakub Kruzik 
1275c0c31c5SJakub Kruzik /*@
1285c0c31c5SJakub Kruzik    PCDeflationSetMaxLvl - Set maximum level of deflation.
1295c0c31c5SJakub Kruzik 
1305c0c31c5SJakub Kruzik    Logically Collective on PC
1315c0c31c5SJakub Kruzik 
1325c0c31c5SJakub Kruzik    Input Parameters:
1335c0c31c5SJakub Kruzik +  pc  - the preconditioner context
13422b0793eSJakub Kruzik -  max - maximum deflation level
1355c0c31c5SJakub Kruzik 
1365c0c31c5SJakub Kruzik    Level: intermediate
1375c0c31c5SJakub Kruzik 
1385c0c31c5SJakub Kruzik .seealso: PCDEFLATION
1395c0c31c5SJakub Kruzik @*/
1405c0c31c5SJakub Kruzik PetscErrorCode PCDeflationSetMaxLvl(PC pc,PetscInt max)
1415c0c31c5SJakub Kruzik {
1425c0c31c5SJakub Kruzik   PetscErrorCode ierr;
1435c0c31c5SJakub Kruzik 
1445c0c31c5SJakub Kruzik   PetscFunctionBegin;
14522b0793eSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1465c0c31c5SJakub Kruzik   PetscValidLogicalCollectiveInt(pc,max,2);
1475c0c31c5SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetLvl_C",(PC,PetscInt,PetscInt),(pc,0,max));CHKERRQ(ierr);
1485c0c31c5SJakub Kruzik   PetscFunctionReturn(0);
1495c0c31c5SJakub Kruzik }
150e662bc50SJakub Kruzik 
15122b0793eSJakub Kruzik static PetscErrorCode PCDeflationSetPC_Deflation(PC pc,PC apc)
15222b0793eSJakub Kruzik {
15322b0793eSJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
15422b0793eSJakub Kruzik   PetscErrorCode ierr;
15522b0793eSJakub Kruzik 
15622b0793eSJakub Kruzik   PetscFunctionBegin;
15722b0793eSJakub Kruzik   ierr = PCDestroy(&def->pc);CHKERRQ(ierr);
15822b0793eSJakub Kruzik   def->pc = apc;
15922b0793eSJakub Kruzik   ierr = PetscObjectReference((PetscObject)apc);CHKERRQ(ierr);
16022b0793eSJakub Kruzik   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->pc);CHKERRQ(ierr);
16122b0793eSJakub Kruzik   PetscFunctionReturn(0);
16222b0793eSJakub Kruzik }
16322b0793eSJakub Kruzik 
16422b0793eSJakub Kruzik /*@
16522b0793eSJakub Kruzik    PCDeflationSetPC - Set additional preconditioner.
16622b0793eSJakub Kruzik 
16722b0793eSJakub Kruzik    Logically Collective on PC
16822b0793eSJakub Kruzik 
16922b0793eSJakub Kruzik    Input Parameters:
17022b0793eSJakub Kruzik +  pc  - the preconditioner context
17122b0793eSJakub Kruzik -  apc - additional preconditioner
17222b0793eSJakub Kruzik 
17322b0793eSJakub Kruzik    Level: advanced
17422b0793eSJakub Kruzik 
17522b0793eSJakub Kruzik .seealso: PCDEFLATION
17622b0793eSJakub Kruzik @*/
17722b0793eSJakub Kruzik PetscErrorCode PCDeflationSetPC(PC pc,PC apc)
17822b0793eSJakub Kruzik {
17922b0793eSJakub Kruzik   PetscErrorCode ierr;
18022b0793eSJakub Kruzik 
18122b0793eSJakub Kruzik   PetscFunctionBegin;
18222b0793eSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
18322b0793eSJakub Kruzik   PetscValidHeaderSpecific(apc,PC_CLASSID,2);
18422b0793eSJakub Kruzik   PetscCheckSameComm(pc,1,apc,2);
18522b0793eSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetPC_C",(PC,PC),(pc,apc));CHKERRQ(ierr);
18622b0793eSJakub Kruzik   PetscFunctionReturn(0);
18722b0793eSJakub Kruzik }
18822b0793eSJakub Kruzik 
18937eeb815SJakub Kruzik /*
190b27c8092SJakub Kruzik   x <- x + W*(W'*A*W)^{-1}*W'*r  = x + Q*r
191b27c8092SJakub Kruzik */
192b27c8092SJakub Kruzik static PetscErrorCode PCPreSolve_Deflation(PC pc,KSP ksp,Vec b, Vec x)
193b27c8092SJakub Kruzik {
194b27c8092SJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
195b27c8092SJakub Kruzik   Mat              A;
196b27c8092SJakub Kruzik   Vec              r,w1,w2;
197b27c8092SJakub Kruzik   PetscBool        nonzero;
198b27c8092SJakub Kruzik   PetscErrorCode   ierr;
19937eeb815SJakub Kruzik 
200b27c8092SJakub Kruzik   PetscFunctionBegin;
201b27c8092SJakub Kruzik   w1 = def->workcoarse[0];
202b27c8092SJakub Kruzik   w2 = def->workcoarse[1];
203b27c8092SJakub Kruzik   r  = def->work;
204b27c8092SJakub Kruzik   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
20537eeb815SJakub Kruzik 
206b27c8092SJakub Kruzik   ierr = KSPGetInitialGuessNonzero(ksp,&nonzero);CHKERRQ(ierr);
207b27c8092SJakub Kruzik   ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
208b27c8092SJakub Kruzik   if (nonzero) {
209b27c8092SJakub Kruzik     ierr = MatMult(A,x,r);CHKERRQ(ierr);               /*    r  <- b - Ax              */
210b27c8092SJakub Kruzik     ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr);
211b27c8092SJakub Kruzik   } else {
212b27c8092SJakub Kruzik     ierr = VecCopy(b,r);CHKERRQ(ierr);                 /*    r  <- b (x is 0)          */
213b27c8092SJakub Kruzik   }
214b27c8092SJakub Kruzik 
215b27c8092SJakub Kruzik   ierr = MatMultTranspose(def->W,r,w1);CHKERRQ(ierr);  /*    w1 <- W'*r                */
216b27c8092SJakub Kruzik   ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);   /*    w2 <- (W'*A*W)^{-1}*w1    */
217b27c8092SJakub Kruzik   ierr = MatMult(def->W,w2,r);CHKERRQ(ierr);           /*    r  <- W*w2                */
218b27c8092SJakub Kruzik   ierr = VecAYPX(x,1.0,r);CHKERRQ(ierr);
219b27c8092SJakub Kruzik   PetscFunctionReturn(0);
220b27c8092SJakub Kruzik }
22137eeb815SJakub Kruzik 
222f8bf229cSJakub Kruzik /*
223f8bf229cSJakub Kruzik   if (def->correct) {
22422b0793eSJakub Kruzik     z <- r - W*(W'*A*W)^{-1}*W'*(A*r -r) = (P-Q)*M^{-1}*r
225f8bf229cSJakub Kruzik   } else {
22622b0793eSJakub Kruzik     z <- r - W*(W'*A*W)^{-1}*W'*A*r = P*M^{-1}*r
227f8bf229cSJakub Kruzik   }
22837eeb815SJakub Kruzik */
229f8bf229cSJakub Kruzik static PetscErrorCode PCApply_Deflation(PC pc,Vec r,Vec z)
230f8bf229cSJakub Kruzik {
231f8bf229cSJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
232f8bf229cSJakub Kruzik   Mat              A;
233f8bf229cSJakub Kruzik   Vec              u,w1,w2;
234f8bf229cSJakub Kruzik   PetscErrorCode   ierr;
235f8bf229cSJakub Kruzik 
236f8bf229cSJakub Kruzik   PetscFunctionBegin;
237f8bf229cSJakub Kruzik   w1 = def->workcoarse[0];
238f8bf229cSJakub Kruzik   w2 = def->workcoarse[1];
239f8bf229cSJakub Kruzik   u  = def->work;
240f8bf229cSJakub Kruzik   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
241f8bf229cSJakub Kruzik 
24222b0793eSJakub Kruzik   ierr = PCApply(def->pc,r,z);CHKERRQ(ierr);
24322b0793eSJakub Kruzik   if (!def->init) {
244f8bf229cSJakub Kruzik     if (!def->AW) {
24522b0793eSJakub Kruzik       ierr = MatMult(A,z,u);CHKERRQ(ierr);                       /*    u  <- A*z                 */
24622b0793eSJakub Kruzik       /* TODO correct const */
24722b0793eSJakub Kruzik       if (def->correct) ierr = VecAXPY(u,-1.0,z);CHKERRQ(ierr);  /*    u  <- A*z -z              */
248f8bf229cSJakub Kruzik       ierr = MatMultTranspose(def->W,u,w1);CHKERRQ(ierr);        /*    w1 <- W'*u                */
249f8bf229cSJakub Kruzik     } else {
25022b0793eSJakub Kruzik       /* ONLY if A SYM */
25122b0793eSJakub Kruzik       ierr = MatMultTranspose(def->AW,z,w1);CHKERRQ(ierr);       /*    w1  <- W'*A*r             */
252f8bf229cSJakub Kruzik       if (def->correct) {
25322b0793eSJakub Kruzik         ierr = MatMultTranspose(def->W,z,w2);CHKERRQ(ierr);      /*    w2 <- W'*u                */
254f8bf229cSJakub Kruzik         ierr = VecAXPY(w1,-1.0,w2);CHKERRQ(ierr);                /*    w1 <- w1 - w2             */
255f8bf229cSJakub Kruzik       }
256f8bf229cSJakub Kruzik     }
257f8bf229cSJakub Kruzik     ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);           /*    w2 <- (W'*A*W)^{-1}*w1    */
258f8bf229cSJakub Kruzik     ierr = MatMult(def->W,w2,u);CHKERRQ(ierr);                   /*    u  <- W*w2                */
25922b0793eSJakub Kruzik     ierr = VecAXPY(z,-1.0,u);CHKERRQ(ierr);                      /*    z  <- z - u               */
26022b0793eSJakub Kruzik   }
261f8bf229cSJakub Kruzik   PetscFunctionReturn(0);
262f8bf229cSJakub Kruzik }
263f8bf229cSJakub Kruzik 
264b27c8092SJakub Kruzik static PetscErrorCode  PCDeflationSetType_Deflation(PC pc,PCDeflationType type)
265b27c8092SJakub Kruzik {
266b27c8092SJakub Kruzik   PC_Deflation *def = (PC_Deflation*)pc->data;
267b27c8092SJakub Kruzik 
268b27c8092SJakub Kruzik   PetscFunctionBegin;
269b27c8092SJakub Kruzik   def->init = PETSC_FALSE;
270b27c8092SJakub Kruzik   def->pre = PETSC_FALSE;
271b27c8092SJakub Kruzik   if (type == PC_DEFLATION_POST) {
272b27c8092SJakub Kruzik     //pc->ops->postsolve = PCPostSolve_Deflation;
273b27c8092SJakub Kruzik     pc->ops->presolve = 0;
274b27c8092SJakub Kruzik   } else {
275b27c8092SJakub Kruzik     pc->ops->presolve = PCPreSolve_Deflation;
276b27c8092SJakub Kruzik     pc->ops->postsolve = 0;
277b27c8092SJakub Kruzik     if (type == PC_DEFLATION_INIT) {
278b27c8092SJakub Kruzik       def->init = PETSC_TRUE;
279b27c8092SJakub Kruzik       pc->ops->apply = 0;
280b27c8092SJakub Kruzik     } else {
281b27c8092SJakub Kruzik       def->pre  = PETSC_TRUE;
282b27c8092SJakub Kruzik     }
283b27c8092SJakub Kruzik   }
284b27c8092SJakub Kruzik   PetscFunctionReturn(0);
285b27c8092SJakub Kruzik }
286b27c8092SJakub Kruzik 
287b27c8092SJakub Kruzik /*@
288b27c8092SJakub Kruzik    PCDeflationSetType - Causes the deflation preconditioner to use only a special
289b27c8092SJakub Kruzik     initial gues or pre/post solve solution update
290b27c8092SJakub Kruzik 
291b27c8092SJakub Kruzik    Logically Collective on PC
292b27c8092SJakub Kruzik 
293b27c8092SJakub Kruzik    Input Parameters:
294b27c8092SJakub Kruzik +  pc - the preconditioner context
295b27c8092SJakub Kruzik -  type - PC_DEFLATION_PRE, PC_DEFLATION_INIT, PC_DEFLATION_POST
296b27c8092SJakub Kruzik 
297b27c8092SJakub Kruzik    Options Database Key:
298b27c8092SJakub Kruzik .  -pc_deflation_type <pre,init,post>
299b27c8092SJakub Kruzik 
300b27c8092SJakub Kruzik    Level: intermediate
301b27c8092SJakub Kruzik 
302b27c8092SJakub Kruzik    Concepts: Deflation preconditioner
303b27c8092SJakub Kruzik 
304b27c8092SJakub Kruzik .seealso: PCDeflationGetType()
305b27c8092SJakub Kruzik @*/
306b27c8092SJakub Kruzik PetscErrorCode  PCDeflationSetType(PC pc,PCDeflationType type)
307b27c8092SJakub Kruzik {
308b27c8092SJakub Kruzik   PetscErrorCode ierr;
309b27c8092SJakub Kruzik 
310b27c8092SJakub Kruzik   PetscFunctionBegin;
311b27c8092SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
312b27c8092SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetType_C",(PC,PCDeflationType),(pc,type));CHKERRQ(ierr);
313b27c8092SJakub Kruzik   PetscFunctionReturn(0);
314b27c8092SJakub Kruzik }
315b27c8092SJakub Kruzik 
316b27c8092SJakub Kruzik static PetscErrorCode  PCDeflationGetType_Deflation(PC pc,PCDeflationType *type)
317b27c8092SJakub Kruzik {
318b27c8092SJakub Kruzik   PC_Deflation *def = (PC_Deflation*)pc->data;
319b27c8092SJakub Kruzik 
320b27c8092SJakub Kruzik   PetscFunctionBegin;
321b27c8092SJakub Kruzik   if (def->init) {
322b27c8092SJakub Kruzik     *type = PC_DEFLATION_INIT;
323b27c8092SJakub Kruzik   } else if (def->pre) {
324b27c8092SJakub Kruzik     *type = PC_DEFLATION_PRE;
325b27c8092SJakub Kruzik   } else {
326b27c8092SJakub Kruzik     *type = PC_DEFLATION_POST;
327b27c8092SJakub Kruzik   }
328b27c8092SJakub Kruzik   PetscFunctionReturn(0);
329b27c8092SJakub Kruzik }
330b27c8092SJakub Kruzik 
331b27c8092SJakub Kruzik /*@
332b27c8092SJakub Kruzik    PCDeflationGetType - Gets how the diagonal matrix is produced for the preconditioner
333b27c8092SJakub Kruzik 
334b27c8092SJakub Kruzik    Not Collective on PC
335b27c8092SJakub Kruzik 
336b27c8092SJakub Kruzik    Input Parameter:
337b27c8092SJakub Kruzik .  pc - the preconditioner context
338b27c8092SJakub Kruzik 
339b27c8092SJakub Kruzik    Output Parameter:
340b27c8092SJakub Kruzik -  type - PC_DEFLATION_PRE, PC_DEFLATION_INIT, PC_DEFLATION_POST
341b27c8092SJakub Kruzik 
342b27c8092SJakub Kruzik    Level: intermediate
343b27c8092SJakub Kruzik 
344b27c8092SJakub Kruzik    Concepts: Deflation preconditioner
345b27c8092SJakub Kruzik 
346b27c8092SJakub Kruzik .seealso: PCDeflationSetType()
347b27c8092SJakub Kruzik @*/
348b27c8092SJakub Kruzik PetscErrorCode  PCDeflationGetType(PC pc,PCDeflationType *type)
349b27c8092SJakub Kruzik {
350b27c8092SJakub Kruzik   PetscErrorCode ierr;
351b27c8092SJakub Kruzik 
352b27c8092SJakub Kruzik   PetscFunctionBegin;
353b27c8092SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
354b27c8092SJakub Kruzik   ierr = PetscUseMethod(pc,"PCDeflationGetType_C",(PC,PCDeflationType*),(pc,type));CHKERRQ(ierr);
355b27c8092SJakub Kruzik   PetscFunctionReturn(0);
356b27c8092SJakub Kruzik }
357b27c8092SJakub Kruzik 
35837eeb815SJakub Kruzik static PetscErrorCode PCSetUp_Deflation(PC pc)
35937eeb815SJakub Kruzik {
360409a357bSJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
361409a357bSJakub Kruzik   KSP              innerksp;
362409a357bSJakub Kruzik   PC               pcinner;
363409a357bSJakub Kruzik   Mat              Amat,nextDef=NULL,*mats;
364409a357bSJakub Kruzik   PetscInt         i,m,red,size,commsize;
365409a357bSJakub Kruzik   PetscBool        match,flgspd,transp=PETSC_FALSE;
366409a357bSJakub Kruzik   MatCompositeType ctype;
367409a357bSJakub Kruzik   MPI_Comm         comm;
368409a357bSJakub Kruzik   const char       *prefix;
36937eeb815SJakub Kruzik   PetscErrorCode   ierr;
37037eeb815SJakub Kruzik 
37137eeb815SJakub Kruzik   PetscFunctionBegin;
372409a357bSJakub Kruzik   if (pc->setupcalled) PetscFunctionReturn(0);
373409a357bSJakub Kruzik   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
374f8bf229cSJakub Kruzik   ierr = PCGetOperators(pc,NULL,&Amat);CHKERRQ(ierr);
375f8bf229cSJakub Kruzik 
376f8bf229cSJakub Kruzik   /* compute a deflation space */
377409a357bSJakub Kruzik   if (def->W || def->Wt) {
378409a357bSJakub Kruzik     def->spacetype = PC_DEFLATION_SPACE_USER;
379409a357bSJakub Kruzik   } else {
380e53e0a0dSJakub Kruzik     ierr = PCDeflationComputeSpace(pc);CHKERRQ(ierr);
38137eeb815SJakub Kruzik   }
38237eeb815SJakub Kruzik 
383409a357bSJakub Kruzik   /* nested deflation */
384409a357bSJakub Kruzik   if (def->W) {
385409a357bSJakub Kruzik     ierr = PetscObjectTypeCompare((PetscObject)def->W,MATCOMPOSITE,&match);CHKERRQ(ierr);
386409a357bSJakub Kruzik     if (match) {
387409a357bSJakub Kruzik       ierr = MatCompositeGetType(def->W,&ctype);CHKERRQ(ierr);
388409a357bSJakub Kruzik       ierr = MatCompositeGetNumberMat(def->W,&size);CHKERRQ(ierr);
38937eeb815SJakub Kruzik     }
390409a357bSJakub Kruzik   } else {
391409a357bSJakub Kruzik     ierr = MatCreateTranspose(def->Wt,&def->W);CHKERRQ(ierr);
392409a357bSJakub Kruzik     ierr = PetscObjectTypeCompare((PetscObject)def->Wt,MATCOMPOSITE,&match);CHKERRQ(ierr);
393409a357bSJakub Kruzik     if (match) {
394409a357bSJakub Kruzik       ierr = MatCompositeGetType(def->Wt,&ctype);CHKERRQ(ierr);
395409a357bSJakub Kruzik       ierr = MatCompositeGetNumberMat(def->Wt,&size);CHKERRQ(ierr);
396409a357bSJakub Kruzik     }
397409a357bSJakub Kruzik     transp = PETSC_TRUE;
398409a357bSJakub Kruzik   }
399409a357bSJakub Kruzik   if (match && ctype == MAT_COMPOSITE_MULTIPLICATIVE) {
400409a357bSJakub Kruzik     if (!transp) {
40128da0170SJakub Kruzik       if (def->nestedlvl < def->maxnestedlvl) {
40228da0170SJakub Kruzik         ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
403409a357bSJakub Kruzik         for (i=0; i<size; i++) {
404409a357bSJakub Kruzik           ierr = MatCompositeGetMat(def->W,i,&mats[i]);CHKERRQ(ierr);
405409a357bSJakub Kruzik         }
406409a357bSJakub Kruzik         size -= 1;
407409a357bSJakub Kruzik         ierr = MatDestroy(&def->W);CHKERRQ(ierr);
408409a357bSJakub Kruzik         def->W = mats[size];
409409a357bSJakub Kruzik         ierr = PetscObjectReference((PetscObject)mats[size]);CHKERRQ(ierr);
410409a357bSJakub Kruzik         if (size > 1) {
411409a357bSJakub Kruzik           ierr = MatCreateComposite(comm,size,mats,&nextDef);CHKERRQ(ierr);
412409a357bSJakub Kruzik           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
413409a357bSJakub Kruzik         } else {
414409a357bSJakub Kruzik           nextDef = mats[0];
415409a357bSJakub Kruzik           ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
416409a357bSJakub Kruzik         }
41728da0170SJakub Kruzik         ierr = PetscFree(mats);CHKERRQ(ierr);
418409a357bSJakub Kruzik       } else {
419409a357bSJakub Kruzik         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
420409a357bSJakub Kruzik         ierr = MatCompositeMerge(def->W);CHKERRQ(ierr);
421409a357bSJakub Kruzik       }
42228da0170SJakub Kruzik     } else {
42328da0170SJakub Kruzik       if (def->nestedlvl < def->maxnestedlvl) {
42428da0170SJakub Kruzik         ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
42528da0170SJakub Kruzik         for (i=0; i<size; i++) {
42628da0170SJakub Kruzik           ierr = MatCompositeGetMat(def->Wt,i,&mats[i]);CHKERRQ(ierr);
42728da0170SJakub Kruzik         }
42828da0170SJakub Kruzik         size -= 1;
42928da0170SJakub Kruzik         ierr = MatDestroy(&def->Wt);CHKERRQ(ierr);
43028da0170SJakub Kruzik         def->Wt = mats[0];
43128da0170SJakub Kruzik         ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
43228da0170SJakub Kruzik         if (size > 1) {
43328da0170SJakub Kruzik           ierr = MatCreateComposite(comm,size,&mats[1],&nextDef);CHKERRQ(ierr);
43428da0170SJakub Kruzik           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
43528da0170SJakub Kruzik         } else {
43628da0170SJakub Kruzik           nextDef = mats[1];
43728da0170SJakub Kruzik           ierr = PetscObjectReference((PetscObject)mats[1]);CHKERRQ(ierr);
438409a357bSJakub Kruzik         }
439409a357bSJakub Kruzik         ierr = PetscFree(mats);CHKERRQ(ierr);
44028da0170SJakub Kruzik       } else {
44128da0170SJakub Kruzik         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
44228da0170SJakub Kruzik         ierr = MatCompositeMerge(def->Wt);CHKERRQ(ierr);
44328da0170SJakub Kruzik       }
44428da0170SJakub Kruzik     }
44528da0170SJakub Kruzik   }
44628da0170SJakub Kruzik 
44728da0170SJakub Kruzik   if (transp) {
44828da0170SJakub Kruzik     ierr = MatDestroy(&def->W);CHKERRQ(ierr);
44928da0170SJakub Kruzik     ierr = MatTranspose(def->Wt,MAT_INITIAL_MATRIX,&def->W);CHKERRQ(ierr);
450409a357bSJakub Kruzik   }
451409a357bSJakub Kruzik 
45222b0793eSJakub Kruzik 
45322b0793eSJakub Kruzik   ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
45422b0793eSJakub Kruzik 
455409a357bSJakub Kruzik   /* setup coarse problem */
456409a357bSJakub Kruzik   if (!def->WtAWinv) {
45728da0170SJakub Kruzik     ierr = MatGetSize(def->W,NULL,&m);CHKERRQ(ierr);
458409a357bSJakub Kruzik     if (!def->WtAW) {
459409a357bSJakub Kruzik       /* TODO add implicit product version ? */
460409a357bSJakub Kruzik       if (!def->AW) {
461409a357bSJakub Kruzik         ierr = MatPtAP(Amat,def->W,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr);
462409a357bSJakub Kruzik       } else {
463409a357bSJakub Kruzik         ierr = MatTransposeMatMult(def->W,def->AW,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr);
464409a357bSJakub Kruzik       }
465409a357bSJakub Kruzik       /* TODO create MatInheritOption(Mat,MatOption) */
466409a357bSJakub Kruzik       ierr = MatGetOption(Amat,MAT_SPD,&flgspd);CHKERRQ(ierr);
467409a357bSJakub Kruzik       ierr = MatSetOption(def->WtAW,MAT_SPD,flgspd);CHKERRQ(ierr);
468409a357bSJakub Kruzik #if defined(PETSC_USE_DEBUG)
469409a357bSJakub Kruzik       /* Check WtAW is not sigular */
470409a357bSJakub Kruzik       PetscReal *norms;
471409a357bSJakub Kruzik       ierr = PetscMalloc1(m,&norms);CHKERRQ(ierr);
472409a357bSJakub Kruzik       ierr = MatGetColumnNorms(def->WtAW,NORM_INFINITY,norms);CHKERRQ(ierr);
473409a357bSJakub Kruzik       for (i=0; i<m; i++) {
474409a357bSJakub Kruzik         if (norms[i] < 100*PETSC_MACHINE_EPSILON) {
475409a357bSJakub Kruzik           SETERRQ1(comm,PETSC_ERR_SUP,"Column %D of W is in kernel of A.",i);
476409a357bSJakub Kruzik         }
477409a357bSJakub Kruzik       }
478409a357bSJakub Kruzik       ierr = PetscFree(norms);CHKERRQ(ierr);
479409a357bSJakub Kruzik #endif
480409a357bSJakub Kruzik     } else {
481409a357bSJakub Kruzik       ierr = MatGetOption(def->WtAW,MAT_SPD,&flgspd);CHKERRQ(ierr);
482409a357bSJakub Kruzik     }
483409a357bSJakub Kruzik     /* TODO use MATINV */
484409a357bSJakub Kruzik     ierr = KSPCreate(comm,&def->WtAWinv);CHKERRQ(ierr);
485409a357bSJakub Kruzik     ierr = KSPSetOperators(def->WtAWinv,def->WtAW,def->WtAW);CHKERRQ(ierr);
486409a357bSJakub Kruzik     ierr = KSPGetPC(def->WtAWinv,&pcinner);CHKERRQ(ierr);
487557a2f7dSJakub Kruzik     /* Setup KSP and PC */
488557a2f7dSJakub Kruzik     if (nextDef) { /* next level for multilevel deflation */
489557a2f7dSJakub Kruzik       innerksp = def->WtAWinv;
490557a2f7dSJakub Kruzik       /* set default KSPtype */
491557a2f7dSJakub Kruzik       if (!def->ksptype) {
492557a2f7dSJakub Kruzik         def->ksptype = KSPFGMRES;
493557a2f7dSJakub Kruzik         if (flgspd) { /* SPD system */
494557a2f7dSJakub Kruzik           def->ksptype = KSPFCG;
495557a2f7dSJakub Kruzik         }
496557a2f7dSJakub Kruzik       }
497557a2f7dSJakub Kruzik       ierr = KSPSetType(innerksp,def->ksptype);CHKERRQ(ierr); /* TODO iherit from KSP */
498557a2f7dSJakub Kruzik       ierr = PCSetType(pcinner,PCDEFLATION);CHKERRQ(ierr); /* TODO create coarse preconditinoner M_c = WtMW ? */
499557a2f7dSJakub Kruzik       ierr = PCDeflationSetSpace(pcinner,nextDef,transp);CHKERRQ(ierr);
500557a2f7dSJakub Kruzik       ierr = PCDeflationSetLvl_Deflation(pcinner,def->nestedlvl+1,def->maxnestedlvl);CHKERRQ(ierr);
501557a2f7dSJakub Kruzik       /* inherit options TODO if not set */
502557a2f7dSJakub Kruzik       ((PC_Deflation*)(pcinner->data))->ksptype = def->ksptype;
503557a2f7dSJakub Kruzik       ((PC_Deflation*)(pcinner->data))->correct = def->correct;
504557a2f7dSJakub Kruzik       ((PC_Deflation*)(pcinner->data))->adaptiveconv = def->adaptiveconv;
505557a2f7dSJakub Kruzik       ((PC_Deflation*)(pcinner->data))->adaptiveconst = def->adaptiveconst;
506557a2f7dSJakub Kruzik       ierr = MatDestroy(&nextDef);CHKERRQ(ierr);
507557a2f7dSJakub Kruzik     } else { /* the last level */
508557a2f7dSJakub Kruzik       ierr = KSPSetType(def->WtAWinv,KSPPREONLY);CHKERRQ(ierr);
509409a357bSJakub Kruzik       ierr = PCSetType(pcinner,PCTELESCOPE);CHKERRQ(ierr);
510ac66f006SJakub Kruzik       /* ugly hack to not have overwritten PCTELESCOPE */
511ac66f006SJakub Kruzik       if (prefix) {
512ac66f006SJakub Kruzik         ierr = KSPSetOptionsPrefix(def->WtAWinv,prefix);CHKERRQ(ierr);
513ac66f006SJakub Kruzik       }
51422b0793eSJakub Kruzik       ierr = KSPAppendOptionsPrefix(def->WtAWinv,"tel_");CHKERRQ(ierr);
515ac66f006SJakub Kruzik       ierr = PCSetFromOptions(pcinner);CHKERRQ(ierr);
516409a357bSJakub Kruzik       /* Reduction factor choice */
517409a357bSJakub Kruzik       red = def->reductionfact;
518409a357bSJakub Kruzik       if (red < 0) {
519409a357bSJakub Kruzik         ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
520409a357bSJakub Kruzik         red  = ceil((float)commsize/ceil((float)m/commsize));
521409a357bSJakub Kruzik         ierr = PetscObjectTypeCompareAny((PetscObject)(def->WtAW),&match,MATSEQDENSE,MATMPIDENSE,MATDENSE,"");CHKERRQ(ierr);
522409a357bSJakub Kruzik         if (match) red = commsize;
523409a357bSJakub Kruzik         ierr = PetscInfo1(pc,"Auto choosing reduction factor %D\n",red);CHKERRQ(ierr); /* TODO add level? */
524409a357bSJakub Kruzik       }
525409a357bSJakub Kruzik       ierr = PCTelescopeSetReductionFactor(pcinner,red);CHKERRQ(ierr);
526ac66f006SJakub Kruzik       ierr = PCSetUp(pcinner);CHKERRQ(ierr);
527409a357bSJakub Kruzik       ierr = PCTelescopeGetKSP(pcinner,&innerksp);CHKERRQ(ierr);
528ac66f006SJakub Kruzik       if (innerksp) {
529409a357bSJakub Kruzik         ierr = KSPGetPC(innerksp,&pcinner);CHKERRQ(ierr);
530409a357bSJakub Kruzik         /* TODO Cholesky if flgspd? */
531ac66f006SJakub Kruzik         ierr = PCSetType(pcinner,PCLU);CHKERRQ(ierr);
532409a357bSJakub Kruzik         //TODO remove explicit matSolverPackage
533409a357bSJakub Kruzik         if (commsize == red) {
534ac66f006SJakub Kruzik           ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU);CHKERRQ(ierr);
535409a357bSJakub Kruzik         } else {
536ac66f006SJakub Kruzik           ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU_DIST);CHKERRQ(ierr);
537409a357bSJakub Kruzik         }
538409a357bSJakub Kruzik       }
539557a2f7dSJakub Kruzik     }
540557a2f7dSJakub Kruzik 
541557a2f7dSJakub Kruzik     if (innerksp) {
542409a357bSJakub Kruzik       /* TODO use def_[lvl]_ if lvl > 0? */
543409a357bSJakub Kruzik       if (prefix) {
544409a357bSJakub Kruzik         ierr = KSPSetOptionsPrefix(innerksp,prefix);CHKERRQ(ierr);
545409a357bSJakub Kruzik       }
54622b0793eSJakub Kruzik       ierr = KSPAppendOptionsPrefix(innerksp,"def_");CHKERRQ(ierr);
547557a2f7dSJakub Kruzik       ierr = KSPSetFromOptions(innerksp);CHKERRQ(ierr);
548557a2f7dSJakub Kruzik       ierr = KSPSetUp(innerksp);CHKERRQ(ierr);
549ac66f006SJakub Kruzik     }
550409a357bSJakub Kruzik     /* TODO: check if WtAWinv is KSP and move following from this if */
551409a357bSJakub Kruzik     //if (def->adaptiveconv) {
552409a357bSJakub Kruzik     //  PetscReal *rnorm;
553409a357bSJakub Kruzik     //  PetscNew(&rnorm);
554409a357bSJakub Kruzik     //  ierr = KSPSetConvergenceTest(def->WtAWinv,KSPDCGConvergedAdaptive_DCG,rnorm,NULL);CHKERRQ(ierr);
555409a357bSJakub Kruzik     //}
556409a357bSJakub Kruzik   }
557557a2f7dSJakub Kruzik   ierr = KSPSetFromOptions(def->WtAWinv);CHKERRQ(ierr);
558557a2f7dSJakub Kruzik   ierr = KSPSetUp(def->WtAWinv);CHKERRQ(ierr);
559409a357bSJakub Kruzik 
56022b0793eSJakub Kruzik   if (!def->pc) {
56122b0793eSJakub Kruzik     ierr = PCCreate(comm,&def->pc);CHKERRQ(ierr);
56222b0793eSJakub Kruzik     ierr = PCSetOperators(def->pc,Amat,Amat);CHKERRQ(ierr);
56322b0793eSJakub Kruzik     ierr = PCSetType(def->pc,PCNONE);CHKERRQ(ierr);
56422b0793eSJakub Kruzik     if (prefix) {
56522b0793eSJakub Kruzik       ierr = PCSetOptionsPrefix(def->pc,prefix);CHKERRQ(ierr);
56622b0793eSJakub Kruzik     }
56722b0793eSJakub Kruzik     ierr = PCAppendOptionsPrefix(def->pc,"def_pc_");CHKERRQ(ierr);
56822b0793eSJakub Kruzik     ierr = PCSetFromOptions(def->pc);CHKERRQ(ierr);
56922b0793eSJakub Kruzik     ierr = PCSetUp(def->pc);CHKERRQ(ierr);
57022b0793eSJakub Kruzik   }
57122b0793eSJakub Kruzik 
572f8bf229cSJakub Kruzik   /* create work vecs */
573f8bf229cSJakub Kruzik   ierr = MatCreateVecs(Amat,NULL,&def->work);CHKERRQ(ierr);
574f8bf229cSJakub Kruzik   ierr = KSPCreateVecs(def->WtAWinv,2,&def->workcoarse,0,NULL);CHKERRQ(ierr);
57537eeb815SJakub Kruzik   PetscFunctionReturn(0);
57637eeb815SJakub Kruzik }
577b30d4775SJakub Kruzik 
57837eeb815SJakub Kruzik static PetscErrorCode PCReset_Deflation(PC pc)
57937eeb815SJakub Kruzik {
580b30d4775SJakub Kruzik   PC_Deflation      *def = (PC_Deflation*)pc->data;
58137eeb815SJakub Kruzik   PetscErrorCode    ierr;
58237eeb815SJakub Kruzik 
58337eeb815SJakub Kruzik   PetscFunctionBegin;
584b30d4775SJakub Kruzik   ierr = VecDestroy(&def->work);CHKERRQ(ierr);
585b30d4775SJakub Kruzik   ierr = VecDestroyVecs(2,&def->workcoarse);CHKERRQ(ierr);
586b30d4775SJakub Kruzik   ierr = MatDestroy(&def->W);CHKERRQ(ierr);
587b30d4775SJakub Kruzik   ierr = MatDestroy(&def->Wt);CHKERRQ(ierr);
588b30d4775SJakub Kruzik   ierr = MatDestroy(&def->AW);CHKERRQ(ierr);
589b30d4775SJakub Kruzik   ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr);
590b30d4775SJakub Kruzik   ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr);
59122b0793eSJakub Kruzik   ierr = PCDestroy(&def->pc);CHKERRQ(ierr);
59237eeb815SJakub Kruzik   PetscFunctionReturn(0);
59337eeb815SJakub Kruzik }
59437eeb815SJakub Kruzik 
59537eeb815SJakub Kruzik /*
59637eeb815SJakub Kruzik    PCDestroy_Deflation - Destroys the private context for the Deflation preconditioner
59737eeb815SJakub Kruzik    that was created with PCCreate_Deflation().
59837eeb815SJakub Kruzik 
59937eeb815SJakub Kruzik    Input Parameter:
60037eeb815SJakub Kruzik .  pc - the preconditioner context
60137eeb815SJakub Kruzik 
60237eeb815SJakub Kruzik    Application Interface Routine: PCDestroy()
60337eeb815SJakub Kruzik */
60437eeb815SJakub Kruzik static PetscErrorCode PCDestroy_Deflation(PC pc)
60537eeb815SJakub Kruzik {
60637eeb815SJakub Kruzik   PetscErrorCode ierr;
60737eeb815SJakub Kruzik 
60837eeb815SJakub Kruzik   PetscFunctionBegin;
60937eeb815SJakub Kruzik   ierr = PCReset_Deflation(pc);CHKERRQ(ierr);
61037eeb815SJakub Kruzik   ierr = PetscFree(pc->data);CHKERRQ(ierr);
61137eeb815SJakub Kruzik   PetscFunctionReturn(0);
61237eeb815SJakub Kruzik }
61337eeb815SJakub Kruzik 
6148513960bSJakub Kruzik static PetscErrorCode PCView_Deflation(PC pc,PetscViewer viewer)
6158513960bSJakub Kruzik {
6168513960bSJakub Kruzik   PC_Deflation      *def = (PC_Deflation*)pc->data;
6178513960bSJakub Kruzik   PetscBool         iascii;
6188513960bSJakub Kruzik   PetscErrorCode    ierr;
6198513960bSJakub Kruzik 
6208513960bSJakub Kruzik   PetscFunctionBegin;
6218513960bSJakub Kruzik   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
6228513960bSJakub Kruzik   if (iascii) {
6238513960bSJakub Kruzik     //if (cg->adaptiveconv) {
6248513960bSJakub Kruzik     //  ierr = PetscViewerASCIIPrintf(viewer,"  DCG: using adaptive precision for inner solve with C=%.1e\n",cg->adaptiveconst);CHKERRQ(ierr);
6258513960bSJakub Kruzik     //}
6268513960bSJakub Kruzik     if (def->correct) {
6278513960bSJakub Kruzik       ierr = PetscViewerASCIIPrintf(viewer,"  Using CP correction\n");CHKERRQ(ierr);
6288513960bSJakub Kruzik     }
6298513960bSJakub Kruzik     if (!def->nestedlvl) {
6308513960bSJakub Kruzik       ierr = PetscViewerASCIIPrintf(viewer,"  Deflation space type: %s\n",PCDeflationSpaceTypes[def->spacetype]);CHKERRQ(ierr);
6318513960bSJakub Kruzik       ierr = PetscViewerASCIIPrintf(viewer,"  DCG %s\n",def->extendsp ? "extended" : "truncated");CHKERRQ(ierr);
6328513960bSJakub Kruzik     }
6338513960bSJakub Kruzik 
63422b0793eSJakub Kruzik     ierr = PetscViewerASCIIPrintf(viewer,"--- Additional PC\n");CHKERRQ(ierr);
63522b0793eSJakub Kruzik     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
63622b0793eSJakub Kruzik     ierr = PCView(def->pc,viewer);CHKERRQ(ierr);
63722b0793eSJakub Kruzik     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
63822b0793eSJakub Kruzik 
6398513960bSJakub Kruzik     ierr = PetscViewerASCIIPrintf(viewer,"--- Coarse solver\n");CHKERRQ(ierr);
6408513960bSJakub Kruzik     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
6418513960bSJakub Kruzik     ierr = KSPView(def->WtAWinv,viewer);CHKERRQ(ierr);
6428513960bSJakub Kruzik     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
6438513960bSJakub Kruzik   }
6448513960bSJakub Kruzik   PetscFunctionReturn(0);
6458513960bSJakub Kruzik }
6468513960bSJakub Kruzik 
64737eeb815SJakub Kruzik static PetscErrorCode PCSetFromOptions_Deflation(PetscOptionItems *PetscOptionsObject,PC pc)
64837eeb815SJakub Kruzik {
649880d05ceSJakub Kruzik   PC_Deflation      *def = (PC_Deflation*)pc->data;
65037eeb815SJakub Kruzik   PetscErrorCode    ierr;
65137eeb815SJakub Kruzik   PetscBool         flg;
65237eeb815SJakub Kruzik   PCDeflationType   deflt,type;
65337eeb815SJakub Kruzik 
65437eeb815SJakub Kruzik   PetscFunctionBegin;
65537eeb815SJakub Kruzik   ierr = PCDeflationGetType(pc,&deflt);CHKERRQ(ierr);
65637eeb815SJakub Kruzik   ierr = PetscOptionsHead(PetscOptionsObject,"Deflation options");CHKERRQ(ierr);
657880d05ceSJakub Kruzik   ierr = PetscOptionsEnum("-pc_deflation_type","Determine type of deflation","PCDeflationSetType",PCDeflationTypes,(PetscEnum)deflt,(PetscEnum*)&type,&flg);CHKERRQ(ierr);
65837eeb815SJakub Kruzik   if (flg) {
65937eeb815SJakub Kruzik     ierr = PCDeflationSetType(pc,type);CHKERRQ(ierr);
66037eeb815SJakub Kruzik   }
661880d05ceSJakub Kruzik   ierr = PetscOptionsEnum("-pc_deflation_compute_space","Compute deflation space","PCDeflationSetSpace",PCDeflationSpaceTypes,(PetscEnum)def->spacetype,(PetscEnum*)&def->spacetype,NULL);CHKERRQ(ierr);
662880d05ceSJakub Kruzik   ierr = PetscOptionsInt("-pc_deflation_compute_space_size","Set size of the deflation space to compute","PCDeflationSetSpace",def->spacesize,&def->spacesize,NULL);CHKERRQ(ierr);
663880d05ceSJakub Kruzik   ierr = PetscOptionsBool("-pc_deflation_space_extend","Extend deflation space instead of truncating (wavelets)","PCDeflation",def->extendsp,&def->extendsp,NULL);CHKERRQ(ierr);
664880d05ceSJakub Kruzik //TODO add set function and fix manpages
665880d05ceSJakub Kruzik   ierr = PetscOptionsBool("-pc_deflation_initdef","Use only initialization step - Initdef","PCDeflation",def->init,&def->init,NULL);CHKERRQ(ierr);
666880d05ceSJakub Kruzik   ierr = PetscOptionsBool("-pc_deflation_correct","Add Qr to descent direction","PCDeflation",def->correct,&def->correct,NULL);CHKERRQ(ierr);
667880d05ceSJakub Kruzik   ierr = PetscOptionsBool("-pc_deflation_adaptive","Adaptive stopping criteria","PCDeflation",def->adaptiveconv,&def->adaptiveconv,NULL);CHKERRQ(ierr);
668880d05ceSJakub Kruzik   ierr = PetscOptionsReal("-pc_deflation_adaptive_const","Adaptive stopping criteria constant","PCDeflation",def->adaptiveconst,&def->adaptiveconst,NULL);CHKERRQ(ierr);
669880d05ceSJakub Kruzik   ierr = PetscOptionsInt("-pc_deflation_redfact","Reduction factor for coarse problem solution","PCDeflation",def->reductionfact,&def->reductionfact,NULL);CHKERRQ(ierr);
670880d05ceSJakub Kruzik   ierr = PetscOptionsInt("-pc_deflation_max_nested_lvl","Maximum of nested deflation levels","PCDeflation",def->maxnestedlvl,&def->maxnestedlvl,NULL);CHKERRQ(ierr);
67137eeb815SJakub Kruzik   ierr = PetscOptionsTail();CHKERRQ(ierr);
67237eeb815SJakub Kruzik   PetscFunctionReturn(0);
67337eeb815SJakub Kruzik }
67437eeb815SJakub Kruzik 
67537eeb815SJakub Kruzik /*MC
676e361f8b5SJakub Kruzik      PCDEFLATION - Deflation preconditioner shifts part of the spectrum to zero (deflates)
677e361f8b5SJakub Kruzik      or to a predefined value
67837eeb815SJakub Kruzik 
67937eeb815SJakub Kruzik    Options Database Key:
680e361f8b5SJakub Kruzik +    -pc_deflation_type <init,pre,post> - selects approach to deflation (default: pre)
68137eeb815SJakub Kruzik -    -pc_jacobi_abs - use the absolute value of the diagonal entry
68237eeb815SJakub Kruzik 
68337eeb815SJakub Kruzik    Level: beginner
68437eeb815SJakub Kruzik 
68537eeb815SJakub Kruzik   Notes:
686e361f8b5SJakub Kruzik     todo
68737eeb815SJakub Kruzik 
68837eeb815SJakub Kruzik .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
689e662bc50SJakub Kruzik            PCDeflationSetType(), PCDeflationSetSpace()
69037eeb815SJakub Kruzik M*/
69137eeb815SJakub Kruzik 
69237eeb815SJakub Kruzik PETSC_EXTERN PetscErrorCode PCCreate_Deflation(PC pc)
69337eeb815SJakub Kruzik {
69437eeb815SJakub Kruzik   PC_Deflation   *def;
69537eeb815SJakub Kruzik   PetscErrorCode ierr;
69637eeb815SJakub Kruzik 
69737eeb815SJakub Kruzik   PetscFunctionBegin;
69837eeb815SJakub Kruzik   ierr     = PetscNewLog(pc,&def);CHKERRQ(ierr);
69937eeb815SJakub Kruzik   pc->data = (void*)def;
70037eeb815SJakub Kruzik 
701e662bc50SJakub Kruzik   def->init          = PETSC_FALSE;
702e662bc50SJakub Kruzik   def->pre           = PETSC_TRUE;
703e662bc50SJakub Kruzik   def->correct       = PETSC_FALSE;
704e662bc50SJakub Kruzik   def->truenorm      = PETSC_TRUE;
705e662bc50SJakub Kruzik   def->reductionfact = -1;
706e662bc50SJakub Kruzik   def->spacetype     = PC_DEFLATION_SPACE_HAAR;
707e662bc50SJakub Kruzik   def->spacesize     = 1;
708e662bc50SJakub Kruzik   def->extendsp      = PETSC_FALSE;
709e662bc50SJakub Kruzik   def->nestedlvl     = 0;
710e662bc50SJakub Kruzik   def->maxnestedlvl  = 0;
711e662bc50SJakub Kruzik   def->adaptiveconv  = PETSC_FALSE;
712e662bc50SJakub Kruzik   def->adaptiveconst = 1.0;
71337eeb815SJakub Kruzik 
71437eeb815SJakub Kruzik   /*
71537eeb815SJakub Kruzik       Set the pointers for the functions that are provided above.
71637eeb815SJakub Kruzik       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
71737eeb815SJakub Kruzik       are called, they will automatically call these functions.  Note we
71837eeb815SJakub Kruzik       choose not to provide a couple of these functions since they are
71937eeb815SJakub Kruzik       not needed.
72037eeb815SJakub Kruzik   */
72137eeb815SJakub Kruzik   pc->ops->apply               = PCApply_Deflation;
72237eeb815SJakub Kruzik   pc->ops->applytranspose      = PCApply_Deflation;
723b27c8092SJakub Kruzik   pc->ops->presolve            = PCPreSolve_Deflation;
724b27c8092SJakub Kruzik   pc->ops->postsolve           = 0;
72537eeb815SJakub Kruzik   pc->ops->setup               = PCSetUp_Deflation;
72637eeb815SJakub Kruzik   pc->ops->reset               = PCReset_Deflation;
72737eeb815SJakub Kruzik   pc->ops->destroy             = PCDestroy_Deflation;
72837eeb815SJakub Kruzik   pc->ops->setfromoptions      = PCSetFromOptions_Deflation;
7298513960bSJakub Kruzik   pc->ops->view                = PCView_Deflation;
73037eeb815SJakub Kruzik   pc->ops->applyrichardson     = 0;
73137eeb815SJakub Kruzik   pc->ops->applysymmetricleft  = 0;
73237eeb815SJakub Kruzik   pc->ops->applysymmetricright = 0;
73337eeb815SJakub Kruzik 
73437eeb815SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetType_C",PCDeflationSetType_Deflation);CHKERRQ(ierr);
73537eeb815SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetType_C",PCDeflationGetType_Deflation);CHKERRQ(ierr);
736e662bc50SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpace_C",PCDeflationSetSpace_Deflation);CHKERRQ(ierr);
7375c0c31c5SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetLvl_C",PCDeflationSetLvl_Deflation);CHKERRQ(ierr);
73822b0793eSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetPC_C",PCDeflationSetPC_Deflation);CHKERRQ(ierr);
73937eeb815SJakub Kruzik   PetscFunctionReturn(0);
74037eeb815SJakub Kruzik }
74137eeb815SJakub Kruzik 
742