xref: /petsc/src/ksp/pc/impls/deflation/deflation.c (revision 859a873c22d867fd3d79478291d54c35b3208089)
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 
538513960bSJakub Kruzik const char *const PCDeflationSpaceTypes[] = {
548513960bSJakub Kruzik   "haar",
558513960bSJakub Kruzik   "jacket-haar",
568513960bSJakub Kruzik   "db2",
578513960bSJakub Kruzik   "db4",
588513960bSJakub Kruzik   "db8",
598513960bSJakub Kruzik   "db16",
608513960bSJakub Kruzik   "biorth22",
618513960bSJakub Kruzik   "meyer",
628513960bSJakub Kruzik   "aggregation",
638513960bSJakub Kruzik   "slepc",
648513960bSJakub Kruzik   "slepc-cheap",
658513960bSJakub Kruzik   "user",
668513960bSJakub Kruzik   "DdefSpaceType",
678513960bSJakub Kruzik   "Ddef_SPACE_",
688513960bSJakub Kruzik   0
698513960bSJakub Kruzik };
708513960bSJakub Kruzik 
7198d6e3deSJakub Kruzik static PetscErrorCode PCDeflationSetLvl_Deflation(PC pc,PetscInt current,PetscInt max)
7298d6e3deSJakub Kruzik {
7398d6e3deSJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
7498d6e3deSJakub Kruzik 
7598d6e3deSJakub Kruzik   PetscFunctionBegin;
7698d6e3deSJakub Kruzik   if (current) def->nestedlvl = current;
7798d6e3deSJakub Kruzik   def->maxnestedlvl = max;
7898d6e3deSJakub Kruzik   PetscFunctionReturn(0);
7998d6e3deSJakub Kruzik }
8098d6e3deSJakub Kruzik 
8198d6e3deSJakub Kruzik /*@
8298d6e3deSJakub Kruzik    PCDeflationSetMaxLvl - Set maximum level of deflation.
8398d6e3deSJakub Kruzik 
8498d6e3deSJakub Kruzik    Logically Collective on PC
8598d6e3deSJakub Kruzik 
8698d6e3deSJakub Kruzik    Input Parameters:
8798d6e3deSJakub Kruzik +  pc  - the preconditioner context
8898d6e3deSJakub Kruzik -  max - maximum deflation level
8998d6e3deSJakub Kruzik 
9098d6e3deSJakub Kruzik    Level: intermediate
9198d6e3deSJakub Kruzik 
9298d6e3deSJakub Kruzik .seealso: PCDEFLATION
9398d6e3deSJakub Kruzik @*/
9498d6e3deSJakub Kruzik PetscErrorCode PCDeflationSetMaxLvl(PC pc,PetscInt max)
9598d6e3deSJakub Kruzik {
9698d6e3deSJakub Kruzik   PetscErrorCode ierr;
9798d6e3deSJakub Kruzik 
9898d6e3deSJakub Kruzik   PetscFunctionBegin;
9998d6e3deSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
10098d6e3deSJakub Kruzik   PetscValidLogicalCollectiveInt(pc,max,2);
10198d6e3deSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetLvl_C",(PC,PetscInt,PetscInt),(pc,0,max));CHKERRQ(ierr);
10298d6e3deSJakub Kruzik   PetscFunctionReturn(0);
10398d6e3deSJakub Kruzik }
10498d6e3deSJakub Kruzik 
105*859a873cSJakub Kruzik static PetscErrorCode PCDeflationSetReductionFactor_Deflation(PC pc,PetscInt red)
106*859a873cSJakub Kruzik {
107*859a873cSJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
108*859a873cSJakub Kruzik 
109*859a873cSJakub Kruzik   PetscFunctionBegin;
110*859a873cSJakub Kruzik   def->reductionfact = red;
111*859a873cSJakub Kruzik   PetscFunctionReturn(0);
112*859a873cSJakub Kruzik }
113*859a873cSJakub Kruzik 
114*859a873cSJakub Kruzik /*@
115*859a873cSJakub Kruzik    PCDeflationSetReductionFactor - Set reduction factor for PCTELESCOPE coarse problem solver.
116*859a873cSJakub Kruzik 
117*859a873cSJakub Kruzik    Logically Collective on PC
118*859a873cSJakub Kruzik 
119*859a873cSJakub Kruzik    Input Parameters:
120*859a873cSJakub Kruzik +  pc  - the preconditioner context
121*859a873cSJakub Kruzik -  red - reduction factor (or PETSC_DETERMINE)
122*859a873cSJakub Kruzik 
123*859a873cSJakub Kruzik    Level: intermediate
124*859a873cSJakub Kruzik 
125*859a873cSJakub Kruzik .seealso: PCDEFLATION
126*859a873cSJakub Kruzik @*/
127*859a873cSJakub Kruzik PetscErrorCode PCDeflationSetReductionFactor(PC pc,PetscInt red)
128*859a873cSJakub Kruzik {
129*859a873cSJakub Kruzik   PetscErrorCode ierr;
130*859a873cSJakub Kruzik 
131*859a873cSJakub Kruzik   PetscFunctionBegin;
132*859a873cSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
133*859a873cSJakub Kruzik   PetscValidLogicalCollectiveInt(pc,red,2);
134*859a873cSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetReductionFactor_C",(PC,PetscInt),(pc,red));CHKERRQ(ierr);
135*859a873cSJakub Kruzik   PetscFunctionReturn(0);
136*859a873cSJakub Kruzik }
137*859a873cSJakub Kruzik 
13839417d7eSJakub Kruzik static PetscErrorCode PCDeflationSetSpaceToCompute_Deflation(PC pc,PCDeflationSpaceType type,PetscInt size)
13939417d7eSJakub Kruzik {
14039417d7eSJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
14139417d7eSJakub Kruzik 
14239417d7eSJakub Kruzik   PetscFunctionBegin;
14339417d7eSJakub Kruzik   if (type) def->spacetype = type;
14439417d7eSJakub Kruzik   if (size > 0) def->spacesize = size;
14539417d7eSJakub Kruzik   PetscFunctionReturn(0);
14639417d7eSJakub Kruzik }
14739417d7eSJakub Kruzik 
14839417d7eSJakub Kruzik /*@
14939417d7eSJakub Kruzik    PCDeflationSetSpaceToCompute - Set deflation space type and size to compute.
15039417d7eSJakub Kruzik 
15139417d7eSJakub Kruzik    Logically Collective on PC
15239417d7eSJakub Kruzik 
15339417d7eSJakub Kruzik    Input Parameters:
15439417d7eSJakub Kruzik +  pc   - the preconditioner context
15539417d7eSJakub Kruzik .  type - deflation space type to compute (or PETSC_IGNORE)
15639417d7eSJakub Kruzik -  size - size of the space to compute (or PETSC_DEFAULT)
15739417d7eSJakub Kruzik 
15839417d7eSJakub Kruzik    Notes:
15939417d7eSJakub Kruzik     For wavelet-based deflation, size represents number of levels.
16039417d7eSJakub Kruzik     The deflation space is computed in PCSetUP().
16139417d7eSJakub Kruzik 
16239417d7eSJakub Kruzik    Level: intermediate
16339417d7eSJakub Kruzik 
16439417d7eSJakub Kruzik .seealso: PCDEFLATION
16539417d7eSJakub Kruzik @*/
16639417d7eSJakub Kruzik PetscErrorCode PCDeflationSetSpaceToCompute(PC pc,PCDeflationSpaceType type,PetscInt size)
16739417d7eSJakub Kruzik {
16839417d7eSJakub Kruzik   PetscErrorCode ierr;
16939417d7eSJakub Kruzik 
17039417d7eSJakub Kruzik   PetscFunctionBegin;
17139417d7eSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
17239417d7eSJakub Kruzik   if (type) PetscValidLogicalCollectiveEnum(pc,type,2);
17339417d7eSJakub Kruzik   if (size > 0) PetscValidLogicalCollectiveInt(pc,size,3);
17439417d7eSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetSpaceToCompute_C",(PC,PCDeflationSpaceType,PetscInt),(pc,type,size));CHKERRQ(ierr);
17539417d7eSJakub Kruzik   PetscFunctionReturn(0);
17639417d7eSJakub Kruzik }
1778513960bSJakub Kruzik 
178e662bc50SJakub Kruzik static PetscErrorCode PCDeflationSetSpace_Deflation(PC pc,Mat W,PetscBool transpose)
179e662bc50SJakub Kruzik {
180e662bc50SJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
181e662bc50SJakub Kruzik   PetscErrorCode ierr;
182e662bc50SJakub Kruzik 
183e662bc50SJakub Kruzik   PetscFunctionBegin;
184e662bc50SJakub Kruzik   if (transpose) {
185e662bc50SJakub Kruzik     def->Wt = W;
186e662bc50SJakub Kruzik     def->W = NULL;
187e662bc50SJakub Kruzik   } else {
188e662bc50SJakub Kruzik     def->W = W;
189e662bc50SJakub Kruzik   }
190e662bc50SJakub Kruzik   ierr = PetscObjectReference((PetscObject)W);CHKERRQ(ierr);
191e662bc50SJakub Kruzik   PetscFunctionReturn(0);
192e662bc50SJakub Kruzik }
193e662bc50SJakub Kruzik 
194e662bc50SJakub Kruzik /* TODO create PCDeflationSetSpaceTranspose? */
195e662bc50SJakub Kruzik /*@
196e662bc50SJakub Kruzik    PCDeflationSetSpace - Set deflation space matrix (or its transpose).
197e662bc50SJakub Kruzik 
198e662bc50SJakub Kruzik    Logically Collective on PC
199e662bc50SJakub Kruzik 
200e662bc50SJakub Kruzik    Input Parameters:
201e662bc50SJakub Kruzik +  pc - the preconditioner context
202e662bc50SJakub Kruzik .  W  - deflation matrix
203e662bc50SJakub Kruzik -  tranpose - indicates that W is an explicit transpose of the deflation matrix
204e662bc50SJakub Kruzik 
205e662bc50SJakub Kruzik    Level: intermediate
206e662bc50SJakub Kruzik 
207e662bc50SJakub Kruzik .seealso: PCDEFLATION
208e662bc50SJakub Kruzik @*/
209e662bc50SJakub Kruzik PetscErrorCode PCDeflationSetSpace(PC pc,Mat W,PetscBool transpose)
210e662bc50SJakub Kruzik {
211e662bc50SJakub Kruzik   PetscErrorCode ierr;
212e662bc50SJakub Kruzik 
213e662bc50SJakub Kruzik   PetscFunctionBegin;
214e662bc50SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
215e662bc50SJakub Kruzik   PetscValidHeaderSpecific(W,MAT_CLASSID,2);
216e662bc50SJakub Kruzik   PetscValidLogicalCollectiveBool(pc,transpose,3);
217e662bc50SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetSpace_C",(PC,Mat,PetscBool),(pc,W,transpose));CHKERRQ(ierr);
218e662bc50SJakub Kruzik   PetscFunctionReturn(0);
219e662bc50SJakub Kruzik }
220e662bc50SJakub Kruzik 
2213cf3a049SJakub Kruzik static PetscErrorCode PCDeflationSetProjectionNullSpaceMat_Deflation(PC pc,Mat mat)
2223cf3a049SJakub Kruzik {
2233cf3a049SJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
2243cf3a049SJakub Kruzik   PetscErrorCode   ierr;
2253cf3a049SJakub Kruzik 
2263cf3a049SJakub Kruzik   PetscFunctionBegin;
2273cf3a049SJakub Kruzik   ierr = MatDestroy(&def->WtA);CHKERRQ(ierr);
2283cf3a049SJakub Kruzik   def->WtA = mat;
2293cf3a049SJakub Kruzik   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
2303cf3a049SJakub Kruzik   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtA);CHKERRQ(ierr);
2313cf3a049SJakub Kruzik   PetscFunctionReturn(0);
2323cf3a049SJakub Kruzik }
2333cf3a049SJakub Kruzik 
2343cf3a049SJakub Kruzik /*@
2353cf3a049SJakub Kruzik    PCDeflationSetProjectionNullSpaceMat - Set projection null space matrix (W'*A).
2363cf3a049SJakub Kruzik 
2373cf3a049SJakub Kruzik    Not Collective
2383cf3a049SJakub Kruzik 
2393cf3a049SJakub Kruzik    Input Parameters:
2403cf3a049SJakub Kruzik +  pc  - preconditioner context
2413cf3a049SJakub Kruzik -  mat - projection null space matrix
2423cf3a049SJakub Kruzik 
2433cf3a049SJakub Kruzik    Level: developer
2443cf3a049SJakub Kruzik 
2453cf3a049SJakub Kruzik .seealso: PCDEFLATION
2463cf3a049SJakub Kruzik @*/
2473cf3a049SJakub Kruzik PetscErrorCode  PCDeflationSetProjectionNullSpaceMat(PC pc,Mat mat)
2483cf3a049SJakub Kruzik {
2493cf3a049SJakub Kruzik   PetscErrorCode ierr;
2503cf3a049SJakub Kruzik 
2513cf3a049SJakub Kruzik   PetscFunctionBegin;
2523cf3a049SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2533cf3a049SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
2543cf3a049SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetProjectionNullSpaceMat_C",(PC,Mat),(pc,mat));CHKERRQ(ierr);
2553cf3a049SJakub Kruzik   PetscFunctionReturn(0);
2563cf3a049SJakub Kruzik }
2573cf3a049SJakub Kruzik 
258e924b002SJakub Kruzik static PetscErrorCode PCDeflationSetCoarseMat_Deflation(PC pc,Mat mat)
259e924b002SJakub Kruzik {
260e924b002SJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
261e924b002SJakub Kruzik   PetscErrorCode   ierr;
262e924b002SJakub Kruzik 
263e924b002SJakub Kruzik   PetscFunctionBegin;
264e924b002SJakub Kruzik   ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr);
265e924b002SJakub Kruzik   def->WtAW = mat;
266e924b002SJakub Kruzik   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
267e924b002SJakub Kruzik   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtAW);CHKERRQ(ierr);
268e924b002SJakub Kruzik   PetscFunctionReturn(0);
269e924b002SJakub Kruzik }
270e924b002SJakub Kruzik 
271e924b002SJakub Kruzik /*@
272e924b002SJakub Kruzik    PCDeflationSetCoarseMat - Set coarse problem Mat.
273e924b002SJakub Kruzik 
274e924b002SJakub Kruzik    Not Collective
275e924b002SJakub Kruzik 
276e924b002SJakub Kruzik    Input Parameters:
277e924b002SJakub Kruzik +  pc - preconditioner context
278e924b002SJakub Kruzik -  mat - coarse problem mat
279e924b002SJakub Kruzik 
280e924b002SJakub Kruzik    Level: developer
281e924b002SJakub Kruzik 
282e924b002SJakub Kruzik .seealso: PCDEFLATION
283e924b002SJakub Kruzik @*/
284e924b002SJakub Kruzik PetscErrorCode  PCDeflationSetCoarseMat(PC pc,Mat mat)
285e924b002SJakub Kruzik {
286e924b002SJakub Kruzik   PetscErrorCode ierr;
287e924b002SJakub Kruzik 
288e924b002SJakub Kruzik   PetscFunctionBegin;
289e924b002SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
290e924b002SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
291e924b002SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetCoarseMat_C",(PC,Mat),(pc,mat));CHKERRQ(ierr);
292e924b002SJakub Kruzik   PetscFunctionReturn(0);
293e924b002SJakub Kruzik }
294e924b002SJakub Kruzik 
29598d6e3deSJakub Kruzik static PetscErrorCode PCDeflationGetCoarseKSP_Deflation(PC pc,KSP *ksp)
2965c0c31c5SJakub Kruzik {
2975c0c31c5SJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
2985c0c31c5SJakub Kruzik 
2995c0c31c5SJakub Kruzik   PetscFunctionBegin;
30098d6e3deSJakub Kruzik   *ksp = def->WtAWinv;
3015c0c31c5SJakub Kruzik   PetscFunctionReturn(0);
3025c0c31c5SJakub Kruzik }
3035c0c31c5SJakub Kruzik 
3045c0c31c5SJakub Kruzik /*@
30598d6e3deSJakub Kruzik    PCDeflationGetCoarseKSP - Returns a pointer to the coarse problem KSP.
3065c0c31c5SJakub Kruzik 
30798d6e3deSJakub Kruzik    Not Collective
3085c0c31c5SJakub Kruzik 
3095c0c31c5SJakub Kruzik    Input Parameters:
31098d6e3deSJakub Kruzik .  pc - preconditioner context
3115c0c31c5SJakub Kruzik 
31298d6e3deSJakub Kruzik    Output Parameter:
31398d6e3deSJakub Kruzik .  ksp - coarse problem KSP context
3145c0c31c5SJakub Kruzik 
31598d6e3deSJakub Kruzik    Level: developer
31698d6e3deSJakub Kruzik 
31798d6e3deSJakub Kruzik .seealso: PCDeflationSetCoarseKSP(), PCDEFLATION
3185c0c31c5SJakub Kruzik @*/
31998d6e3deSJakub Kruzik PetscErrorCode  PCDeflationGetCoarseKSP(PC pc,KSP *ksp)
3205c0c31c5SJakub Kruzik {
3215c0c31c5SJakub Kruzik   PetscErrorCode ierr;
3225c0c31c5SJakub Kruzik 
3235c0c31c5SJakub Kruzik   PetscFunctionBegin;
32422b0793eSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
32598d6e3deSJakub Kruzik   PetscValidPointer(ksp,2);
32698d6e3deSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationGetCoarseKSP_C",(PC,KSP*),(pc,ksp));CHKERRQ(ierr);
32798d6e3deSJakub Kruzik   PetscFunctionReturn(0);
32898d6e3deSJakub Kruzik }
32998d6e3deSJakub Kruzik 
33098d6e3deSJakub Kruzik static PetscErrorCode PCDeflationSetCoarseKSP_Deflation(PC pc,KSP ksp)
33198d6e3deSJakub Kruzik {
33298d6e3deSJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
33398d6e3deSJakub Kruzik   PetscErrorCode   ierr;
33498d6e3deSJakub Kruzik 
33598d6e3deSJakub Kruzik   PetscFunctionBegin;
33698d6e3deSJakub Kruzik   ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr);
33798d6e3deSJakub Kruzik   def->WtAWinv = ksp;
33898d6e3deSJakub Kruzik   ierr = PetscObjectReference((PetscObject)ksp);CHKERRQ(ierr);
33998d6e3deSJakub Kruzik   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtAWinv);CHKERRQ(ierr);
34098d6e3deSJakub Kruzik   PetscFunctionReturn(0);
34198d6e3deSJakub Kruzik }
34298d6e3deSJakub Kruzik 
34398d6e3deSJakub Kruzik /*@
34498d6e3deSJakub Kruzik    PCDeflationSetCoarseKSP - Set coarse problem KSP.
34598d6e3deSJakub Kruzik 
34698d6e3deSJakub Kruzik    Collective on PC
34798d6e3deSJakub Kruzik 
34898d6e3deSJakub Kruzik    Input Parameters:
34998d6e3deSJakub Kruzik +  pc - preconditioner context
35098d6e3deSJakub Kruzik -  ksp - coarse problem KSP context
35198d6e3deSJakub Kruzik 
35298d6e3deSJakub Kruzik    Level: developer
35398d6e3deSJakub Kruzik 
35498d6e3deSJakub Kruzik .seealso: PCDeflationGetCoarseKSP(), PCDEFLATION
35598d6e3deSJakub Kruzik @*/
35698d6e3deSJakub Kruzik PetscErrorCode  PCDeflationSetCoarseKSP(PC pc,KSP ksp)
35798d6e3deSJakub Kruzik {
35898d6e3deSJakub Kruzik   PetscErrorCode ierr;
35998d6e3deSJakub Kruzik 
36098d6e3deSJakub Kruzik   PetscFunctionBegin;
36198d6e3deSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
36298d6e3deSJakub Kruzik   PetscValidHeaderSpecific(ksp,KSP_CLASSID,2);
36398d6e3deSJakub Kruzik   PetscCheckSameComm(pc,1,ksp,2);
36498d6e3deSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetCoarseKSP_C",(PC,KSP),(pc,ksp));CHKERRQ(ierr);
3655c0c31c5SJakub Kruzik   PetscFunctionReturn(0);
3665c0c31c5SJakub Kruzik }
367e662bc50SJakub Kruzik 
368268c6673SJakub Kruzik static PetscErrorCode PCDeflationGetPC_Deflation(PC pc,PC *apc)
369268c6673SJakub Kruzik {
370268c6673SJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
371268c6673SJakub Kruzik 
372268c6673SJakub Kruzik   PetscFunctionBegin;
373268c6673SJakub Kruzik   *apc = def->pc;
374268c6673SJakub Kruzik   PetscFunctionReturn(0);
375268c6673SJakub Kruzik }
376268c6673SJakub Kruzik 
377268c6673SJakub Kruzik /*@
378268c6673SJakub Kruzik    PCDeflationGetPC - Returns a pointer to additional preconditioner.
379268c6673SJakub Kruzik 
380268c6673SJakub Kruzik    Not Collective
381268c6673SJakub Kruzik 
382268c6673SJakub Kruzik    Input Parameters:
383268c6673SJakub Kruzik .  pc  - the preconditioner context
384268c6673SJakub Kruzik 
385268c6673SJakub Kruzik    Output Parameter:
386268c6673SJakub Kruzik .  apc - additional preconditioner
387268c6673SJakub Kruzik 
388268c6673SJakub Kruzik    Level: advanced
389268c6673SJakub Kruzik 
390268c6673SJakub Kruzik .seealso: PCDeflationSetPC(), PCDEFLATION
391268c6673SJakub Kruzik @*/
392268c6673SJakub Kruzik PetscErrorCode PCDeflationGetPC(PC pc,PC *apc)
393268c6673SJakub Kruzik {
394268c6673SJakub Kruzik   PetscErrorCode ierr;
395268c6673SJakub Kruzik 
396268c6673SJakub Kruzik   PetscFunctionBegin;
397268c6673SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
398268c6673SJakub Kruzik   PetscValidPointer(pc,2);
399268c6673SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationGetPC_C",(PC,PC*),(pc,apc));CHKERRQ(ierr);
400268c6673SJakub Kruzik   PetscFunctionReturn(0);
401268c6673SJakub Kruzik }
402268c6673SJakub Kruzik 
40322b0793eSJakub Kruzik static PetscErrorCode PCDeflationSetPC_Deflation(PC pc,PC apc)
40422b0793eSJakub Kruzik {
40522b0793eSJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
40622b0793eSJakub Kruzik   PetscErrorCode ierr;
40722b0793eSJakub Kruzik 
40822b0793eSJakub Kruzik   PetscFunctionBegin;
40922b0793eSJakub Kruzik   ierr = PCDestroy(&def->pc);CHKERRQ(ierr);
41022b0793eSJakub Kruzik   def->pc = apc;
41122b0793eSJakub Kruzik   ierr = PetscObjectReference((PetscObject)apc);CHKERRQ(ierr);
41222b0793eSJakub Kruzik   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->pc);CHKERRQ(ierr);
41322b0793eSJakub Kruzik   PetscFunctionReturn(0);
41422b0793eSJakub Kruzik }
41522b0793eSJakub Kruzik 
41622b0793eSJakub Kruzik /*@
41722b0793eSJakub Kruzik    PCDeflationSetPC - Set additional preconditioner.
41822b0793eSJakub Kruzik 
419268c6673SJakub Kruzik    Collective on PC
42022b0793eSJakub Kruzik 
42122b0793eSJakub Kruzik    Input Parameters:
42222b0793eSJakub Kruzik +  pc  - the preconditioner context
42322b0793eSJakub Kruzik -  apc - additional preconditioner
42422b0793eSJakub Kruzik 
425268c6673SJakub Kruzik    Level: developer
42622b0793eSJakub Kruzik 
427268c6673SJakub Kruzik .seealso: PCDeflationGetPC(), PCDEFLATION
42822b0793eSJakub Kruzik @*/
42922b0793eSJakub Kruzik PetscErrorCode PCDeflationSetPC(PC pc,PC apc)
43022b0793eSJakub Kruzik {
43122b0793eSJakub Kruzik   PetscErrorCode ierr;
43222b0793eSJakub Kruzik 
43322b0793eSJakub Kruzik   PetscFunctionBegin;
43422b0793eSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
43522b0793eSJakub Kruzik   PetscValidHeaderSpecific(apc,PC_CLASSID,2);
43622b0793eSJakub Kruzik   PetscCheckSameComm(pc,1,apc,2);
43722b0793eSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetPC_C",(PC,PC),(pc,apc));CHKERRQ(ierr);
43822b0793eSJakub Kruzik   PetscFunctionReturn(0);
43922b0793eSJakub Kruzik }
44022b0793eSJakub Kruzik 
44137eeb815SJakub Kruzik /*
442b27c8092SJakub Kruzik   x <- x + W*(W'*A*W)^{-1}*W'*r  = x + Q*r
443b27c8092SJakub Kruzik */
444b27c8092SJakub Kruzik static PetscErrorCode PCPreSolve_Deflation(PC pc,KSP ksp,Vec b, Vec x)
445b27c8092SJakub Kruzik {
446b27c8092SJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
447b27c8092SJakub Kruzik   Mat              A;
448b27c8092SJakub Kruzik   Vec              r,w1,w2;
449b27c8092SJakub Kruzik   PetscBool        nonzero;
450b27c8092SJakub Kruzik   PetscErrorCode   ierr;
45137eeb815SJakub Kruzik 
452b27c8092SJakub Kruzik   PetscFunctionBegin;
453b27c8092SJakub Kruzik   w1 = def->workcoarse[0];
454b27c8092SJakub Kruzik   w2 = def->workcoarse[1];
455b27c8092SJakub Kruzik   r  = def->work;
456b27c8092SJakub Kruzik   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
45737eeb815SJakub Kruzik 
458b27c8092SJakub Kruzik   ierr = KSPGetInitialGuessNonzero(ksp,&nonzero);CHKERRQ(ierr);
459b27c8092SJakub Kruzik   ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
460b27c8092SJakub Kruzik   if (nonzero) {
461b27c8092SJakub Kruzik     ierr = MatMult(A,x,r);CHKERRQ(ierr);                          /*    r  <- b - Ax              */
462b27c8092SJakub Kruzik     ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr);
463b27c8092SJakub Kruzik   } else {
464b27c8092SJakub Kruzik     ierr = VecCopy(b,r);CHKERRQ(ierr);                            /*    r  <- b (x is 0)          */
465b27c8092SJakub Kruzik   }
466b27c8092SJakub Kruzik 
467a3177931SJakub Kruzik   if (def->Wt) {
468a3177931SJakub Kruzik     ierr = MatMult(def->Wt,r,w1);CHKERRQ(ierr);                   /*    w1 <- W'*r                */
469a3177931SJakub Kruzik   } else {
470a3177931SJakub Kruzik     ierr = MatMultHermitianTranspose(def->W,r,w1);CHKERRQ(ierr);  /*    w1 <- W'*r                */
471a3177931SJakub Kruzik   }
472b27c8092SJakub Kruzik   ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);              /*    w2 <- (W'*A*W)^{-1}*w1    */
473b27c8092SJakub Kruzik   ierr = MatMult(def->W,w2,r);CHKERRQ(ierr);                      /*    r  <- W*w2                */
474b27c8092SJakub Kruzik   ierr = VecAYPX(x,1.0,r);CHKERRQ(ierr);
475b27c8092SJakub Kruzik   PetscFunctionReturn(0);
476b27c8092SJakub Kruzik }
47737eeb815SJakub Kruzik 
478f8bf229cSJakub Kruzik /*
479f8bf229cSJakub Kruzik   if (def->correct) {
480ae029463SJakub Kruzik     z <- M^{-1}r - W*(W'*A*W)^{-1}*(W'*A*M^{-1}r - l*W'*r) = (P*M^{-1} + l*Q)*r
481f8bf229cSJakub Kruzik   } else {
482ae029463SJakub Kruzik     z <- M^{-1}*r - W*(W'*A*W)^{-1}*W'*A*M{-1}*r = P*M^{-1}*r
483f8bf229cSJakub Kruzik   }
48437eeb815SJakub Kruzik */
485f8bf229cSJakub Kruzik static PetscErrorCode PCApply_Deflation(PC pc,Vec r,Vec z)
486f8bf229cSJakub Kruzik {
487f8bf229cSJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
488f8bf229cSJakub Kruzik   Mat              A;
489f8bf229cSJakub Kruzik   Vec              u,w1,w2;
490f8bf229cSJakub Kruzik   PetscErrorCode   ierr;
491f8bf229cSJakub Kruzik 
492f8bf229cSJakub Kruzik   PetscFunctionBegin;
493f8bf229cSJakub Kruzik   w1 = def->workcoarse[0];
494f8bf229cSJakub Kruzik   w2 = def->workcoarse[1];
495f8bf229cSJakub Kruzik   u  = def->work;
496f8bf229cSJakub Kruzik   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
497f8bf229cSJakub Kruzik 
498ae029463SJakub Kruzik   ierr = PCApply(def->pc,r,z);CHKERRQ(ierr);                      /*    z <- M^{-1}*r             */
49922b0793eSJakub Kruzik   if (!def->init) {
500ae029463SJakub Kruzik     ierr = MatMult(def->WtA,z,w1);CHKERRQ(ierr);                  /*    w1 <- W'*A*z              */
501f8bf229cSJakub Kruzik     if (def->correct) {
502ae029463SJakub Kruzik       if (def->Wt) {
503ae029463SJakub Kruzik         ierr = MatMult(def->Wt,r,w2);CHKERRQ(ierr);               /*    w2 <- W'*r                */
504ae029463SJakub Kruzik       } else {
505a3177931SJakub Kruzik         ierr = MatMultHermitianTranspose(def->W,r,w2);CHKERRQ(ierr);       /*    w2 <- W'*r                */
506f8bf229cSJakub Kruzik       }
507ae029463SJakub Kruzik       ierr = VecAXPY(w1,-1.0*def->correctfact,w2);CHKERRQ(ierr);  /*    w1 <- w1 - l*w2           */
508f8bf229cSJakub Kruzik     }
509f8bf229cSJakub Kruzik     ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);            /*    w2 <- (W'*A*W)^{-1}*w1    */
510f8bf229cSJakub Kruzik     ierr = MatMult(def->W,w2,u);CHKERRQ(ierr);                    /*    u  <- W*w2                */
51122b0793eSJakub Kruzik     ierr = VecAXPY(z,-1.0,u);CHKERRQ(ierr);                       /*    z  <- z - u               */
51222b0793eSJakub Kruzik   }
513f8bf229cSJakub Kruzik   PetscFunctionReturn(0);
514f8bf229cSJakub Kruzik }
515f8bf229cSJakub Kruzik 
51637eeb815SJakub Kruzik static PetscErrorCode PCSetUp_Deflation(PC pc)
51737eeb815SJakub Kruzik {
518409a357bSJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
519409a357bSJakub Kruzik   KSP              innerksp;
520409a357bSJakub Kruzik   PC               pcinner;
521409a357bSJakub Kruzik   Mat              Amat,nextDef=NULL,*mats;
522409a357bSJakub Kruzik   PetscInt         i,m,red,size,commsize;
523409a357bSJakub Kruzik   PetscBool        match,flgspd,transp=PETSC_FALSE;
524409a357bSJakub Kruzik   MatCompositeType ctype;
525409a357bSJakub Kruzik   MPI_Comm         comm;
526409a357bSJakub Kruzik   const char       *prefix;
52737eeb815SJakub Kruzik   PetscErrorCode   ierr;
52837eeb815SJakub Kruzik 
52937eeb815SJakub Kruzik   PetscFunctionBegin;
530409a357bSJakub Kruzik   if (pc->setupcalled) PetscFunctionReturn(0);
531409a357bSJakub Kruzik   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
532f8bf229cSJakub Kruzik   ierr = PCGetOperators(pc,NULL,&Amat);CHKERRQ(ierr);
533f8bf229cSJakub Kruzik 
534f8bf229cSJakub Kruzik   /* compute a deflation space */
535409a357bSJakub Kruzik   if (def->W || def->Wt) {
536409a357bSJakub Kruzik     def->spacetype = PC_DEFLATION_SPACE_USER;
537409a357bSJakub Kruzik   } else {
538e53e0a0dSJakub Kruzik     ierr = PCDeflationComputeSpace(pc);CHKERRQ(ierr);
53937eeb815SJakub Kruzik   }
54037eeb815SJakub Kruzik 
541409a357bSJakub Kruzik   /* nested deflation */
542409a357bSJakub Kruzik   if (def->W) {
543409a357bSJakub Kruzik     ierr = PetscObjectTypeCompare((PetscObject)def->W,MATCOMPOSITE,&match);CHKERRQ(ierr);
544409a357bSJakub Kruzik     if (match) {
545409a357bSJakub Kruzik       ierr = MatCompositeGetType(def->W,&ctype);CHKERRQ(ierr);
546409a357bSJakub Kruzik       ierr = MatCompositeGetNumberMat(def->W,&size);CHKERRQ(ierr);
54737eeb815SJakub Kruzik     }
548409a357bSJakub Kruzik   } else {
549a3177931SJakub Kruzik     ierr = MatCreateHermitianTranspose(def->Wt,&def->W);CHKERRQ(ierr);
550409a357bSJakub Kruzik     ierr = PetscObjectTypeCompare((PetscObject)def->Wt,MATCOMPOSITE,&match);CHKERRQ(ierr);
551409a357bSJakub Kruzik     if (match) {
552409a357bSJakub Kruzik       ierr = MatCompositeGetType(def->Wt,&ctype);CHKERRQ(ierr);
553409a357bSJakub Kruzik       ierr = MatCompositeGetNumberMat(def->Wt,&size);CHKERRQ(ierr);
554409a357bSJakub Kruzik     }
555409a357bSJakub Kruzik     transp = PETSC_TRUE;
556409a357bSJakub Kruzik   }
557409a357bSJakub Kruzik   if (match && ctype == MAT_COMPOSITE_MULTIPLICATIVE) {
558409a357bSJakub Kruzik     if (!transp) {
55928da0170SJakub Kruzik       if (def->nestedlvl < def->maxnestedlvl) {
56028da0170SJakub Kruzik         ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
561409a357bSJakub Kruzik         for (i=0; i<size; i++) {
562409a357bSJakub Kruzik           ierr = MatCompositeGetMat(def->W,i,&mats[i]);CHKERRQ(ierr);
563409a357bSJakub Kruzik         }
564409a357bSJakub Kruzik         size -= 1;
565409a357bSJakub Kruzik         ierr = MatDestroy(&def->W);CHKERRQ(ierr);
566409a357bSJakub Kruzik         def->W = mats[size];
567409a357bSJakub Kruzik         ierr = PetscObjectReference((PetscObject)mats[size]);CHKERRQ(ierr);
568409a357bSJakub Kruzik         if (size > 1) {
569409a357bSJakub Kruzik           ierr = MatCreateComposite(comm,size,mats,&nextDef);CHKERRQ(ierr);
570409a357bSJakub Kruzik           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
571409a357bSJakub Kruzik         } else {
572409a357bSJakub Kruzik           nextDef = mats[0];
573409a357bSJakub Kruzik           ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
574409a357bSJakub Kruzik         }
57528da0170SJakub Kruzik         ierr = PetscFree(mats);CHKERRQ(ierr);
576409a357bSJakub Kruzik       } else {
577409a357bSJakub Kruzik         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
578409a357bSJakub Kruzik         ierr = MatCompositeMerge(def->W);CHKERRQ(ierr);
579409a357bSJakub Kruzik       }
58028da0170SJakub Kruzik     } else {
58128da0170SJakub Kruzik       if (def->nestedlvl < def->maxnestedlvl) {
58228da0170SJakub Kruzik         ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
58328da0170SJakub Kruzik         for (i=0; i<size; i++) {
58428da0170SJakub Kruzik           ierr = MatCompositeGetMat(def->Wt,i,&mats[i]);CHKERRQ(ierr);
58528da0170SJakub Kruzik         }
58628da0170SJakub Kruzik         size -= 1;
58728da0170SJakub Kruzik         ierr = MatDestroy(&def->Wt);CHKERRQ(ierr);
58828da0170SJakub Kruzik         def->Wt = mats[0];
58928da0170SJakub Kruzik         ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
59028da0170SJakub Kruzik         if (size > 1) {
59128da0170SJakub Kruzik           ierr = MatCreateComposite(comm,size,&mats[1],&nextDef);CHKERRQ(ierr);
59228da0170SJakub Kruzik           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
59328da0170SJakub Kruzik         } else {
59428da0170SJakub Kruzik           nextDef = mats[1];
59528da0170SJakub Kruzik           ierr = PetscObjectReference((PetscObject)mats[1]);CHKERRQ(ierr);
596409a357bSJakub Kruzik         }
597409a357bSJakub Kruzik         ierr = PetscFree(mats);CHKERRQ(ierr);
59828da0170SJakub Kruzik       } else {
59928da0170SJakub Kruzik         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
60028da0170SJakub Kruzik         ierr = MatCompositeMerge(def->Wt);CHKERRQ(ierr);
60128da0170SJakub Kruzik       }
60228da0170SJakub Kruzik     }
60328da0170SJakub Kruzik   }
60428da0170SJakub Kruzik 
60528da0170SJakub Kruzik   if (transp) {
60628da0170SJakub Kruzik     ierr = MatDestroy(&def->W);CHKERRQ(ierr);
607a3177931SJakub Kruzik     ierr = MatHermitianTranspose(def->Wt,MAT_INITIAL_MATRIX,&def->W);CHKERRQ(ierr);
608409a357bSJakub Kruzik   }
609409a357bSJakub Kruzik 
61022b0793eSJakub Kruzik 
61122b0793eSJakub Kruzik   ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
61222b0793eSJakub Kruzik 
613ae029463SJakub Kruzik   /* assemble WtA */
614ae029463SJakub Kruzik   if (!def->WtA) {
615ae029463SJakub Kruzik     if (def->Wt) {
616ae029463SJakub Kruzik       ierr = MatMatMult(def->Wt,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr);
617ae029463SJakub Kruzik     } else {
618a3177931SJakub Kruzik #if defined(PETSC_USE_COMPLEX)
619a3177931SJakub Kruzik       ierr = MatHermitianTranspose(def->W,MAT_INITIAL_MATRIX,&def->Wt);CHKERRQ(ierr);
620a3177931SJakub Kruzik       ierr = MatMatMult(def->W,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr);
621a3177931SJakub Kruzik #else
622ae029463SJakub Kruzik       ierr = MatTransposeMatMult(def->W,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr);
623a3177931SJakub Kruzik #endif
624ae029463SJakub Kruzik     }
625ae029463SJakub Kruzik   }
626409a357bSJakub Kruzik   /* setup coarse problem */
627409a357bSJakub Kruzik   if (!def->WtAWinv) {
62828da0170SJakub Kruzik     ierr = MatGetSize(def->W,NULL,&m);CHKERRQ(ierr);
629409a357bSJakub Kruzik     if (!def->WtAW) {
630ae029463SJakub Kruzik       ierr = MatMatMult(def->WtA,def->W,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr);
631409a357bSJakub Kruzik       /* TODO create MatInheritOption(Mat,MatOption) */
632409a357bSJakub Kruzik       ierr = MatGetOption(Amat,MAT_SPD,&flgspd);CHKERRQ(ierr);
633409a357bSJakub Kruzik       ierr = MatSetOption(def->WtAW,MAT_SPD,flgspd);CHKERRQ(ierr);
634409a357bSJakub Kruzik #if defined(PETSC_USE_DEBUG)
635ae029463SJakub Kruzik       /* Check columns of W are not in kernel of A */
636409a357bSJakub Kruzik       PetscReal *norms;
637409a357bSJakub Kruzik       ierr = PetscMalloc1(m,&norms);CHKERRQ(ierr);
638409a357bSJakub Kruzik       ierr = MatGetColumnNorms(def->WtAW,NORM_INFINITY,norms);CHKERRQ(ierr);
639409a357bSJakub Kruzik       for (i=0; i<m; i++) {
640409a357bSJakub Kruzik         if (norms[i] < 100*PETSC_MACHINE_EPSILON) {
641409a357bSJakub Kruzik           SETERRQ1(comm,PETSC_ERR_SUP,"Column %D of W is in kernel of A.",i);
642409a357bSJakub Kruzik         }
643409a357bSJakub Kruzik       }
644409a357bSJakub Kruzik       ierr = PetscFree(norms);CHKERRQ(ierr);
645409a357bSJakub Kruzik #endif
646409a357bSJakub Kruzik     } else {
647409a357bSJakub Kruzik       ierr = MatGetOption(def->WtAW,MAT_SPD,&flgspd);CHKERRQ(ierr);
648409a357bSJakub Kruzik     }
649409a357bSJakub Kruzik     /* TODO use MATINV */
650409a357bSJakub Kruzik     ierr = KSPCreate(comm,&def->WtAWinv);CHKERRQ(ierr);
651409a357bSJakub Kruzik     ierr = KSPSetOperators(def->WtAWinv,def->WtAW,def->WtAW);CHKERRQ(ierr);
652409a357bSJakub Kruzik     ierr = KSPGetPC(def->WtAWinv,&pcinner);CHKERRQ(ierr);
653557a2f7dSJakub Kruzik     /* Setup KSP and PC */
654557a2f7dSJakub Kruzik     if (nextDef) { /* next level for multilevel deflation */
655557a2f7dSJakub Kruzik       innerksp = def->WtAWinv;
656557a2f7dSJakub Kruzik       /* set default KSPtype */
657557a2f7dSJakub Kruzik       if (!def->ksptype) {
658557a2f7dSJakub Kruzik         def->ksptype = KSPFGMRES;
659557a2f7dSJakub Kruzik         if (flgspd) { /* SPD system */
660557a2f7dSJakub Kruzik           def->ksptype = KSPFCG;
661557a2f7dSJakub Kruzik         }
662557a2f7dSJakub Kruzik       }
663ae029463SJakub Kruzik       ierr = KSPSetType(innerksp,def->ksptype);CHKERRQ(ierr); /* TODO iherit from KSP + tolerances */
664557a2f7dSJakub Kruzik       ierr = PCSetType(pcinner,PCDEFLATION);CHKERRQ(ierr); /* TODO create coarse preconditinoner M_c = WtMW ? */
665557a2f7dSJakub Kruzik       ierr = PCDeflationSetSpace(pcinner,nextDef,transp);CHKERRQ(ierr);
666557a2f7dSJakub Kruzik       ierr = PCDeflationSetLvl_Deflation(pcinner,def->nestedlvl+1,def->maxnestedlvl);CHKERRQ(ierr);
667ae029463SJakub Kruzik       /* inherit options */
668557a2f7dSJakub Kruzik       ((PC_Deflation*)(pcinner->data))->ksptype = def->ksptype;
669557a2f7dSJakub Kruzik       ((PC_Deflation*)(pcinner->data))->correct = def->correct;
670557a2f7dSJakub Kruzik       ierr = MatDestroy(&nextDef);CHKERRQ(ierr);
671557a2f7dSJakub Kruzik     } else { /* the last level */
672557a2f7dSJakub Kruzik       ierr = KSPSetType(def->WtAWinv,KSPPREONLY);CHKERRQ(ierr);
673409a357bSJakub Kruzik       ierr = PCSetType(pcinner,PCTELESCOPE);CHKERRQ(ierr);
674ac66f006SJakub Kruzik       /* ugly hack to not have overwritten PCTELESCOPE */
675ac66f006SJakub Kruzik       if (prefix) {
676ac66f006SJakub Kruzik         ierr = KSPSetOptionsPrefix(def->WtAWinv,prefix);CHKERRQ(ierr);
677ac66f006SJakub Kruzik       }
67822b0793eSJakub Kruzik       ierr = KSPAppendOptionsPrefix(def->WtAWinv,"tel_");CHKERRQ(ierr);
679ac66f006SJakub Kruzik       ierr = PCSetFromOptions(pcinner);CHKERRQ(ierr);
680409a357bSJakub Kruzik       /* Reduction factor choice */
681409a357bSJakub Kruzik       red = def->reductionfact;
682409a357bSJakub Kruzik       if (red < 0) {
683409a357bSJakub Kruzik         ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
684409a357bSJakub Kruzik         red  = ceil((float)commsize/ceil((float)m/commsize));
685409a357bSJakub Kruzik         ierr = PetscObjectTypeCompareAny((PetscObject)(def->WtAW),&match,MATSEQDENSE,MATMPIDENSE,MATDENSE,"");CHKERRQ(ierr);
686409a357bSJakub Kruzik         if (match) red = commsize;
687409a357bSJakub Kruzik         ierr = PetscInfo1(pc,"Auto choosing reduction factor %D\n",red);CHKERRQ(ierr); /* TODO add level? */
688409a357bSJakub Kruzik       }
689409a357bSJakub Kruzik       ierr = PCTelescopeSetReductionFactor(pcinner,red);CHKERRQ(ierr);
690ac66f006SJakub Kruzik       ierr = PCSetUp(pcinner);CHKERRQ(ierr);
691409a357bSJakub Kruzik       ierr = PCTelescopeGetKSP(pcinner,&innerksp);CHKERRQ(ierr);
692ac66f006SJakub Kruzik       if (innerksp) {
693409a357bSJakub Kruzik         ierr = KSPGetPC(innerksp,&pcinner);CHKERRQ(ierr);
694409a357bSJakub Kruzik         /* TODO Cholesky if flgspd? */
695ac66f006SJakub Kruzik         ierr = PCSetType(pcinner,PCLU);CHKERRQ(ierr);
696409a357bSJakub Kruzik         //TODO remove explicit matSolverPackage
697409a357bSJakub Kruzik         if (commsize == red) {
698ac66f006SJakub Kruzik           ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU);CHKERRQ(ierr);
699409a357bSJakub Kruzik         } else {
700ac66f006SJakub Kruzik           ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU_DIST);CHKERRQ(ierr);
701409a357bSJakub Kruzik         }
702409a357bSJakub Kruzik       }
703557a2f7dSJakub Kruzik     }
704557a2f7dSJakub Kruzik 
705557a2f7dSJakub Kruzik     if (innerksp) {
706409a357bSJakub Kruzik       /* TODO use def_[lvl]_ if lvl > 0? */
707409a357bSJakub Kruzik       if (prefix) {
708409a357bSJakub Kruzik         ierr = KSPSetOptionsPrefix(innerksp,prefix);CHKERRQ(ierr);
709409a357bSJakub Kruzik       }
71022b0793eSJakub Kruzik       ierr = KSPAppendOptionsPrefix(innerksp,"def_");CHKERRQ(ierr);
711557a2f7dSJakub Kruzik       ierr = KSPSetFromOptions(innerksp);CHKERRQ(ierr);
712557a2f7dSJakub Kruzik       ierr = KSPSetUp(innerksp);CHKERRQ(ierr);
713ac66f006SJakub Kruzik     }
714409a357bSJakub Kruzik   }
715557a2f7dSJakub Kruzik   ierr = KSPSetFromOptions(def->WtAWinv);CHKERRQ(ierr);
716557a2f7dSJakub Kruzik   ierr = KSPSetUp(def->WtAWinv);CHKERRQ(ierr);
717409a357bSJakub Kruzik 
71822b0793eSJakub Kruzik   if (!def->pc) {
71922b0793eSJakub Kruzik     ierr = PCCreate(comm,&def->pc);CHKERRQ(ierr);
72022b0793eSJakub Kruzik     ierr = PCSetOperators(def->pc,Amat,Amat);CHKERRQ(ierr);
72122b0793eSJakub Kruzik     ierr = PCSetType(def->pc,PCNONE);CHKERRQ(ierr);
72222b0793eSJakub Kruzik     if (prefix) {
72322b0793eSJakub Kruzik       ierr = PCSetOptionsPrefix(def->pc,prefix);CHKERRQ(ierr);
72422b0793eSJakub Kruzik     }
72522b0793eSJakub Kruzik     ierr = PCAppendOptionsPrefix(def->pc,"def_pc_");CHKERRQ(ierr);
72622b0793eSJakub Kruzik     ierr = PCSetFromOptions(def->pc);CHKERRQ(ierr);
72722b0793eSJakub Kruzik     ierr = PCSetUp(def->pc);CHKERRQ(ierr);
72822b0793eSJakub Kruzik   }
72922b0793eSJakub Kruzik 
730f8bf229cSJakub Kruzik   /* create work vecs */
731f8bf229cSJakub Kruzik   ierr = MatCreateVecs(Amat,NULL,&def->work);CHKERRQ(ierr);
732f8bf229cSJakub Kruzik   ierr = KSPCreateVecs(def->WtAWinv,2,&def->workcoarse,0,NULL);CHKERRQ(ierr);
73337eeb815SJakub Kruzik   PetscFunctionReturn(0);
73437eeb815SJakub Kruzik }
735b30d4775SJakub Kruzik 
73637eeb815SJakub Kruzik static PetscErrorCode PCReset_Deflation(PC pc)
73737eeb815SJakub Kruzik {
738b30d4775SJakub Kruzik   PC_Deflation      *def = (PC_Deflation*)pc->data;
73937eeb815SJakub Kruzik   PetscErrorCode    ierr;
74037eeb815SJakub Kruzik 
74137eeb815SJakub Kruzik   PetscFunctionBegin;
742b30d4775SJakub Kruzik   ierr = VecDestroy(&def->work);CHKERRQ(ierr);
743b30d4775SJakub Kruzik   ierr = VecDestroyVecs(2,&def->workcoarse);CHKERRQ(ierr);
744b30d4775SJakub Kruzik   ierr = MatDestroy(&def->W);CHKERRQ(ierr);
745b30d4775SJakub Kruzik   ierr = MatDestroy(&def->Wt);CHKERRQ(ierr);
746ae029463SJakub Kruzik   ierr = MatDestroy(&def->WtA);CHKERRQ(ierr);
747b30d4775SJakub Kruzik   ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr);
748b30d4775SJakub Kruzik   ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr);
74922b0793eSJakub Kruzik   ierr = PCDestroy(&def->pc);CHKERRQ(ierr);
75037eeb815SJakub Kruzik   PetscFunctionReturn(0);
75137eeb815SJakub Kruzik }
75237eeb815SJakub Kruzik 
75337eeb815SJakub Kruzik /*
75437eeb815SJakub Kruzik    PCDestroy_Deflation - Destroys the private context for the Deflation preconditioner
75537eeb815SJakub Kruzik    that was created with PCCreate_Deflation().
75637eeb815SJakub Kruzik 
75737eeb815SJakub Kruzik    Input Parameter:
75837eeb815SJakub Kruzik .  pc - the preconditioner context
75937eeb815SJakub Kruzik 
76037eeb815SJakub Kruzik    Application Interface Routine: PCDestroy()
76137eeb815SJakub Kruzik */
76237eeb815SJakub Kruzik static PetscErrorCode PCDestroy_Deflation(PC pc)
76337eeb815SJakub Kruzik {
76437eeb815SJakub Kruzik   PetscErrorCode ierr;
76537eeb815SJakub Kruzik 
76637eeb815SJakub Kruzik   PetscFunctionBegin;
76737eeb815SJakub Kruzik   ierr = PCReset_Deflation(pc);CHKERRQ(ierr);
76837eeb815SJakub Kruzik   ierr = PetscFree(pc->data);CHKERRQ(ierr);
76937eeb815SJakub Kruzik   PetscFunctionReturn(0);
77037eeb815SJakub Kruzik }
77137eeb815SJakub Kruzik 
7728513960bSJakub Kruzik static PetscErrorCode PCView_Deflation(PC pc,PetscViewer viewer)
7738513960bSJakub Kruzik {
7748513960bSJakub Kruzik   PC_Deflation      *def = (PC_Deflation*)pc->data;
7758513960bSJakub Kruzik   PetscBool         iascii;
7768513960bSJakub Kruzik   PetscErrorCode    ierr;
7778513960bSJakub Kruzik 
7788513960bSJakub Kruzik   PetscFunctionBegin;
7798513960bSJakub Kruzik   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
7808513960bSJakub Kruzik   if (iascii) {
7818513960bSJakub Kruzik     //if (cg->adaptiveconv) {
7828513960bSJakub Kruzik     //  ierr = PetscViewerASCIIPrintf(viewer,"  DCG: using adaptive precision for inner solve with C=%.1e\n",cg->adaptiveconst);CHKERRQ(ierr);
7838513960bSJakub Kruzik     //}
7848513960bSJakub Kruzik     if (def->correct) {
7858513960bSJakub Kruzik       ierr = PetscViewerASCIIPrintf(viewer,"  Using CP correction\n");CHKERRQ(ierr);
7868513960bSJakub Kruzik     }
7878513960bSJakub Kruzik     if (!def->nestedlvl) {
7888513960bSJakub Kruzik       ierr = PetscViewerASCIIPrintf(viewer,"  Deflation space type: %s\n",PCDeflationSpaceTypes[def->spacetype]);CHKERRQ(ierr);
7898513960bSJakub Kruzik       ierr = PetscViewerASCIIPrintf(viewer,"  DCG %s\n",def->extendsp ? "extended" : "truncated");CHKERRQ(ierr);
7908513960bSJakub Kruzik     }
7918513960bSJakub Kruzik 
79222b0793eSJakub Kruzik     ierr = PetscViewerASCIIPrintf(viewer,"--- Additional PC\n");CHKERRQ(ierr);
79322b0793eSJakub Kruzik     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
79422b0793eSJakub Kruzik     ierr = PCView(def->pc,viewer);CHKERRQ(ierr);
79522b0793eSJakub Kruzik     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
79622b0793eSJakub Kruzik 
7978513960bSJakub Kruzik     ierr = PetscViewerASCIIPrintf(viewer,"--- Coarse solver\n");CHKERRQ(ierr);
7988513960bSJakub Kruzik     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
7998513960bSJakub Kruzik     ierr = KSPView(def->WtAWinv,viewer);CHKERRQ(ierr);
8008513960bSJakub Kruzik     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
8018513960bSJakub Kruzik   }
8028513960bSJakub Kruzik   PetscFunctionReturn(0);
8038513960bSJakub Kruzik }
8048513960bSJakub Kruzik 
80537eeb815SJakub Kruzik static PetscErrorCode PCSetFromOptions_Deflation(PetscOptionItems *PetscOptionsObject,PC pc)
80637eeb815SJakub Kruzik {
807880d05ceSJakub Kruzik   PC_Deflation      *def = (PC_Deflation*)pc->data;
80837eeb815SJakub Kruzik   PetscErrorCode    ierr;
80937eeb815SJakub Kruzik 
81037eeb815SJakub Kruzik   PetscFunctionBegin;
81137eeb815SJakub Kruzik   ierr = PetscOptionsHead(PetscOptionsObject,"Deflation options");CHKERRQ(ierr);
812*859a873cSJakub Kruzik   ierr = PetscOptionsInt("-pc_deflation_max_lvl","Maximum of deflation levels","PCDeflationSetMaxLvl",def->maxnestedlvl,&def->maxnestedlvl,NULL);CHKERRQ(ierr);
813*859a873cSJakub Kruzik   ierr = PetscOptionsInt("-pc_deflation_reduction_factor","Reduction factor for coarse problem solution using PCTELESCOPE","PCDeflationSetReductionFactor",def->reductionfact,&def->reductionfact,NULL);CHKERRQ(ierr);
814880d05ceSJakub Kruzik   ierr = PetscOptionsEnum("-pc_deflation_compute_space","Compute deflation space","PCDeflationSetSpace",PCDeflationSpaceTypes,(PetscEnum)def->spacetype,(PetscEnum*)&def->spacetype,NULL);CHKERRQ(ierr);
815880d05ceSJakub Kruzik   ierr = PetscOptionsInt("-pc_deflation_compute_space_size","Set size of the deflation space to compute","PCDeflationSetSpace",def->spacesize,&def->spacesize,NULL);CHKERRQ(ierr);
816880d05ceSJakub Kruzik   ierr = PetscOptionsBool("-pc_deflation_space_extend","Extend deflation space instead of truncating (wavelets)","PCDeflation",def->extendsp,&def->extendsp,NULL);CHKERRQ(ierr);
817880d05ceSJakub Kruzik //TODO add set function and fix manpages
818880d05ceSJakub Kruzik   ierr = PetscOptionsBool("-pc_deflation_initdef","Use only initialization step - Initdef","PCDeflation",def->init,&def->init,NULL);CHKERRQ(ierr);
819fcb31d99SJakub Kruzik   ierr = PetscOptionsBool("-pc_deflation_correct","Add coarse problem correction Q to P","PCDeflation",def->correct,&def->correct,NULL);CHKERRQ(ierr);
820fcb31d99SJakub Kruzik   ierr = PetscOptionsReal("-pc_deflation_correct_val","Set multiple of Q to use as coarse problem correction","PCDeflation",def->correctfact,&def->correctfact,NULL);CHKERRQ(ierr);
82137eeb815SJakub Kruzik   ierr = PetscOptionsTail();CHKERRQ(ierr);
82237eeb815SJakub Kruzik   PetscFunctionReturn(0);
82337eeb815SJakub Kruzik }
82437eeb815SJakub Kruzik 
82537eeb815SJakub Kruzik /*MC
826e361f8b5SJakub Kruzik      PCDEFLATION - Deflation preconditioner shifts part of the spectrum to zero (deflates)
827e361f8b5SJakub Kruzik      or to a predefined value
82837eeb815SJakub Kruzik 
82937eeb815SJakub Kruzik    Options Database Key:
830e361f8b5SJakub Kruzik +    -pc_deflation_type <init,pre,post> - selects approach to deflation (default: pre)
83137eeb815SJakub Kruzik -    -pc_jacobi_abs - use the absolute value of the diagonal entry
83237eeb815SJakub Kruzik 
83337eeb815SJakub Kruzik    Level: beginner
83437eeb815SJakub Kruzik 
83537eeb815SJakub Kruzik   Notes:
836e361f8b5SJakub Kruzik     todo
83737eeb815SJakub Kruzik 
83837eeb815SJakub Kruzik .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
839e662bc50SJakub Kruzik            PCDeflationSetType(), PCDeflationSetSpace()
84037eeb815SJakub Kruzik M*/
84137eeb815SJakub Kruzik 
84237eeb815SJakub Kruzik PETSC_EXTERN PetscErrorCode PCCreate_Deflation(PC pc)
84337eeb815SJakub Kruzik {
84437eeb815SJakub Kruzik   PC_Deflation   *def;
84537eeb815SJakub Kruzik   PetscErrorCode ierr;
84637eeb815SJakub Kruzik 
84737eeb815SJakub Kruzik   PetscFunctionBegin;
84837eeb815SJakub Kruzik   ierr     = PetscNewLog(pc,&def);CHKERRQ(ierr);
84937eeb815SJakub Kruzik   pc->data = (void*)def;
85037eeb815SJakub Kruzik 
851e662bc50SJakub Kruzik   def->init          = PETSC_FALSE;
852e662bc50SJakub Kruzik   def->correct       = PETSC_FALSE;
853fcb31d99SJakub Kruzik   def->correctfact   = 1.0;
854e662bc50SJakub Kruzik   def->reductionfact = -1;
855e662bc50SJakub Kruzik   def->spacetype     = PC_DEFLATION_SPACE_HAAR;
856e662bc50SJakub Kruzik   def->spacesize     = 1;
857e662bc50SJakub Kruzik   def->extendsp      = PETSC_FALSE;
858e662bc50SJakub Kruzik   def->nestedlvl     = 0;
859e662bc50SJakub Kruzik   def->maxnestedlvl  = 0;
86037eeb815SJakub Kruzik 
86137eeb815SJakub Kruzik   /*
86237eeb815SJakub Kruzik       Set the pointers for the functions that are provided above.
86337eeb815SJakub Kruzik       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
86437eeb815SJakub Kruzik       are called, they will automatically call these functions.  Note we
86537eeb815SJakub Kruzik       choose not to provide a couple of these functions since they are
86637eeb815SJakub Kruzik       not needed.
86737eeb815SJakub Kruzik   */
86837eeb815SJakub Kruzik   pc->ops->apply               = PCApply_Deflation;
86937eeb815SJakub Kruzik   pc->ops->applytranspose      = PCApply_Deflation;
870b27c8092SJakub Kruzik   pc->ops->presolve            = PCPreSolve_Deflation;
871b27c8092SJakub Kruzik   pc->ops->postsolve           = 0;
87237eeb815SJakub Kruzik   pc->ops->setup               = PCSetUp_Deflation;
87337eeb815SJakub Kruzik   pc->ops->reset               = PCReset_Deflation;
87437eeb815SJakub Kruzik   pc->ops->destroy             = PCDestroy_Deflation;
87537eeb815SJakub Kruzik   pc->ops->setfromoptions      = PCSetFromOptions_Deflation;
8768513960bSJakub Kruzik   pc->ops->view                = PCView_Deflation;
87737eeb815SJakub Kruzik   pc->ops->applyrichardson     = 0;
87837eeb815SJakub Kruzik   pc->ops->applysymmetricleft  = 0;
87937eeb815SJakub Kruzik   pc->ops->applysymmetricright = 0;
88037eeb815SJakub Kruzik 
88198d6e3deSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetLvl_C",PCDeflationSetLvl_Deflation);CHKERRQ(ierr);
882*859a873cSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetReductionFactor_C",PCDeflationSetReductionFactor_Deflation);CHKERRQ(ierr);
88339417d7eSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpaceToCompute_C",PCDeflationSetSpaceToCompute_Deflation);CHKERRQ(ierr);
884e662bc50SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpace_C",PCDeflationSetSpace_Deflation);CHKERRQ(ierr);
8853cf3a049SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetProjectionNullSpaceMat_C",PCDeflationSetProjectionNullSpaceMat_Deflation);CHKERRQ(ierr);
886e924b002SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCoarseMat_C",PCDeflationSetCoarseMat_Deflation);CHKERRQ(ierr);
8874a99276eSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetCoarseKSP_C",PCDeflationGetCoarseKSP_Deflation);CHKERRQ(ierr);
888f3eaa4f0SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCoarseKSP_C",PCDeflationSetCoarseKSP_Deflation);CHKERRQ(ierr);
88998d6e3deSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetPC_C",PCDeflationGetPC_Deflation);CHKERRQ(ierr);
89098d6e3deSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetPC_C",PCDeflationSetPC_Deflation);CHKERRQ(ierr);
89137eeb815SJakub Kruzik   PetscFunctionReturn(0);
89237eeb815SJakub Kruzik }
89337eeb815SJakub Kruzik 
894