xref: /petsc/src/ksp/pc/impls/deflation/deflation.c (revision e26ad46ddb9b797f150bedfb0b83e3b3eea939d9)
1292e2e67SJakub Kruzik #include <../src/ksp/pc/impls/deflation/deflation.h> /*I "petscpc.h" I*/  /* includes for fortran wrappers */
237eeb815SJakub Kruzik 
38513960bSJakub Kruzik const char *const PCDeflationSpaceTypes[] = {
48513960bSJakub Kruzik   "haar",
58513960bSJakub Kruzik   "jacket-haar",
68513960bSJakub Kruzik   "db2",
78513960bSJakub Kruzik   "db4",
88513960bSJakub Kruzik   "db8",
98513960bSJakub Kruzik   "db16",
108513960bSJakub Kruzik   "biorth22",
118513960bSJakub Kruzik   "meyer",
128513960bSJakub Kruzik   "aggregation",
138513960bSJakub Kruzik   "slepc",
148513960bSJakub Kruzik   "slepc-cheap",
158513960bSJakub Kruzik   "user",
160a78af22SJakub Kruzik   "PCDeflationSpaceType",
170a78af22SJakub Kruzik   "PC_DEFLATION_SPACE_",
188513960bSJakub Kruzik   0
198513960bSJakub Kruzik };
208513960bSJakub Kruzik 
21a122ebaeSJakub Kruzik static PetscErrorCode PCDeflationSetInitOnly_Deflation(PC pc,PetscBool flg)
22a122ebaeSJakub Kruzik {
23a122ebaeSJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
24a122ebaeSJakub Kruzik 
25a122ebaeSJakub Kruzik   PetscFunctionBegin;
26a122ebaeSJakub Kruzik   def->init = flg;
27a122ebaeSJakub Kruzik   PetscFunctionReturn(0);
28a122ebaeSJakub Kruzik }
29a122ebaeSJakub Kruzik 
30a122ebaeSJakub Kruzik /*@
31a122ebaeSJakub Kruzik    PCDeflationSetInitOnly - Do only initialization step.
32*e26ad46dSJakub Kruzik     Sets initial guess to the solution on the deflation space but does not apply
33*e26ad46dSJakub Kruzik     the deflation preconditioner. The additional preconditioner is still applied.
34a122ebaeSJakub Kruzik 
35*e26ad46dSJakub Kruzik    Logically Collective
36a122ebaeSJakub Kruzik 
37a122ebaeSJakub Kruzik    Input Parameters:
38a122ebaeSJakub Kruzik +  pc  - the preconditioner context
39a122ebaeSJakub Kruzik -  flg - default PETSC_FALSE
40a122ebaeSJakub Kruzik 
41*e26ad46dSJakub Kruzik    Options Database Keys:
42*e26ad46dSJakub Kruzik .    -pc_deflation_init_only <false> - if true computes only the special guess
43*e26ad46dSJakub Kruzik 
44a122ebaeSJakub Kruzik    Level: intermediate
45a122ebaeSJakub Kruzik 
46a122ebaeSJakub Kruzik .seealso: PCDEFLATION
47a122ebaeSJakub Kruzik @*/
48a122ebaeSJakub Kruzik PetscErrorCode PCDeflationSetInitOnly(PC pc,PetscBool flg)
49a122ebaeSJakub Kruzik {
50a122ebaeSJakub Kruzik   PetscErrorCode ierr;
51a122ebaeSJakub Kruzik 
52a122ebaeSJakub Kruzik   PetscFunctionBegin;
53a122ebaeSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
54a122ebaeSJakub Kruzik   PetscValidLogicalCollectiveBool(pc,flg,2);
55a122ebaeSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetInitOnly_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
56a122ebaeSJakub Kruzik   PetscFunctionReturn(0);
57a122ebaeSJakub Kruzik }
58a122ebaeSJakub Kruzik 
59a122ebaeSJakub Kruzik 
6098d6e3deSJakub Kruzik static PetscErrorCode PCDeflationSetLvl_Deflation(PC pc,PetscInt current,PetscInt max)
6198d6e3deSJakub Kruzik {
6298d6e3deSJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
6398d6e3deSJakub Kruzik 
6498d6e3deSJakub Kruzik   PetscFunctionBegin;
6598d6e3deSJakub Kruzik   if (current) def->nestedlvl = current;
6698d6e3deSJakub Kruzik   def->maxnestedlvl = max;
6798d6e3deSJakub Kruzik   PetscFunctionReturn(0);
6898d6e3deSJakub Kruzik }
6998d6e3deSJakub Kruzik 
7098d6e3deSJakub Kruzik /*@
71*e26ad46dSJakub Kruzik    PCDeflationSetMaxLvl - Set the maximum level of deflation nesting.
7298d6e3deSJakub Kruzik 
73*e26ad46dSJakub Kruzik    Logically Collective
7498d6e3deSJakub Kruzik 
7598d6e3deSJakub Kruzik    Input Parameters:
7698d6e3deSJakub Kruzik +  pc  - the preconditioner context
7798d6e3deSJakub Kruzik -  max - maximum deflation level
7898d6e3deSJakub Kruzik 
79*e26ad46dSJakub Kruzik    Options Database Keys:
80*e26ad46dSJakub Kruzik .    -pc_deflation_max_lvl <0> - maximum number of levels for multilevel deflation
81*e26ad46dSJakub Kruzik 
8298d6e3deSJakub Kruzik    Level: intermediate
8398d6e3deSJakub Kruzik 
84*e26ad46dSJakub Kruzik .seealso: PCDeflationSetSpaceToCompute(), PCDeflationSetSpace(), PCDEFLATION
8598d6e3deSJakub Kruzik @*/
8698d6e3deSJakub Kruzik PetscErrorCode PCDeflationSetMaxLvl(PC pc,PetscInt max)
8798d6e3deSJakub Kruzik {
8898d6e3deSJakub Kruzik   PetscErrorCode ierr;
8998d6e3deSJakub Kruzik 
9098d6e3deSJakub Kruzik   PetscFunctionBegin;
9198d6e3deSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
9298d6e3deSJakub Kruzik   PetscValidLogicalCollectiveInt(pc,max,2);
9398d6e3deSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetLvl_C",(PC,PetscInt,PetscInt),(pc,0,max));CHKERRQ(ierr);
9498d6e3deSJakub Kruzik   PetscFunctionReturn(0);
9598d6e3deSJakub Kruzik }
9698d6e3deSJakub Kruzik 
97859a873cSJakub Kruzik static PetscErrorCode PCDeflationSetReductionFactor_Deflation(PC pc,PetscInt red)
98859a873cSJakub Kruzik {
99859a873cSJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
100859a873cSJakub Kruzik 
101859a873cSJakub Kruzik   PetscFunctionBegin;
102859a873cSJakub Kruzik   def->reductionfact = red;
103859a873cSJakub Kruzik   PetscFunctionReturn(0);
104859a873cSJakub Kruzik }
105859a873cSJakub Kruzik 
106859a873cSJakub Kruzik /*@
107*e26ad46dSJakub Kruzik    PCDeflationSetReductionFactor - Set reduction factor for the bottom PCTELESCOPE coarse problem solver.
108859a873cSJakub Kruzik 
109*e26ad46dSJakub Kruzik    Logically Collective
110859a873cSJakub Kruzik 
111859a873cSJakub Kruzik    Input Parameters:
112859a873cSJakub Kruzik +  pc  - the preconditioner context
113859a873cSJakub Kruzik -  red - reduction factor (or PETSC_DETERMINE)
114859a873cSJakub Kruzik 
115*e26ad46dSJakub Kruzik    Options Database Keys:
116*e26ad46dSJakub Kruzik .    -pc_deflation_reduction_factor <-1> - reduction factor on bottom level coarse problem for PCTELESCOPE
117*e26ad46dSJakub Kruzik 
118*e26ad46dSJakub Kruzik    Notes:
119*e26ad46dSJakub Kruzik      Default is computed based on the size of the coarse problem.
120*e26ad46dSJakub Kruzik 
121859a873cSJakub Kruzik    Level: intermediate
122859a873cSJakub Kruzik 
123*e26ad46dSJakub Kruzik .seealso: PCTELESCOPE, PCDEFLATION
124859a873cSJakub Kruzik @*/
125859a873cSJakub Kruzik PetscErrorCode PCDeflationSetReductionFactor(PC pc,PetscInt red)
126859a873cSJakub Kruzik {
127859a873cSJakub Kruzik   PetscErrorCode ierr;
128859a873cSJakub Kruzik 
129859a873cSJakub Kruzik   PetscFunctionBegin;
130859a873cSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
131859a873cSJakub Kruzik   PetscValidLogicalCollectiveInt(pc,red,2);
132859a873cSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetReductionFactor_C",(PC,PetscInt),(pc,red));CHKERRQ(ierr);
133859a873cSJakub Kruzik   PetscFunctionReturn(0);
134859a873cSJakub Kruzik }
135859a873cSJakub Kruzik 
1368a71cb68SJakub Kruzik static PetscErrorCode PCDeflationSetCorrectionFactor_Deflation(PC pc,PetscScalar fact)
1378a71cb68SJakub Kruzik {
1388a71cb68SJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
1398a71cb68SJakub Kruzik 
1408a71cb68SJakub Kruzik   PetscFunctionBegin;
1418a71cb68SJakub Kruzik   /* TODO PETSC_DETERMINE -> compute max eigenvalue with power method */
1428a71cb68SJakub Kruzik   def->correct = PETSC_TRUE;
1438a71cb68SJakub Kruzik   def->correctfact = fact;
144*e26ad46dSJakub Kruzik   if (def->correct == 0.0) {
1458a71cb68SJakub Kruzik     def->correct = PETSC_FALSE;
1468a71cb68SJakub Kruzik   }
1478a71cb68SJakub Kruzik   PetscFunctionReturn(0);
1488a71cb68SJakub Kruzik }
1498a71cb68SJakub Kruzik 
1508a71cb68SJakub Kruzik /*@
1518a71cb68SJakub Kruzik    PCDeflationSetCorrectionFactor - Set coarse problem correction factor.
152*e26ad46dSJakub Kruzik     The Preconditioner becomes P*M^{-1} + fact*Q.
1538a71cb68SJakub Kruzik 
154*e26ad46dSJakub Kruzik    Logically Collective
1558a71cb68SJakub Kruzik 
1568a71cb68SJakub Kruzik    Input Parameters:
1578a71cb68SJakub Kruzik +  pc   - the preconditioner context
158*e26ad46dSJakub Kruzik -  fact - correction factor
159*e26ad46dSJakub Kruzik 
160*e26ad46dSJakub Kruzik    Options Database Keys:
161*e26ad46dSJakub Kruzik +    -pc_deflation_correction        <false> - if true apply coarse problem correction
162*e26ad46dSJakub Kruzik -    -pc_deflation_correction_factor <1.0>   - sets coarse problem correction factor
163*e26ad46dSJakub Kruzik 
164*e26ad46dSJakub Kruzik    Notes:
165*e26ad46dSJakub Kruzik     Any non-zero fact enables the coarse problem correction.
1668a71cb68SJakub Kruzik 
1678a71cb68SJakub Kruzik    Level: intermediate
1688a71cb68SJakub Kruzik 
1698a71cb68SJakub Kruzik .seealso: PCDEFLATION
1708a71cb68SJakub Kruzik @*/
1718a71cb68SJakub Kruzik PetscErrorCode PCDeflationSetCorrectionFactor(PC pc,PetscScalar fact)
1728a71cb68SJakub Kruzik {
1738a71cb68SJakub Kruzik   PetscErrorCode ierr;
1748a71cb68SJakub Kruzik 
1758a71cb68SJakub Kruzik   PetscFunctionBegin;
1768a71cb68SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1778a71cb68SJakub Kruzik   PetscValidLogicalCollectiveScalar(pc,fact,2);
1788a71cb68SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetCorrectionFactor_C",(PC,PetscScalar),(pc,fact));CHKERRQ(ierr);
1798a71cb68SJakub Kruzik   PetscFunctionReturn(0);
1808a71cb68SJakub Kruzik }
1818a71cb68SJakub Kruzik 
18239417d7eSJakub Kruzik static PetscErrorCode PCDeflationSetSpaceToCompute_Deflation(PC pc,PCDeflationSpaceType type,PetscInt size)
18339417d7eSJakub Kruzik {
18439417d7eSJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
18539417d7eSJakub Kruzik 
18639417d7eSJakub Kruzik   PetscFunctionBegin;
18739417d7eSJakub Kruzik   if (type) def->spacetype = type;
18839417d7eSJakub Kruzik   if (size > 0) def->spacesize = size;
18939417d7eSJakub Kruzik   PetscFunctionReturn(0);
19039417d7eSJakub Kruzik }
19139417d7eSJakub Kruzik 
19239417d7eSJakub Kruzik /*@
19339417d7eSJakub Kruzik    PCDeflationSetSpaceToCompute - Set deflation space type and size to compute.
19439417d7eSJakub Kruzik 
195*e26ad46dSJakub Kruzik    Logically Collective
19639417d7eSJakub Kruzik 
19739417d7eSJakub Kruzik    Input Parameters:
19839417d7eSJakub Kruzik +  pc   - the preconditioner context
19939417d7eSJakub Kruzik .  type - deflation space type to compute (or PETSC_IGNORE)
20039417d7eSJakub Kruzik -  size - size of the space to compute (or PETSC_DEFAULT)
20139417d7eSJakub Kruzik 
202*e26ad46dSJakub Kruzik    Options Database Keys:
203*e26ad46dSJakub Kruzik +    -pc_deflation_compute_space      <haar> - compute PCDeflationSpaceType deflation space
204*e26ad46dSJakub Kruzik -    -pc_deflation_compute_space_size <1>    - size of the deflation space
205*e26ad46dSJakub Kruzik 
20639417d7eSJakub Kruzik    Notes:
20739417d7eSJakub Kruzik     For wavelet-based deflation, size represents number of levels.
208*e26ad46dSJakub Kruzik 
20939417d7eSJakub Kruzik     The deflation space is computed in PCSetUP().
21039417d7eSJakub Kruzik 
21139417d7eSJakub Kruzik    Level: intermediate
21239417d7eSJakub Kruzik 
213*e26ad46dSJakub Kruzik .seealso: PCDeflationSetMaxLvl(), PCDEFLATION
21439417d7eSJakub Kruzik @*/
21539417d7eSJakub Kruzik PetscErrorCode PCDeflationSetSpaceToCompute(PC pc,PCDeflationSpaceType type,PetscInt size)
21639417d7eSJakub Kruzik {
21739417d7eSJakub Kruzik   PetscErrorCode ierr;
21839417d7eSJakub Kruzik 
21939417d7eSJakub Kruzik   PetscFunctionBegin;
22039417d7eSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
22139417d7eSJakub Kruzik   if (type) PetscValidLogicalCollectiveEnum(pc,type,2);
22239417d7eSJakub Kruzik   if (size > 0) PetscValidLogicalCollectiveInt(pc,size,3);
22339417d7eSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetSpaceToCompute_C",(PC,PCDeflationSpaceType,PetscInt),(pc,type,size));CHKERRQ(ierr);
22439417d7eSJakub Kruzik   PetscFunctionReturn(0);
22539417d7eSJakub Kruzik }
2268513960bSJakub Kruzik 
227e662bc50SJakub Kruzik static PetscErrorCode PCDeflationSetSpace_Deflation(PC pc,Mat W,PetscBool transpose)
228e662bc50SJakub Kruzik {
229e662bc50SJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
230e662bc50SJakub Kruzik   PetscErrorCode ierr;
231e662bc50SJakub Kruzik 
232e662bc50SJakub Kruzik   PetscFunctionBegin;
233e662bc50SJakub Kruzik   if (transpose) {
234e662bc50SJakub Kruzik     def->Wt = W;
235e662bc50SJakub Kruzik     def->W = NULL;
236e662bc50SJakub Kruzik   } else {
237e662bc50SJakub Kruzik     def->W = W;
238e662bc50SJakub Kruzik   }
239e662bc50SJakub Kruzik   ierr = PetscObjectReference((PetscObject)W);CHKERRQ(ierr);
240e662bc50SJakub Kruzik   PetscFunctionReturn(0);
241e662bc50SJakub Kruzik }
242e662bc50SJakub Kruzik 
243e662bc50SJakub Kruzik /*@
244*e26ad46dSJakub Kruzik    PCDeflationSetSpace - Set the deflation space matrix (or its (hermitian) transpose).
245e662bc50SJakub Kruzik 
246*e26ad46dSJakub Kruzik    Logically Collective
247e662bc50SJakub Kruzik 
248e662bc50SJakub Kruzik    Input Parameters:
249e662bc50SJakub Kruzik +  pc        - the preconditioner context
250e662bc50SJakub Kruzik .  W         - deflation matrix
251*e26ad46dSJakub Kruzik -  transpose - indicates that W is an explicit transpose of the deflation matrix
252*e26ad46dSJakub Kruzik 
253*e26ad46dSJakub Kruzik    Notes:
254*e26ad46dSJakub Kruzik     Setting W as a multipliplicative MATCOMPOSITE enables use of the multilevel
255*e26ad46dSJakub Kruzik     deflation. If W = W0*W1*W2*...*Wn, W0 is taken as the first deflation space and
256*e26ad46dSJakub Kruzik     the coarse problem (W0'*A*W0)^{-1} is again preconditioned by deflation with
257*e26ad46dSJakub Kruzik     W1 as the deflation matrix. This repeats until the maximum level set by
258*e26ad46dSJakub Kruzik     PCDeflationSetMaxLvl is reached or there are no more matrices available.
259*e26ad46dSJakub Kruzik     If there are matrices left after reaching the maximum level,
260*e26ad46dSJakub Kruzik     they are merged into a deflation matrix ...*W{n-1}*Wn.
261e662bc50SJakub Kruzik 
262e662bc50SJakub Kruzik    Level: intermediate
263e662bc50SJakub Kruzik 
264*e26ad46dSJakub Kruzik .seealso: PCDeflationSetMaxLvl(), PCDEFLATION
265e662bc50SJakub Kruzik @*/
266e662bc50SJakub Kruzik PetscErrorCode PCDeflationSetSpace(PC pc,Mat W,PetscBool transpose)
267e662bc50SJakub Kruzik {
268e662bc50SJakub Kruzik   PetscErrorCode ierr;
269e662bc50SJakub Kruzik 
270e662bc50SJakub Kruzik   PetscFunctionBegin;
271e662bc50SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
272e662bc50SJakub Kruzik   PetscValidHeaderSpecific(W,MAT_CLASSID,2);
273e662bc50SJakub Kruzik   PetscValidLogicalCollectiveBool(pc,transpose,3);
274e662bc50SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetSpace_C",(PC,Mat,PetscBool),(pc,W,transpose));CHKERRQ(ierr);
275e662bc50SJakub Kruzik   PetscFunctionReturn(0);
276e662bc50SJakub Kruzik }
277e662bc50SJakub Kruzik 
2783cf3a049SJakub Kruzik static PetscErrorCode PCDeflationSetProjectionNullSpaceMat_Deflation(PC pc,Mat mat)
2793cf3a049SJakub Kruzik {
2803cf3a049SJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
2813cf3a049SJakub Kruzik   PetscErrorCode   ierr;
2823cf3a049SJakub Kruzik 
2833cf3a049SJakub Kruzik   PetscFunctionBegin;
2843cf3a049SJakub Kruzik   ierr = MatDestroy(&def->WtA);CHKERRQ(ierr);
2853cf3a049SJakub Kruzik   def->WtA = mat;
2863cf3a049SJakub Kruzik   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
2873cf3a049SJakub Kruzik   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtA);CHKERRQ(ierr);
2883cf3a049SJakub Kruzik   PetscFunctionReturn(0);
2893cf3a049SJakub Kruzik }
2903cf3a049SJakub Kruzik 
2913cf3a049SJakub Kruzik /*@
292*e26ad46dSJakub Kruzik    PCDeflationSetProjectionNullSpaceMat - Set the projection null space matrix (W'*A).
2933cf3a049SJakub Kruzik 
294*e26ad46dSJakub Kruzik    Collective
2953cf3a049SJakub Kruzik 
2963cf3a049SJakub Kruzik    Input Parameters:
2973cf3a049SJakub Kruzik +  pc  - preconditioner context
2983cf3a049SJakub Kruzik -  mat - projection null space matrix
2993cf3a049SJakub Kruzik 
3003cf3a049SJakub Kruzik    Level: developer
3013cf3a049SJakub Kruzik 
3023cf3a049SJakub Kruzik .seealso: PCDEFLATION
3033cf3a049SJakub Kruzik @*/
3043cf3a049SJakub Kruzik PetscErrorCode  PCDeflationSetProjectionNullSpaceMat(PC pc,Mat mat)
3053cf3a049SJakub Kruzik {
3063cf3a049SJakub Kruzik   PetscErrorCode ierr;
3073cf3a049SJakub Kruzik 
3083cf3a049SJakub Kruzik   PetscFunctionBegin;
3093cf3a049SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
3103cf3a049SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
3113cf3a049SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetProjectionNullSpaceMat_C",(PC,Mat),(pc,mat));CHKERRQ(ierr);
3123cf3a049SJakub Kruzik   PetscFunctionReturn(0);
3133cf3a049SJakub Kruzik }
3143cf3a049SJakub Kruzik 
315e924b002SJakub Kruzik static PetscErrorCode PCDeflationSetCoarseMat_Deflation(PC pc,Mat mat)
316e924b002SJakub Kruzik {
317e924b002SJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
318e924b002SJakub Kruzik   PetscErrorCode   ierr;
319e924b002SJakub Kruzik 
320e924b002SJakub Kruzik   PetscFunctionBegin;
321e924b002SJakub Kruzik   ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr);
322e924b002SJakub Kruzik   def->WtAW = mat;
323e924b002SJakub Kruzik   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
324e924b002SJakub Kruzik   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtAW);CHKERRQ(ierr);
325e924b002SJakub Kruzik   PetscFunctionReturn(0);
326e924b002SJakub Kruzik }
327e924b002SJakub Kruzik 
328e924b002SJakub Kruzik /*@
329*e26ad46dSJakub Kruzik    PCDeflationSetCoarseMat - Set the coarse problem Mat.
330e924b002SJakub Kruzik 
331*e26ad46dSJakub Kruzik    Collective
332e924b002SJakub Kruzik 
333e924b002SJakub Kruzik    Input Parameters:
334e924b002SJakub Kruzik +  pc  - preconditioner context
335e924b002SJakub Kruzik -  mat - coarse problem mat
336e924b002SJakub Kruzik 
337e924b002SJakub Kruzik    Level: developer
338e924b002SJakub Kruzik 
339e924b002SJakub Kruzik .seealso: PCDEFLATION
340e924b002SJakub Kruzik @*/
341e924b002SJakub Kruzik PetscErrorCode  PCDeflationSetCoarseMat(PC pc,Mat mat)
342e924b002SJakub Kruzik {
343e924b002SJakub Kruzik   PetscErrorCode ierr;
344e924b002SJakub Kruzik 
345e924b002SJakub Kruzik   PetscFunctionBegin;
346e924b002SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
347e924b002SJakub Kruzik   PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
348e924b002SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetCoarseMat_C",(PC,Mat),(pc,mat));CHKERRQ(ierr);
349e924b002SJakub Kruzik   PetscFunctionReturn(0);
350e924b002SJakub Kruzik }
351e924b002SJakub Kruzik 
35298d6e3deSJakub Kruzik static PetscErrorCode PCDeflationGetCoarseKSP_Deflation(PC pc,KSP *ksp)
3535c0c31c5SJakub Kruzik {
3545c0c31c5SJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
3555c0c31c5SJakub Kruzik 
3565c0c31c5SJakub Kruzik   PetscFunctionBegin;
35798d6e3deSJakub Kruzik   *ksp = def->WtAWinv;
3585c0c31c5SJakub Kruzik   PetscFunctionReturn(0);
3595c0c31c5SJakub Kruzik }
3605c0c31c5SJakub Kruzik 
3615c0c31c5SJakub Kruzik /*@
36298d6e3deSJakub Kruzik    PCDeflationGetCoarseKSP - Returns a pointer to the coarse problem KSP.
3635c0c31c5SJakub Kruzik 
36498d6e3deSJakub Kruzik    Not Collective
3655c0c31c5SJakub Kruzik 
3665c0c31c5SJakub Kruzik    Input Parameters:
36798d6e3deSJakub Kruzik .  pc - preconditioner context
3685c0c31c5SJakub Kruzik 
369*e26ad46dSJakub Kruzik    Output Parameters:
37098d6e3deSJakub Kruzik .  ksp - coarse problem KSP context
3715c0c31c5SJakub Kruzik 
372*e26ad46dSJakub Kruzik    Level: advanced
37398d6e3deSJakub Kruzik 
37498d6e3deSJakub Kruzik .seealso: PCDeflationSetCoarseKSP(), PCDEFLATION
3755c0c31c5SJakub Kruzik @*/
37698d6e3deSJakub Kruzik PetscErrorCode  PCDeflationGetCoarseKSP(PC pc,KSP *ksp)
3775c0c31c5SJakub Kruzik {
3785c0c31c5SJakub Kruzik   PetscErrorCode ierr;
3795c0c31c5SJakub Kruzik 
3805c0c31c5SJakub Kruzik   PetscFunctionBegin;
38122b0793eSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
38298d6e3deSJakub Kruzik   PetscValidPointer(ksp,2);
38398d6e3deSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationGetCoarseKSP_C",(PC,KSP*),(pc,ksp));CHKERRQ(ierr);
38498d6e3deSJakub Kruzik   PetscFunctionReturn(0);
38598d6e3deSJakub Kruzik }
38698d6e3deSJakub Kruzik 
38798d6e3deSJakub Kruzik static PetscErrorCode PCDeflationSetCoarseKSP_Deflation(PC pc,KSP ksp)
38898d6e3deSJakub Kruzik {
38998d6e3deSJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
39098d6e3deSJakub Kruzik   PetscErrorCode   ierr;
39198d6e3deSJakub Kruzik 
39298d6e3deSJakub Kruzik   PetscFunctionBegin;
39398d6e3deSJakub Kruzik   ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr);
39498d6e3deSJakub Kruzik   def->WtAWinv = ksp;
39598d6e3deSJakub Kruzik   ierr = PetscObjectReference((PetscObject)ksp);CHKERRQ(ierr);
39698d6e3deSJakub Kruzik   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->WtAWinv);CHKERRQ(ierr);
39798d6e3deSJakub Kruzik   PetscFunctionReturn(0);
39898d6e3deSJakub Kruzik }
39998d6e3deSJakub Kruzik 
40098d6e3deSJakub Kruzik /*@
401*e26ad46dSJakub Kruzik    PCDeflationSetCoarseKSP - Set the coarse problem KSP.
40298d6e3deSJakub Kruzik 
403*e26ad46dSJakub Kruzik    Collective
40498d6e3deSJakub Kruzik 
40598d6e3deSJakub Kruzik    Input Parameters:
40698d6e3deSJakub Kruzik +  pc  - preconditioner context
40798d6e3deSJakub Kruzik -  ksp - coarse problem KSP context
40898d6e3deSJakub Kruzik 
40998d6e3deSJakub Kruzik    Level: developer
41098d6e3deSJakub Kruzik 
41198d6e3deSJakub Kruzik .seealso: PCDeflationGetCoarseKSP(), PCDEFLATION
41298d6e3deSJakub Kruzik @*/
41398d6e3deSJakub Kruzik PetscErrorCode  PCDeflationSetCoarseKSP(PC pc,KSP ksp)
41498d6e3deSJakub Kruzik {
41598d6e3deSJakub Kruzik   PetscErrorCode ierr;
41698d6e3deSJakub Kruzik 
41798d6e3deSJakub Kruzik   PetscFunctionBegin;
41898d6e3deSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
41998d6e3deSJakub Kruzik   PetscValidHeaderSpecific(ksp,KSP_CLASSID,2);
42098d6e3deSJakub Kruzik   PetscCheckSameComm(pc,1,ksp,2);
42198d6e3deSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetCoarseKSP_C",(PC,KSP),(pc,ksp));CHKERRQ(ierr);
4225c0c31c5SJakub Kruzik   PetscFunctionReturn(0);
4235c0c31c5SJakub Kruzik }
424e662bc50SJakub Kruzik 
425268c6673SJakub Kruzik static PetscErrorCode PCDeflationGetPC_Deflation(PC pc,PC *apc)
426268c6673SJakub Kruzik {
427268c6673SJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
428268c6673SJakub Kruzik 
429268c6673SJakub Kruzik   PetscFunctionBegin;
430268c6673SJakub Kruzik   *apc = def->pc;
431268c6673SJakub Kruzik   PetscFunctionReturn(0);
432268c6673SJakub Kruzik }
433268c6673SJakub Kruzik 
434268c6673SJakub Kruzik /*@
435*e26ad46dSJakub Kruzik    PCDeflationGetPC - Returns a pointer to the additional preconditioner.
436268c6673SJakub Kruzik 
437268c6673SJakub Kruzik    Not Collective
438268c6673SJakub Kruzik 
439268c6673SJakub Kruzik    Input Parameters:
440268c6673SJakub Kruzik .  pc  - the preconditioner context
441268c6673SJakub Kruzik 
442*e26ad46dSJakub Kruzik    Output Parameters:
443268c6673SJakub Kruzik .  apc - additional preconditioner
444268c6673SJakub Kruzik 
445268c6673SJakub Kruzik    Level: advanced
446268c6673SJakub Kruzik 
447268c6673SJakub Kruzik .seealso: PCDeflationSetPC(), PCDEFLATION
448268c6673SJakub Kruzik @*/
449268c6673SJakub Kruzik PetscErrorCode PCDeflationGetPC(PC pc,PC *apc)
450268c6673SJakub Kruzik {
451268c6673SJakub Kruzik   PetscErrorCode ierr;
452268c6673SJakub Kruzik 
453268c6673SJakub Kruzik   PetscFunctionBegin;
454268c6673SJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
455268c6673SJakub Kruzik   PetscValidPointer(pc,2);
456268c6673SJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationGetPC_C",(PC,PC*),(pc,apc));CHKERRQ(ierr);
457268c6673SJakub Kruzik   PetscFunctionReturn(0);
458268c6673SJakub Kruzik }
459268c6673SJakub Kruzik 
46022b0793eSJakub Kruzik static PetscErrorCode PCDeflationSetPC_Deflation(PC pc,PC apc)
46122b0793eSJakub Kruzik {
46222b0793eSJakub Kruzik   PC_Deflation   *def = (PC_Deflation*)pc->data;
46322b0793eSJakub Kruzik   PetscErrorCode ierr;
46422b0793eSJakub Kruzik 
46522b0793eSJakub Kruzik   PetscFunctionBegin;
46622b0793eSJakub Kruzik   ierr = PCDestroy(&def->pc);CHKERRQ(ierr);
46722b0793eSJakub Kruzik   def->pc = apc;
46822b0793eSJakub Kruzik   ierr = PetscObjectReference((PetscObject)apc);CHKERRQ(ierr);
46922b0793eSJakub Kruzik   ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)def->pc);CHKERRQ(ierr);
47022b0793eSJakub Kruzik   PetscFunctionReturn(0);
47122b0793eSJakub Kruzik }
47222b0793eSJakub Kruzik 
47322b0793eSJakub Kruzik /*@
474*e26ad46dSJakub Kruzik    PCDeflationSetPC - Set the additional preconditioner.
47522b0793eSJakub Kruzik 
476*e26ad46dSJakub Kruzik    Collective
47722b0793eSJakub Kruzik 
47822b0793eSJakub Kruzik    Input Parameters:
47922b0793eSJakub Kruzik +  pc  - the preconditioner context
48022b0793eSJakub Kruzik -  apc - additional preconditioner
48122b0793eSJakub Kruzik 
482268c6673SJakub Kruzik    Level: developer
48322b0793eSJakub Kruzik 
484268c6673SJakub Kruzik .seealso: PCDeflationGetPC(), PCDEFLATION
48522b0793eSJakub Kruzik @*/
48622b0793eSJakub Kruzik PetscErrorCode PCDeflationSetPC(PC pc,PC apc)
48722b0793eSJakub Kruzik {
48822b0793eSJakub Kruzik   PetscErrorCode ierr;
48922b0793eSJakub Kruzik 
49022b0793eSJakub Kruzik   PetscFunctionBegin;
49122b0793eSJakub Kruzik   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
49222b0793eSJakub Kruzik   PetscValidHeaderSpecific(apc,PC_CLASSID,2);
49322b0793eSJakub Kruzik   PetscCheckSameComm(pc,1,apc,2);
49422b0793eSJakub Kruzik   ierr = PetscTryMethod(pc,"PCDeflationSetPC_C",(PC,PC),(pc,apc));CHKERRQ(ierr);
49522b0793eSJakub Kruzik   PetscFunctionReturn(0);
49622b0793eSJakub Kruzik }
49722b0793eSJakub Kruzik 
49837eeb815SJakub Kruzik /*
499b27c8092SJakub Kruzik   x <- x + W*(W'*A*W)^{-1}*W'*r  = x + Q*r
500b27c8092SJakub Kruzik */
501b27c8092SJakub Kruzik static PetscErrorCode PCPreSolve_Deflation(PC pc,KSP ksp,Vec b, Vec x)
502b27c8092SJakub Kruzik {
503b27c8092SJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
504b27c8092SJakub Kruzik   Mat              A;
505b27c8092SJakub Kruzik   Vec              r,w1,w2;
506b27c8092SJakub Kruzik   PetscBool        nonzero;
507b27c8092SJakub Kruzik   PetscErrorCode   ierr;
50837eeb815SJakub Kruzik 
509b27c8092SJakub Kruzik   PetscFunctionBegin;
510b27c8092SJakub Kruzik   w1 = def->workcoarse[0];
511b27c8092SJakub Kruzik   w2 = def->workcoarse[1];
512b27c8092SJakub Kruzik   r  = def->work;
513b27c8092SJakub Kruzik   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
51437eeb815SJakub Kruzik 
515b27c8092SJakub Kruzik   ierr = KSPGetInitialGuessNonzero(ksp,&nonzero);CHKERRQ(ierr);
516b27c8092SJakub Kruzik   ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
517b27c8092SJakub Kruzik   if (nonzero) {
518b27c8092SJakub Kruzik     ierr = MatMult(A,x,r);CHKERRQ(ierr);                          /*    r  <- b - Ax              */
519b27c8092SJakub Kruzik     ierr = VecAYPX(r,-1.0,b);CHKERRQ(ierr);
520b27c8092SJakub Kruzik   } else {
521b27c8092SJakub Kruzik     ierr = VecCopy(b,r);CHKERRQ(ierr);                            /*    r  <- b (x is 0)          */
522b27c8092SJakub Kruzik   }
523b27c8092SJakub Kruzik 
524a3177931SJakub Kruzik   if (def->Wt) {
525a3177931SJakub Kruzik     ierr = MatMult(def->Wt,r,w1);CHKERRQ(ierr);                   /*    w1 <- W'*r                */
526a3177931SJakub Kruzik   } else {
527a3177931SJakub Kruzik     ierr = MatMultHermitianTranspose(def->W,r,w1);CHKERRQ(ierr);  /*    w1 <- W'*r                */
528a3177931SJakub Kruzik   }
529b27c8092SJakub Kruzik   ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);              /*    w2 <- (W'*A*W)^{-1}*w1    */
530b27c8092SJakub Kruzik   ierr = MatMult(def->W,w2,r);CHKERRQ(ierr);                      /*    r  <- W*w2                */
531b27c8092SJakub Kruzik   ierr = VecAYPX(x,1.0,r);CHKERRQ(ierr);
532b27c8092SJakub Kruzik   PetscFunctionReturn(0);
533b27c8092SJakub Kruzik }
53437eeb815SJakub Kruzik 
535f8bf229cSJakub Kruzik /*
536f8bf229cSJakub Kruzik   if (def->correct) {
537ae029463SJakub Kruzik     z <- M^{-1}r - W*(W'*A*W)^{-1}*(W'*A*M^{-1}r - l*W'*r) = (P*M^{-1} + l*Q)*r
538f8bf229cSJakub Kruzik   } else {
539ae029463SJakub Kruzik     z <- M^{-1}*r - W*(W'*A*W)^{-1}*W'*A*M{-1}*r = P*M^{-1}*r
540f8bf229cSJakub Kruzik   }
54137eeb815SJakub Kruzik */
542f8bf229cSJakub Kruzik static PetscErrorCode PCApply_Deflation(PC pc,Vec r,Vec z)
543f8bf229cSJakub Kruzik {
544f8bf229cSJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
545f8bf229cSJakub Kruzik   Mat              A;
546f8bf229cSJakub Kruzik   Vec              u,w1,w2;
547f8bf229cSJakub Kruzik   PetscErrorCode   ierr;
548f8bf229cSJakub Kruzik 
549f8bf229cSJakub Kruzik   PetscFunctionBegin;
550f8bf229cSJakub Kruzik   w1 = def->workcoarse[0];
551f8bf229cSJakub Kruzik   w2 = def->workcoarse[1];
552f8bf229cSJakub Kruzik   u  = def->work;
553f8bf229cSJakub Kruzik   ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr);
554f8bf229cSJakub Kruzik 
555ae029463SJakub Kruzik   ierr = PCApply(def->pc,r,z);CHKERRQ(ierr);                          /*    z <- M^{-1}*r             */
55622b0793eSJakub Kruzik   if (!def->init) {
557ae029463SJakub Kruzik     ierr = MatMult(def->WtA,z,w1);CHKERRQ(ierr);                      /*    w1 <- W'*A*z              */
558f8bf229cSJakub Kruzik     if (def->correct) {
559ae029463SJakub Kruzik       if (def->Wt) {
560ae029463SJakub Kruzik         ierr = MatMult(def->Wt,r,w2);CHKERRQ(ierr);                   /*    w2 <- W'*r                */
561ae029463SJakub Kruzik       } else {
562a3177931SJakub Kruzik         ierr = MatMultHermitianTranspose(def->W,r,w2);CHKERRQ(ierr);  /*    w2 <- W'*r                */
563f8bf229cSJakub Kruzik       }
564ae029463SJakub Kruzik       ierr = VecAXPY(w1,-1.0*def->correctfact,w2);CHKERRQ(ierr);      /*    w1 <- w1 - l*w2           */
565f8bf229cSJakub Kruzik     }
566f8bf229cSJakub Kruzik     ierr = KSPSolve(def->WtAWinv,w1,w2);CHKERRQ(ierr);                /*    w2 <- (W'*A*W)^{-1}*w1    */
567f8bf229cSJakub Kruzik     ierr = MatMult(def->W,w2,u);CHKERRQ(ierr);                        /*    u  <- W*w2                */
56822b0793eSJakub Kruzik     ierr = VecAXPY(z,-1.0,u);CHKERRQ(ierr);                           /*    z  <- z - u               */
56922b0793eSJakub Kruzik   }
570f8bf229cSJakub Kruzik   PetscFunctionReturn(0);
571f8bf229cSJakub Kruzik }
572f8bf229cSJakub Kruzik 
57337eeb815SJakub Kruzik static PetscErrorCode PCSetUp_Deflation(PC pc)
57437eeb815SJakub Kruzik {
575409a357bSJakub Kruzik   PC_Deflation     *def = (PC_Deflation*)pc->data;
576409a357bSJakub Kruzik   KSP              innerksp;
577409a357bSJakub Kruzik   PC               pcinner;
578409a357bSJakub Kruzik   Mat              Amat,nextDef=NULL,*mats;
579409a357bSJakub Kruzik   PetscInt         i,m,red,size,commsize;
580409a357bSJakub Kruzik   PetscBool        match,flgspd,transp=PETSC_FALSE;
581409a357bSJakub Kruzik   MatCompositeType ctype;
582409a357bSJakub Kruzik   MPI_Comm         comm;
583409a357bSJakub Kruzik   const char       *prefix;
58437eeb815SJakub Kruzik   PetscErrorCode   ierr;
58537eeb815SJakub Kruzik 
58637eeb815SJakub Kruzik   PetscFunctionBegin;
587409a357bSJakub Kruzik   if (pc->setupcalled) PetscFunctionReturn(0);
588409a357bSJakub Kruzik   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
589f8bf229cSJakub Kruzik   ierr = PCGetOperators(pc,NULL,&Amat);CHKERRQ(ierr);
5900a78af22SJakub Kruzik   ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
591f8bf229cSJakub Kruzik 
592f8bf229cSJakub Kruzik   /* compute a deflation space */
593409a357bSJakub Kruzik   if (def->W || def->Wt) {
594409a357bSJakub Kruzik     def->spacetype = PC_DEFLATION_SPACE_USER;
595409a357bSJakub Kruzik   } else {
596e53e0a0dSJakub Kruzik     ierr = PCDeflationComputeSpace(pc);CHKERRQ(ierr);
59737eeb815SJakub Kruzik   }
59837eeb815SJakub Kruzik 
599409a357bSJakub Kruzik   /* nested deflation */
600409a357bSJakub Kruzik   if (def->W) {
601409a357bSJakub Kruzik     ierr = PetscObjectTypeCompare((PetscObject)def->W,MATCOMPOSITE,&match);CHKERRQ(ierr);
602409a357bSJakub Kruzik     if (match) {
603409a357bSJakub Kruzik       ierr = MatCompositeGetType(def->W,&ctype);CHKERRQ(ierr);
604409a357bSJakub Kruzik       ierr = MatCompositeGetNumberMat(def->W,&size);CHKERRQ(ierr);
60537eeb815SJakub Kruzik     }
606409a357bSJakub Kruzik   } else {
607a3177931SJakub Kruzik     ierr = MatCreateHermitianTranspose(def->Wt,&def->W);CHKERRQ(ierr);
608409a357bSJakub Kruzik     ierr = PetscObjectTypeCompare((PetscObject)def->Wt,MATCOMPOSITE,&match);CHKERRQ(ierr);
609409a357bSJakub Kruzik     if (match) {
610409a357bSJakub Kruzik       ierr = MatCompositeGetType(def->Wt,&ctype);CHKERRQ(ierr);
611409a357bSJakub Kruzik       ierr = MatCompositeGetNumberMat(def->Wt,&size);CHKERRQ(ierr);
612409a357bSJakub Kruzik     }
613409a357bSJakub Kruzik     transp = PETSC_TRUE;
614409a357bSJakub Kruzik   }
615409a357bSJakub Kruzik   if (match && ctype == MAT_COMPOSITE_MULTIPLICATIVE) {
616409a357bSJakub Kruzik     if (!transp) {
61728da0170SJakub Kruzik       if (def->nestedlvl < def->maxnestedlvl) {
61828da0170SJakub Kruzik         ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
619409a357bSJakub Kruzik         for (i=0; i<size; i++) {
620409a357bSJakub Kruzik           ierr = MatCompositeGetMat(def->W,i,&mats[i]);CHKERRQ(ierr);
621409a357bSJakub Kruzik         }
622409a357bSJakub Kruzik         size -= 1;
623409a357bSJakub Kruzik         ierr = MatDestroy(&def->W);CHKERRQ(ierr);
624409a357bSJakub Kruzik         def->W = mats[size];
625409a357bSJakub Kruzik         ierr = PetscObjectReference((PetscObject)mats[size]);CHKERRQ(ierr);
626409a357bSJakub Kruzik         if (size > 1) {
627409a357bSJakub Kruzik           ierr = MatCreateComposite(comm,size,mats,&nextDef);CHKERRQ(ierr);
628409a357bSJakub Kruzik           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
629409a357bSJakub Kruzik         } else {
630409a357bSJakub Kruzik           nextDef = mats[0];
631409a357bSJakub Kruzik           ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
632409a357bSJakub Kruzik         }
63328da0170SJakub Kruzik         ierr = PetscFree(mats);CHKERRQ(ierr);
634409a357bSJakub Kruzik       } else {
635409a357bSJakub Kruzik         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
636409a357bSJakub Kruzik         ierr = MatCompositeMerge(def->W);CHKERRQ(ierr);
637409a357bSJakub Kruzik       }
63828da0170SJakub Kruzik     } else {
63928da0170SJakub Kruzik       if (def->nestedlvl < def->maxnestedlvl) {
64028da0170SJakub Kruzik         ierr = PetscMalloc1(size,&mats);CHKERRQ(ierr);
64128da0170SJakub Kruzik         for (i=0; i<size; i++) {
64228da0170SJakub Kruzik           ierr = MatCompositeGetMat(def->Wt,i,&mats[i]);CHKERRQ(ierr);
64328da0170SJakub Kruzik         }
64428da0170SJakub Kruzik         size -= 1;
64528da0170SJakub Kruzik         ierr = MatDestroy(&def->Wt);CHKERRQ(ierr);
64628da0170SJakub Kruzik         def->Wt = mats[0];
64728da0170SJakub Kruzik         ierr = PetscObjectReference((PetscObject)mats[0]);CHKERRQ(ierr);
64828da0170SJakub Kruzik         if (size > 1) {
64928da0170SJakub Kruzik           ierr = MatCreateComposite(comm,size,&mats[1],&nextDef);CHKERRQ(ierr);
65028da0170SJakub Kruzik           ierr = MatCompositeSetType(nextDef,MAT_COMPOSITE_MULTIPLICATIVE);CHKERRQ(ierr);
65128da0170SJakub Kruzik         } else {
65228da0170SJakub Kruzik           nextDef = mats[1];
65328da0170SJakub Kruzik           ierr = PetscObjectReference((PetscObject)mats[1]);CHKERRQ(ierr);
654409a357bSJakub Kruzik         }
655409a357bSJakub Kruzik         ierr = PetscFree(mats);CHKERRQ(ierr);
65628da0170SJakub Kruzik       } else {
65728da0170SJakub Kruzik         /* ierr = MatCompositeSetMergeType(def->W,MAT_COMPOSITE_MERGE_LEFT);CHKERRQ(ierr); */
65828da0170SJakub Kruzik         ierr = MatCompositeMerge(def->Wt);CHKERRQ(ierr);
65928da0170SJakub Kruzik       }
66028da0170SJakub Kruzik     }
66128da0170SJakub Kruzik   }
66228da0170SJakub Kruzik 
66328da0170SJakub Kruzik   if (transp) {
66428da0170SJakub Kruzik     ierr = MatDestroy(&def->W);CHKERRQ(ierr);
665a3177931SJakub Kruzik     ierr = MatHermitianTranspose(def->Wt,MAT_INITIAL_MATRIX,&def->W);CHKERRQ(ierr);
666409a357bSJakub Kruzik   }
667409a357bSJakub Kruzik 
668ae029463SJakub Kruzik   /* assemble WtA */
669ae029463SJakub Kruzik   if (!def->WtA) {
670ae029463SJakub Kruzik     if (def->Wt) {
671ae029463SJakub Kruzik       ierr = MatMatMult(def->Wt,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr);
672ae029463SJakub Kruzik     } else {
673a3177931SJakub Kruzik #if defined(PETSC_USE_COMPLEX)
674a3177931SJakub Kruzik       ierr = MatHermitianTranspose(def->W,MAT_INITIAL_MATRIX,&def->Wt);CHKERRQ(ierr);
675a3177931SJakub Kruzik       ierr = MatMatMult(def->W,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr);
676a3177931SJakub Kruzik #else
677ae029463SJakub Kruzik       ierr = MatTransposeMatMult(def->W,Amat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtA);CHKERRQ(ierr);
678a3177931SJakub Kruzik #endif
679ae029463SJakub Kruzik     }
680ae029463SJakub Kruzik   }
681409a357bSJakub Kruzik   /* setup coarse problem */
682409a357bSJakub Kruzik   if (!def->WtAWinv) {
68328da0170SJakub Kruzik     ierr = MatGetSize(def->W,NULL,&m);CHKERRQ(ierr);
684409a357bSJakub Kruzik     if (!def->WtAW) {
685ae029463SJakub Kruzik       ierr = MatMatMult(def->WtA,def->W,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&def->WtAW);CHKERRQ(ierr);
686409a357bSJakub Kruzik       /* TODO create MatInheritOption(Mat,MatOption) */
687409a357bSJakub Kruzik       ierr = MatGetOption(Amat,MAT_SPD,&flgspd);CHKERRQ(ierr);
688409a357bSJakub Kruzik       ierr = MatSetOption(def->WtAW,MAT_SPD,flgspd);CHKERRQ(ierr);
689409a357bSJakub Kruzik #if defined(PETSC_USE_DEBUG)
690ae029463SJakub Kruzik       /* Check columns of W are not in kernel of A */
691409a357bSJakub Kruzik       PetscReal *norms;
692409a357bSJakub Kruzik       ierr = PetscMalloc1(m,&norms);CHKERRQ(ierr);
693409a357bSJakub Kruzik       ierr = MatGetColumnNorms(def->WtAW,NORM_INFINITY,norms);CHKERRQ(ierr);
694409a357bSJakub Kruzik       for (i=0; i<m; i++) {
695409a357bSJakub Kruzik         if (norms[i] < 100*PETSC_MACHINE_EPSILON) {
696409a357bSJakub Kruzik           SETERRQ1(comm,PETSC_ERR_SUP,"Column %D of W is in kernel of A.",i);
697409a357bSJakub Kruzik         }
698409a357bSJakub Kruzik       }
699409a357bSJakub Kruzik       ierr = PetscFree(norms);CHKERRQ(ierr);
700409a357bSJakub Kruzik #endif
701409a357bSJakub Kruzik     } else {
702409a357bSJakub Kruzik       ierr = MatGetOption(def->WtAW,MAT_SPD,&flgspd);CHKERRQ(ierr);
703409a357bSJakub Kruzik     }
704409a357bSJakub Kruzik     /* TODO use MATINV */
705409a357bSJakub Kruzik     ierr = KSPCreate(comm,&def->WtAWinv);CHKERRQ(ierr);
706409a357bSJakub Kruzik     ierr = KSPSetOperators(def->WtAWinv,def->WtAW,def->WtAW);CHKERRQ(ierr);
707409a357bSJakub Kruzik     ierr = KSPGetPC(def->WtAWinv,&pcinner);CHKERRQ(ierr);
708557a2f7dSJakub Kruzik     /* Setup KSP and PC */
709557a2f7dSJakub Kruzik     if (nextDef) { /* next level for multilevel deflation */
710557a2f7dSJakub Kruzik       innerksp = def->WtAWinv;
711557a2f7dSJakub Kruzik       /* set default KSPtype */
712557a2f7dSJakub Kruzik       if (!def->ksptype) {
713557a2f7dSJakub Kruzik         def->ksptype = KSPFGMRES;
714557a2f7dSJakub Kruzik         if (flgspd) { /* SPD system */
715557a2f7dSJakub Kruzik           def->ksptype = KSPFCG;
716557a2f7dSJakub Kruzik         }
717557a2f7dSJakub Kruzik       }
718ae029463SJakub Kruzik       ierr = KSPSetType(innerksp,def->ksptype);CHKERRQ(ierr); /* TODO iherit from KSP + tolerances */
719557a2f7dSJakub Kruzik       ierr = PCSetType(pcinner,PCDEFLATION);CHKERRQ(ierr); /* TODO create coarse preconditinoner M_c = WtMW ? */
720557a2f7dSJakub Kruzik       ierr = PCDeflationSetSpace(pcinner,nextDef,transp);CHKERRQ(ierr);
721557a2f7dSJakub Kruzik       ierr = PCDeflationSetLvl_Deflation(pcinner,def->nestedlvl+1,def->maxnestedlvl);CHKERRQ(ierr);
722ae029463SJakub Kruzik       /* inherit options */
723557a2f7dSJakub Kruzik       ((PC_Deflation*)(pcinner->data))->ksptype = def->ksptype;
724557a2f7dSJakub Kruzik       ((PC_Deflation*)(pcinner->data))->correct = def->correct;
725557a2f7dSJakub Kruzik       ierr = MatDestroy(&nextDef);CHKERRQ(ierr);
726557a2f7dSJakub Kruzik     } else { /* the last level */
727557a2f7dSJakub Kruzik       ierr = KSPSetType(def->WtAWinv,KSPPREONLY);CHKERRQ(ierr);
728409a357bSJakub Kruzik       ierr = PCSetType(pcinner,PCTELESCOPE);CHKERRQ(ierr);
729ac66f006SJakub Kruzik       /* ugly hack to not have overwritten PCTELESCOPE */
730ac66f006SJakub Kruzik       if (prefix) {
731ac66f006SJakub Kruzik         ierr = KSPSetOptionsPrefix(def->WtAWinv,prefix);CHKERRQ(ierr);
732ac66f006SJakub Kruzik       }
73322b0793eSJakub Kruzik       ierr = KSPAppendOptionsPrefix(def->WtAWinv,"tel_");CHKERRQ(ierr);
734ac66f006SJakub Kruzik       ierr = PCSetFromOptions(pcinner);CHKERRQ(ierr);
735409a357bSJakub Kruzik       /* Reduction factor choice */
736409a357bSJakub Kruzik       red = def->reductionfact;
737409a357bSJakub Kruzik       if (red < 0) {
738409a357bSJakub Kruzik         ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
739409a357bSJakub Kruzik         red  = ceil((float)commsize/ceil((float)m/commsize));
740409a357bSJakub Kruzik         ierr = PetscObjectTypeCompareAny((PetscObject)(def->WtAW),&match,MATSEQDENSE,MATMPIDENSE,MATDENSE,"");CHKERRQ(ierr);
741409a357bSJakub Kruzik         if (match) red = commsize;
742409a357bSJakub Kruzik         ierr = PetscInfo1(pc,"Auto choosing reduction factor %D\n",red);CHKERRQ(ierr); /* TODO add level? */
743409a357bSJakub Kruzik       }
744409a357bSJakub Kruzik       ierr = PCTelescopeSetReductionFactor(pcinner,red);CHKERRQ(ierr);
745ac66f006SJakub Kruzik       ierr = PCSetUp(pcinner);CHKERRQ(ierr);
746409a357bSJakub Kruzik       ierr = PCTelescopeGetKSP(pcinner,&innerksp);CHKERRQ(ierr);
747ac66f006SJakub Kruzik       if (innerksp) {
748409a357bSJakub Kruzik         ierr = KSPGetPC(innerksp,&pcinner);CHKERRQ(ierr);
749409a357bSJakub Kruzik         /* TODO Cholesky if flgspd? */
750ac66f006SJakub Kruzik         ierr = PCSetType(pcinner,PCLU);CHKERRQ(ierr);
751409a357bSJakub Kruzik         //TODO remove explicit matSolverPackage
752409a357bSJakub Kruzik         if (commsize == red) {
753ac66f006SJakub Kruzik           ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU);CHKERRQ(ierr);
754409a357bSJakub Kruzik         } else {
755ac66f006SJakub Kruzik           ierr = PCFactorSetMatSolverType(pcinner,MATSOLVERSUPERLU_DIST);CHKERRQ(ierr);
756409a357bSJakub Kruzik         }
757409a357bSJakub Kruzik       }
758557a2f7dSJakub Kruzik     }
759557a2f7dSJakub Kruzik 
760557a2f7dSJakub Kruzik     if (innerksp) {
761409a357bSJakub Kruzik       /* TODO use def_[lvl]_ if lvl > 0? */
762409a357bSJakub Kruzik       if (prefix) {
763409a357bSJakub Kruzik         ierr = KSPSetOptionsPrefix(innerksp,prefix);CHKERRQ(ierr);
764409a357bSJakub Kruzik       }
76522b0793eSJakub Kruzik       ierr = KSPAppendOptionsPrefix(innerksp,"def_");CHKERRQ(ierr);
766557a2f7dSJakub Kruzik       ierr = KSPSetFromOptions(innerksp);CHKERRQ(ierr);
767557a2f7dSJakub Kruzik       ierr = KSPSetUp(innerksp);CHKERRQ(ierr);
768ac66f006SJakub Kruzik     }
769409a357bSJakub Kruzik   }
770557a2f7dSJakub Kruzik   ierr = KSPSetFromOptions(def->WtAWinv);CHKERRQ(ierr);
771557a2f7dSJakub Kruzik   ierr = KSPSetUp(def->WtAWinv);CHKERRQ(ierr);
772409a357bSJakub Kruzik 
77322b0793eSJakub Kruzik   if (!def->pc) {
77422b0793eSJakub Kruzik     ierr = PCCreate(comm,&def->pc);CHKERRQ(ierr);
77522b0793eSJakub Kruzik     ierr = PCSetOperators(def->pc,Amat,Amat);CHKERRQ(ierr);
77622b0793eSJakub Kruzik     ierr = PCSetType(def->pc,PCNONE);CHKERRQ(ierr);
77722b0793eSJakub Kruzik     if (prefix) {
77822b0793eSJakub Kruzik       ierr = PCSetOptionsPrefix(def->pc,prefix);CHKERRQ(ierr);
77922b0793eSJakub Kruzik     }
78022b0793eSJakub Kruzik     ierr = PCAppendOptionsPrefix(def->pc,"def_pc_");CHKERRQ(ierr);
78122b0793eSJakub Kruzik     ierr = PCSetFromOptions(def->pc);CHKERRQ(ierr);
78222b0793eSJakub Kruzik     ierr = PCSetUp(def->pc);CHKERRQ(ierr);
78322b0793eSJakub Kruzik   }
78422b0793eSJakub Kruzik 
785f8bf229cSJakub Kruzik   /* create work vecs */
786f8bf229cSJakub Kruzik   ierr = MatCreateVecs(Amat,NULL,&def->work);CHKERRQ(ierr);
787f8bf229cSJakub Kruzik   ierr = KSPCreateVecs(def->WtAWinv,2,&def->workcoarse,0,NULL);CHKERRQ(ierr);
78837eeb815SJakub Kruzik   PetscFunctionReturn(0);
78937eeb815SJakub Kruzik }
790b30d4775SJakub Kruzik 
79137eeb815SJakub Kruzik static PetscErrorCode PCReset_Deflation(PC pc)
79237eeb815SJakub Kruzik {
793b30d4775SJakub Kruzik   PC_Deflation      *def = (PC_Deflation*)pc->data;
79437eeb815SJakub Kruzik   PetscErrorCode    ierr;
79537eeb815SJakub Kruzik 
79637eeb815SJakub Kruzik   PetscFunctionBegin;
797b30d4775SJakub Kruzik   ierr = VecDestroy(&def->work);CHKERRQ(ierr);
798b30d4775SJakub Kruzik   ierr = VecDestroyVecs(2,&def->workcoarse);CHKERRQ(ierr);
799b30d4775SJakub Kruzik   ierr = MatDestroy(&def->W);CHKERRQ(ierr);
800b30d4775SJakub Kruzik   ierr = MatDestroy(&def->Wt);CHKERRQ(ierr);
801ae029463SJakub Kruzik   ierr = MatDestroy(&def->WtA);CHKERRQ(ierr);
802b30d4775SJakub Kruzik   ierr = MatDestroy(&def->WtAW);CHKERRQ(ierr);
803b30d4775SJakub Kruzik   ierr = KSPDestroy(&def->WtAWinv);CHKERRQ(ierr);
80422b0793eSJakub Kruzik   ierr = PCDestroy(&def->pc);CHKERRQ(ierr);
80537eeb815SJakub Kruzik   PetscFunctionReturn(0);
80637eeb815SJakub Kruzik }
80737eeb815SJakub Kruzik 
80837eeb815SJakub Kruzik static PetscErrorCode PCDestroy_Deflation(PC pc)
80937eeb815SJakub Kruzik {
81037eeb815SJakub Kruzik   PetscErrorCode ierr;
81137eeb815SJakub Kruzik 
81237eeb815SJakub Kruzik   PetscFunctionBegin;
81337eeb815SJakub Kruzik   ierr = PCReset_Deflation(pc);CHKERRQ(ierr);
81437eeb815SJakub Kruzik   ierr = PetscFree(pc->data);CHKERRQ(ierr);
81537eeb815SJakub Kruzik   PetscFunctionReturn(0);
81637eeb815SJakub Kruzik }
81737eeb815SJakub Kruzik 
8188513960bSJakub Kruzik static PetscErrorCode PCView_Deflation(PC pc,PetscViewer viewer)
8198513960bSJakub Kruzik {
8208513960bSJakub Kruzik   PC_Deflation      *def = (PC_Deflation*)pc->data;
8211ac6250aSJakub Kruzik   PetscInt          its;
8228513960bSJakub Kruzik   PetscBool         iascii;
8238513960bSJakub Kruzik   PetscErrorCode    ierr;
8248513960bSJakub Kruzik 
8258513960bSJakub Kruzik   PetscFunctionBegin;
8268513960bSJakub Kruzik   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
8278513960bSJakub Kruzik   if (iascii) {
8288513960bSJakub Kruzik     if (def->correct) {
8291ac6250aSJakub Kruzik       ierr = PetscViewerASCIIPrintf(viewer,"using CP correction, factor = %g+%gi\n",
8301ac6250aSJakub Kruzik                                     (double)PetscRealPart(def->correctfact),
8311ac6250aSJakub Kruzik                                     (double)PetscImaginaryPart(def->correctfact));CHKERRQ(ierr);
8328513960bSJakub Kruzik     }
8338513960bSJakub Kruzik     if (!def->nestedlvl) {
8341ac6250aSJakub Kruzik       ierr = PetscViewerASCIIPrintf(viewer,"deflation space type: %s\n",PCDeflationSpaceTypes[def->spacetype]);CHKERRQ(ierr);
8358513960bSJakub Kruzik     }
8368513960bSJakub Kruzik 
8371ac6250aSJakub Kruzik     ierr = PetscViewerASCIIPrintf(viewer,"--- Additional PC:\n");CHKERRQ(ierr);
83822b0793eSJakub Kruzik     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
83922b0793eSJakub Kruzik     ierr = PCView(def->pc,viewer);CHKERRQ(ierr);
84022b0793eSJakub Kruzik     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
84122b0793eSJakub Kruzik 
8421ac6250aSJakub Kruzik     ierr = PetscViewerASCIIPrintf(viewer,"--- Coarse problem solver:\n");CHKERRQ(ierr);
8438513960bSJakub Kruzik     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
8441ac6250aSJakub Kruzik     ierr = KSPGetTotalIterations(def->WtAWinv,&its);CHKERRQ(ierr);
8451ac6250aSJakub Kruzik     ierr = PetscViewerASCIIPrintf(viewer,"total number of iterations: %D\n",its);CHKERRQ(ierr);
8468513960bSJakub Kruzik     ierr = KSPView(def->WtAWinv,viewer);CHKERRQ(ierr);
8478513960bSJakub Kruzik     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
8488513960bSJakub Kruzik   }
8498513960bSJakub Kruzik   PetscFunctionReturn(0);
8508513960bSJakub Kruzik }
8518513960bSJakub Kruzik 
85237eeb815SJakub Kruzik static PetscErrorCode PCSetFromOptions_Deflation(PetscOptionItems *PetscOptionsObject,PC pc)
85337eeb815SJakub Kruzik {
854880d05ceSJakub Kruzik   PC_Deflation      *def = (PC_Deflation*)pc->data;
85537eeb815SJakub Kruzik   PetscErrorCode    ierr;
85637eeb815SJakub Kruzik 
85737eeb815SJakub Kruzik   PetscFunctionBegin;
85837eeb815SJakub Kruzik   ierr = PetscOptionsHead(PetscOptionsObject,"Deflation options");CHKERRQ(ierr);
859a122ebaeSJakub Kruzik   ierr = PetscOptionsBool("-pc_deflation_init_only","Use only initialization step - Initdef","PCDeflationSetInitOnly",def->init,&def->init,NULL);CHKERRQ(ierr);
860859a873cSJakub Kruzik   ierr = PetscOptionsInt("-pc_deflation_max_lvl","Maximum of deflation levels","PCDeflationSetMaxLvl",def->maxnestedlvl,&def->maxnestedlvl,NULL);CHKERRQ(ierr);
861859a873cSJakub Kruzik   ierr = PetscOptionsInt("-pc_deflation_reduction_factor","Reduction factor for coarse problem solution using PCTELESCOPE","PCDeflationSetReductionFactor",def->reductionfact,&def->reductionfact,NULL);CHKERRQ(ierr);
8628a71cb68SJakub Kruzik   ierr = PetscOptionsBool("-pc_deflation_correction","Add coarse problem correction Q to P","PCDeflationSetCorrectionFactor",def->correct,&def->correct,NULL);CHKERRQ(ierr);
8638a71cb68SJakub Kruzik   ierr = PetscOptionsScalar("-pc_deflation_correction_factor","Set multiple of Q to use as coarse problem correction","PCDeflationSetCorrectionFactor",def->correctfact,&def->correctfact,NULL);CHKERRQ(ierr);
864880d05ceSJakub Kruzik   ierr = PetscOptionsEnum("-pc_deflation_compute_space","Compute deflation space","PCDeflationSetSpace",PCDeflationSpaceTypes,(PetscEnum)def->spacetype,(PetscEnum*)&def->spacetype,NULL);CHKERRQ(ierr);
865880d05ceSJakub Kruzik   ierr = PetscOptionsInt("-pc_deflation_compute_space_size","Set size of the deflation space to compute","PCDeflationSetSpace",def->spacesize,&def->spacesize,NULL);CHKERRQ(ierr);
866880d05ceSJakub Kruzik   ierr = PetscOptionsBool("-pc_deflation_space_extend","Extend deflation space instead of truncating (wavelets)","PCDeflation",def->extendsp,&def->extendsp,NULL);CHKERRQ(ierr);
867880d05ceSJakub Kruzik //TODO add set function and fix manpages
86837eeb815SJakub Kruzik   ierr = PetscOptionsTail();CHKERRQ(ierr);
86937eeb815SJakub Kruzik   PetscFunctionReturn(0);
87037eeb815SJakub Kruzik }
87137eeb815SJakub Kruzik 
87237eeb815SJakub Kruzik /*MC
873*e26ad46dSJakub Kruzik    PCDEFLATION - Deflation preconditioner shifts (deflates) part of the spectrum to zero or to a predefined value.
87437eeb815SJakub Kruzik 
875*e26ad46dSJakub Kruzik    Options Database Keys:
876*e26ad46dSJakub Kruzik +    -pc_deflation_init_only          <false> - if true computes only the special guess
877*e26ad46dSJakub Kruzik .    -pc_deflation_max_lvl            <0>     - maximum number of levels for multilevel deflation
878*e26ad46dSJakub Kruzik .    -pc_deflation_reduction_factor   <-1>    - reduction factor on bottom level coarse problem for PCTELESCOPE (default based on the size of the coarse problem)
879*e26ad46dSJakub Kruzik .    -pc_deflation_correction         <false> - if true apply coarse problem correction
880*e26ad46dSJakub Kruzik .    -pc_deflation_correction_factor  <1.0>   - sets coarse problem correction factor
881*e26ad46dSJakub Kruzik .    -pc_deflation_compute_space      <haar>  - compute PCDeflationSpaceType deflation space
882*e26ad46dSJakub Kruzik -    -pc_deflation_compute_space_size <1>     - size of the deflation space (corresponds to number of levels for wavelet-based deflation)
88337eeb815SJakub Kruzik 
88437eeb815SJakub Kruzik    Notes:
885*e26ad46dSJakub Kruzik     Given a (complex - transpose is always hermitian) full rank deflation matrix W, the deflation (introduced in [1,2])
886*e26ad46dSJakub Kruzik     preconditioner uses projections Q = W*(W'*A*W)^{-1}*W' and P = I - Q*A, where A is pmat.
887*e26ad46dSJakub Kruzik 
888*e26ad46dSJakub Kruzik     The deflation computes initial guess x0 = x_{-1} - Q*r_{-1}, which is the solution on the deflation space.
889*e26ad46dSJakub Kruzik     If PCDeflationSetInitOnly() or -pc_deflation_init_only is set to PETSC_TRUE (InitDef scheme), the application of the
890*e26ad46dSJakub Kruzik     preconditioner consists only of application of the additional preconditioner M^{-1}. Otherwise, the preconditioner
891*e26ad46dSJakub Kruzik     application consists of P*M{-1} + factor*Q. The first part of the preconditioner (PM^{-1}) shifts some eigenvalues
892*e26ad46dSJakub Kruzik     to zero while the addition of the coarse problem correction (factor*Q) makes the preconditioner to shift some
893*e26ad46dSJakub Kruzik     eigenvalues to the given factor. The InitDef scheme is recommended for deflation using high accuracy estimates
894*e26ad46dSJakub Kruzik     of eigenvectors of A when it exhibits similar convergence to the full deflation but is cheaper.
895*e26ad46dSJakub Kruzik 
896*e26ad46dSJakub Kruzik     The deflation matrix is by default automatically computed. The type of deflation matrix and its size to compute can
897*e26ad46dSJakub Kruzik     be controlled by PCDeflationSetSpaceToCompute() or -pc_deflation_compute_space and -pc_deflation_compute_space_size.
898*e26ad46dSJakub Kruzik     User can set an arbitrary deflation space matrix with PCDeflationSetSpace(). If the deflation matrix
899*e26ad46dSJakub Kruzik     is a multiplicative MATCOMPOSITE, a multilevel deflation [3] is used. The first matrix in the composite is used as the
900*e26ad46dSJakub Kruzik     deflation matrix, and the coarse problem (W'*A*W)^{-1} is solved by FCG (if A is MAT_SPD) or FGMRES preconditioned
901*e26ad46dSJakub Kruzik     by deflation with deflation matrix being the next matrix in the MATCOMPOSITE. This scheme repeats until the maximum
902*e26ad46dSJakub Kruzik     level is reached or there are no more matrices. If the maximal level is reached, the remaining matrices are merged
903*e26ad46dSJakub Kruzik     (multiplied) to create the last deflation matrix. The maximal level defaults to 0 and can be set by
904*e26ad46dSJakub Kruzik     PCDeflationSetMaxLvl() or by -pc_deflation_max_lvl.
905*e26ad46dSJakub Kruzik 
906*e26ad46dSJakub Kruzik     The coarse problem KSP can be controlled from the command line with prefix -def_[lvl]. You can also use
907*e26ad46dSJakub Kruzik     PCDeflationGetCoarseKSP() or PCDeflationSetCoarseKSP() to control it from code. The bottom level KSP defaults to
908*e26ad46dSJakub Kruzik     KSPREONLY with PCLU direct solver wrapped into PCTELESCOPE. For convenience, the reduction factor can be set by
909*e26ad46dSJakub Kruzik     PCDeflationSetReductionFactor() or -pc_deflation_recduction_factor. The default is chosen heuristically based on the
910*e26ad46dSJakub Kruzik     coarse problem size.
911*e26ad46dSJakub Kruzik 
912*e26ad46dSJakub Kruzik     The additional preconditioner can be controlled from command line with prefix -def_[lvl]_pc,
913*e26ad46dSJakub Kruzik     e.g., -def_0_pc_pc_type bjacobi. You can also use PCDeflationGetPC() or PCDeflationSetPC() to control
914*e26ad46dSJakub Kruzik     the additional preconditioner from code. It defaults to PCNONE.
915*e26ad46dSJakub Kruzik 
916*e26ad46dSJakub Kruzik     The coarse problem correction term (factor*Q) can be turned on by -pc_deflation_correction and the factor value can
917*e26ad46dSJakub Kruzik     be set by pc_deflation_correction_factor or by PCDeflationSetCorrectionFactor(). The coarse problem can
918*e26ad46dSJakub Kruzik     significantly improve convergence when the deflation coarse problem is not solved with high enough accuracy. We
919*e26ad46dSJakub Kruzik     recommend setting factor to some eigenvalue, e.g., the largest eigenvalue so that the preconditioner does not create
920*e26ad46dSJakub Kruzik     an isolated eigenvalue.
921*e26ad46dSJakub Kruzik 
922*e26ad46dSJakub Kruzik     The preconditioner supports KSPMonitorDynamicTolerance(). This is useful for the multilevel scheme for which we also
923*e26ad46dSJakub Kruzik     recommend limiting the number of iterations for the coarse problem.
924*e26ad46dSJakub Kruzik 
925*e26ad46dSJakub Kruzik     See section 3 of [4] for additional references and decription of the algorithm when used for conjugate gradients.
926*e26ad46dSJakub Kruzik     Section 4 describes some possible choices for the deflation space.
927*e26ad46dSJakub Kruzik 
928*e26ad46dSJakub Kruzik    Developer Notes:
929*e26ad46dSJakub Kruzik      Contributed by Jakub Kruzik (PERMON), Institute of Geonics of the Czech
930*e26ad46dSJakub Kruzik      Academy of Sciences and VSB - TU Ostrava.
931*e26ad46dSJakub Kruzik 
932*e26ad46dSJakub Kruzik      Developed from PERMON code used in [4] while on a research stay with
933*e26ad46dSJakub Kruzik      Prof. Reinhard Nabben at the Institute of Mathematics, TU Berlin.
934*e26ad46dSJakub Kruzik 
935*e26ad46dSJakub Kruzik    References:
936*e26ad46dSJakub Kruzik +    [1] - A. Nicolaides. “Deflation of conjugate gradients with applications to boundary valueproblems”, SIAM J. Numer. Anal. 24.2, 1987.
937*e26ad46dSJakub Kruzik .    [2] - Z. Dostal. "Conjugate gradient method with preconditioning by projector", Int J. Comput. Math. 23.3-4, 1988.
938*e26ad46dSJakub Kruzik .    [3] - Y. A. Erlangga and R. Nabben. "Multilevel Projection-Based Nested Krylov Iteration for Boundary Value Problems", SIAM J. Sci. Comput. 30.3, 2008.
939*e26ad46dSJakub Kruzik .    [4] - J. Kruzik "Implementation of the Deflated Variants of the Conjugate Gradient Method", Master's thesis, VSB-TUO, 2018 - http://dspace5.vsb.cz/bitstream/handle/10084/130303/KRU0097_USP_N2658_2612T078_2018.pdf
940*e26ad46dSJakub Kruzik 
941*e26ad46dSJakub Kruzik    Level: intermediate
94237eeb815SJakub Kruzik 
94337eeb815SJakub Kruzik .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
944*e26ad46dSJakub Kruzik            PCDeflationSetInitOnly(), PCDeflationSetMaxLvl(), PCDeflationSetReductionFactor(),
945*e26ad46dSJakub Kruzik            PCDeflationSetCorrectionFactor(), PCDeflationSetSpaceToCompoute(),
946*e26ad46dSJakub Kruzik            PCDeflationSetSpace(), PCDeflationSpaceType, PCDeflationSetProjectionNullSpaceMat(),
947*e26ad46dSJakub Kruzik            PCDeflationSetCoarseMat(), PCDeflationSetCoarseKSP(), PCDeflationGetCoarseKSP(),
948*e26ad46dSJakub Kruzik            PCDeflationGetPC(), PCDeflationSetPC()
94937eeb815SJakub Kruzik M*/
95037eeb815SJakub Kruzik 
95137eeb815SJakub Kruzik PETSC_EXTERN PetscErrorCode PCCreate_Deflation(PC pc)
95237eeb815SJakub Kruzik {
95337eeb815SJakub Kruzik   PC_Deflation   *def;
95437eeb815SJakub Kruzik   PetscErrorCode ierr;
95537eeb815SJakub Kruzik 
95637eeb815SJakub Kruzik   PetscFunctionBegin;
95737eeb815SJakub Kruzik   ierr     = PetscNewLog(pc,&def);CHKERRQ(ierr);
95837eeb815SJakub Kruzik   pc->data = (void*)def;
95937eeb815SJakub Kruzik 
960e662bc50SJakub Kruzik   def->init          = PETSC_FALSE;
961e662bc50SJakub Kruzik   def->correct       = PETSC_FALSE;
962fcb31d99SJakub Kruzik   def->correctfact   = 1.0;
963e662bc50SJakub Kruzik   def->reductionfact = -1;
964e662bc50SJakub Kruzik   def->spacetype     = PC_DEFLATION_SPACE_HAAR;
965e662bc50SJakub Kruzik   def->spacesize     = 1;
966e662bc50SJakub Kruzik   def->extendsp      = PETSC_FALSE;
967e662bc50SJakub Kruzik   def->nestedlvl     = 0;
968e662bc50SJakub Kruzik   def->maxnestedlvl  = 0;
96937eeb815SJakub Kruzik 
97037eeb815SJakub Kruzik   pc->ops->apply          = PCApply_Deflation;
971b27c8092SJakub Kruzik   pc->ops->presolve       = PCPreSolve_Deflation;
97237eeb815SJakub Kruzik   pc->ops->setup          = PCSetUp_Deflation;
97337eeb815SJakub Kruzik   pc->ops->reset          = PCReset_Deflation;
97437eeb815SJakub Kruzik   pc->ops->destroy        = PCDestroy_Deflation;
97537eeb815SJakub Kruzik   pc->ops->setfromoptions = PCSetFromOptions_Deflation;
9768513960bSJakub Kruzik   pc->ops->view           = PCView_Deflation;
97737eeb815SJakub Kruzik 
978a122ebaeSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetInitOnly_C",PCDeflationSetInitOnly_Deflation);CHKERRQ(ierr);
97998d6e3deSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetLvl_C",PCDeflationSetLvl_Deflation);CHKERRQ(ierr);
980859a873cSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetReductionFactor_C",PCDeflationSetReductionFactor_Deflation);CHKERRQ(ierr);
9818a71cb68SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCorrectionFactor_C",PCDeflationSetCorrectionFactor_Deflation);CHKERRQ(ierr);
98239417d7eSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpaceToCompute_C",PCDeflationSetSpaceToCompute_Deflation);CHKERRQ(ierr);
983e662bc50SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetSpace_C",PCDeflationSetSpace_Deflation);CHKERRQ(ierr);
9843cf3a049SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetProjectionNullSpaceMat_C",PCDeflationSetProjectionNullSpaceMat_Deflation);CHKERRQ(ierr);
985e924b002SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCoarseMat_C",PCDeflationSetCoarseMat_Deflation);CHKERRQ(ierr);
9864a99276eSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetCoarseKSP_C",PCDeflationGetCoarseKSP_Deflation);CHKERRQ(ierr);
987f3eaa4f0SJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetCoarseKSP_C",PCDeflationSetCoarseKSP_Deflation);CHKERRQ(ierr);
98898d6e3deSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationGetPC_C",PCDeflationGetPC_Deflation);CHKERRQ(ierr);
98998d6e3deSJakub Kruzik   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCDeflationSetPC_C",PCDeflationSetPC_Deflation);CHKERRQ(ierr);
99037eeb815SJakub Kruzik   PetscFunctionReturn(0);
99137eeb815SJakub Kruzik }
99237eeb815SJakub Kruzik 
993