xref: /petsc/src/ksp/pc/impls/composite/composite.c (revision 2b1d202a64cc9a575ce3606b483c3f323cc7f3ab)
1dba47a55SKris Buschelman 
24b9ad928SBarry Smith /*
34b9ad928SBarry Smith       Defines a preconditioner that can consist of a collection of PCs
44b9ad928SBarry Smith */
5af0996ceSBarry Smith #include <petsc/private/pcimpl.h>
6c6db04a5SJed Brown #include <petscksp.h>            /*I "petscksp.h" I*/
74b9ad928SBarry Smith 
84b9ad928SBarry Smith typedef struct _PC_CompositeLink *PC_CompositeLink;
94b9ad928SBarry Smith struct _PC_CompositeLink {
104b9ad928SBarry Smith   PC               pc;
114b9ad928SBarry Smith   PC_CompositeLink next;
12421e10b8SBarry Smith   PC_CompositeLink previous;
134b9ad928SBarry Smith };
144b9ad928SBarry Smith 
154b9ad928SBarry Smith typedef struct {
164b9ad928SBarry Smith   PC_CompositeLink head;
174b9ad928SBarry Smith   PCCompositeType  type;
184b9ad928SBarry Smith   Vec              work1;
194b9ad928SBarry Smith   Vec              work2;
204b9ad928SBarry Smith   PetscScalar      alpha;
214b9ad928SBarry Smith } PC_Composite;
224b9ad928SBarry Smith 
236849ba73SBarry Smith static PetscErrorCode PCApply_Composite_Multiplicative(PC pc,Vec x,Vec y)
244b9ad928SBarry Smith {
25dfbe8321SBarry Smith   PetscErrorCode   ierr;
264b9ad928SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
274b9ad928SBarry Smith   PC_CompositeLink next = jac->head;
284b9ad928SBarry Smith   Mat              mat  = pc->pmat;
294b9ad928SBarry Smith 
304b9ad928SBarry Smith   PetscFunctionBegin;
31450d59ebSPatrick Farrell 
32ce94432eSBarry Smith   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
33450d59ebSPatrick Farrell 
34450d59ebSPatrick Farrell   /* Set the reuse flag on children PCs */
35450d59ebSPatrick Farrell   while (next) {
36450d59ebSPatrick Farrell     ierr = PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);CHKERRQ(ierr);
37450d59ebSPatrick Farrell     next = next->next;
38450d59ebSPatrick Farrell   }
39450d59ebSPatrick Farrell   next = jac->head;
40450d59ebSPatrick Farrell 
414b9ad928SBarry Smith   if (next->next && !jac->work2) { /* allocate second work vector */
424b9ad928SBarry Smith     ierr = VecDuplicate(jac->work1,&jac->work2);CHKERRQ(ierr);
434b9ad928SBarry Smith   }
4449517cdeSBarry Smith   if (pc->useAmat) mat = pc->mat;
4509b21952SJed Brown   ierr = PCApply(next->pc,x,y);CHKERRQ(ierr);                      /* y <- B x */
464b9ad928SBarry Smith   while (next->next) {
474b9ad928SBarry Smith     next = next->next;
4809b21952SJed Brown     ierr = MatMult(mat,y,jac->work1);CHKERRQ(ierr);                /* work1 <- A y */
4909b21952SJed Brown     ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr);   /* work2 <- x - work1 */
5009b21952SJed Brown     ierr = PCApply(next->pc,jac->work2,jac->work1);CHKERRQ(ierr);  /* work1 <- C work2 */
5109b21952SJed Brown     ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);                /* y <- y + work1 = B x + C (x - A B x) = (B + C (1 - A B)) x */
524b9ad928SBarry Smith   }
53421e10b8SBarry Smith   if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
54421e10b8SBarry Smith     while (next->previous) {
55421e10b8SBarry Smith       next = next->previous;
56421e10b8SBarry Smith       ierr = MatMult(mat,y,jac->work1);CHKERRQ(ierr);
57421e10b8SBarry Smith       ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr);
58421e10b8SBarry Smith       ierr = PCApply(next->pc,jac->work2,jac->work1);CHKERRQ(ierr);
59421e10b8SBarry Smith       ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
60421e10b8SBarry Smith     }
61421e10b8SBarry Smith   }
624b9ad928SBarry Smith   PetscFunctionReturn(0);
634b9ad928SBarry Smith }
644b9ad928SBarry Smith 
652533e041SBarry Smith static PetscErrorCode PCApplyTranspose_Composite_Multiplicative(PC pc,Vec x,Vec y)
662533e041SBarry Smith {
672533e041SBarry Smith   PetscErrorCode   ierr;
682533e041SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
692533e041SBarry Smith   PC_CompositeLink next = jac->head;
702533e041SBarry Smith   Mat              mat  = pc->pmat;
712533e041SBarry Smith 
722533e041SBarry Smith   PetscFunctionBegin;
73ce94432eSBarry Smith   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
742533e041SBarry Smith   if (next->next && !jac->work2) { /* allocate second work vector */
752533e041SBarry Smith     ierr = VecDuplicate(jac->work1,&jac->work2);CHKERRQ(ierr);
762533e041SBarry Smith   }
7749517cdeSBarry Smith   if (pc->useAmat) mat = pc->mat;
782533e041SBarry Smith   /* locate last PC */
792533e041SBarry Smith   while (next->next) {
802533e041SBarry Smith     next = next->next;
812533e041SBarry Smith   }
822533e041SBarry Smith   ierr = PCApplyTranspose(next->pc,x,y);CHKERRQ(ierr);
832533e041SBarry Smith   while (next->previous) {
842533e041SBarry Smith     next = next->previous;
852533e041SBarry Smith     ierr = MatMultTranspose(mat,y,jac->work1);CHKERRQ(ierr);
862533e041SBarry Smith     ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr);
872533e041SBarry Smith     ierr = PCApplyTranspose(next->pc,jac->work2,jac->work1);CHKERRQ(ierr);
882533e041SBarry Smith     ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
892533e041SBarry Smith   }
902533e041SBarry Smith   if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
912533e041SBarry Smith     next = jac->head;
922533e041SBarry Smith     while (next->next) {
932533e041SBarry Smith       next = next->next;
942533e041SBarry Smith       ierr = MatMultTranspose(mat,y,jac->work1);CHKERRQ(ierr);
952533e041SBarry Smith       ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr);
962533e041SBarry Smith       ierr = PCApplyTranspose(next->pc,jac->work2,jac->work1);CHKERRQ(ierr);
972533e041SBarry Smith       ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
982533e041SBarry Smith     }
992533e041SBarry Smith   }
1002533e041SBarry Smith   PetscFunctionReturn(0);
1012533e041SBarry Smith }
1022533e041SBarry Smith 
1034b9ad928SBarry Smith /*
1044b9ad928SBarry Smith     This is very special for a matrix of the form alpha I + R + S
1054b9ad928SBarry Smith where first preconditioner is built from alpha I + S and second from
1064b9ad928SBarry Smith alpha I + R
1074b9ad928SBarry Smith */
1086849ba73SBarry Smith static PetscErrorCode PCApply_Composite_Special(PC pc,Vec x,Vec y)
1094b9ad928SBarry Smith {
110dfbe8321SBarry Smith   PetscErrorCode   ierr;
1114b9ad928SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
1124b9ad928SBarry Smith   PC_CompositeLink next = jac->head;
1134b9ad928SBarry Smith 
1144b9ad928SBarry Smith   PetscFunctionBegin;
115ce94432eSBarry Smith   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
116ce94432eSBarry Smith   if (!next->next || next->next->next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Special composite preconditioners requires exactly two PCs");
1174b9ad928SBarry Smith 
118450d59ebSPatrick Farrell   /* Set the reuse flag on children PCs */
119450d59ebSPatrick Farrell   ierr = PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);CHKERRQ(ierr);
120450d59ebSPatrick Farrell   ierr = PCSetReusePreconditioner(next->next->pc,pc->reusepreconditioner);CHKERRQ(ierr);
121450d59ebSPatrick Farrell 
122d8fd42c4SBarry Smith   ierr = PCApply(next->pc,x,jac->work1);CHKERRQ(ierr);
123d8fd42c4SBarry Smith   ierr = PCApply(next->next->pc,jac->work1,y);CHKERRQ(ierr);
1244b9ad928SBarry Smith   PetscFunctionReturn(0);
1254b9ad928SBarry Smith }
1264b9ad928SBarry Smith 
1276849ba73SBarry Smith static PetscErrorCode PCApply_Composite_Additive(PC pc,Vec x,Vec y)
1284b9ad928SBarry Smith {
129dfbe8321SBarry Smith   PetscErrorCode   ierr;
1304b9ad928SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
1314b9ad928SBarry Smith   PC_CompositeLink next = jac->head;
1324b9ad928SBarry Smith 
1334b9ad928SBarry Smith   PetscFunctionBegin;
134ce94432eSBarry Smith   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
135450d59ebSPatrick Farrell 
136450d59ebSPatrick Farrell   /* Set the reuse flag on children PCs */
137450d59ebSPatrick Farrell   while (next) {
138450d59ebSPatrick Farrell     ierr = PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);CHKERRQ(ierr);
139450d59ebSPatrick Farrell     next = next->next;
140450d59ebSPatrick Farrell   }
141450d59ebSPatrick Farrell   next = jac->head;
142450d59ebSPatrick Farrell 
143d8fd42c4SBarry Smith   ierr = PCApply(next->pc,x,y);CHKERRQ(ierr);
1444b9ad928SBarry Smith   while (next->next) {
1454b9ad928SBarry Smith     next = next->next;
146d8fd42c4SBarry Smith     ierr = PCApply(next->pc,x,jac->work1);CHKERRQ(ierr);
147efb30889SBarry Smith     ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
1484b9ad928SBarry Smith   }
1494b9ad928SBarry Smith   PetscFunctionReturn(0);
1504b9ad928SBarry Smith }
1514b9ad928SBarry Smith 
1522533e041SBarry Smith static PetscErrorCode PCApplyTranspose_Composite_Additive(PC pc,Vec x,Vec y)
1532533e041SBarry Smith {
1542533e041SBarry Smith   PetscErrorCode   ierr;
1552533e041SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
1562533e041SBarry Smith   PC_CompositeLink next = jac->head;
1572533e041SBarry Smith 
1582533e041SBarry Smith   PetscFunctionBegin;
159ce94432eSBarry Smith   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
1602533e041SBarry Smith   ierr = PCApplyTranspose(next->pc,x,y);CHKERRQ(ierr);
1612533e041SBarry Smith   while (next->next) {
1622533e041SBarry Smith     next = next->next;
1632533e041SBarry Smith     ierr = PCApplyTranspose(next->pc,x,jac->work1);CHKERRQ(ierr);
1642533e041SBarry Smith     ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
1652533e041SBarry Smith   }
1662533e041SBarry Smith   PetscFunctionReturn(0);
1672533e041SBarry Smith }
1682533e041SBarry Smith 
1696849ba73SBarry Smith static PetscErrorCode PCSetUp_Composite(PC pc)
1704b9ad928SBarry Smith {
171dfbe8321SBarry Smith   PetscErrorCode   ierr;
1724b9ad928SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
1734b9ad928SBarry Smith   PC_CompositeLink next = jac->head;
1745a78d018SMatthew G. Knepley   DM               dm;
1754b9ad928SBarry Smith 
1764b9ad928SBarry Smith   PetscFunctionBegin;
1774b9ad928SBarry Smith   if (!jac->work1) {
1782a7a6963SBarry Smith     ierr = MatCreateVecs(pc->pmat,&jac->work1,0);CHKERRQ(ierr);
1794b9ad928SBarry Smith   }
1805a78d018SMatthew G. Knepley   ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
1814b9ad928SBarry Smith   while (next) {
182*2b1d202aSBarry Smith     if (!next->pc->dm) {
1835a78d018SMatthew G. Knepley       ierr = PCSetDM(next->pc,dm);CHKERRQ(ierr);
184*2b1d202aSBarry Smith     }
185*2b1d202aSBarry Smith     if (!next->pc->mat) {
18623ee1639SBarry Smith       ierr = PCSetOperators(next->pc,pc->mat,pc->pmat);CHKERRQ(ierr);
187*2b1d202aSBarry Smith     }
1884b9ad928SBarry Smith     next = next->next;
1894b9ad928SBarry Smith   }
1904b9ad928SBarry Smith   PetscFunctionReturn(0);
1914b9ad928SBarry Smith }
1924b9ad928SBarry Smith 
19369d2c0f9SBarry Smith static PetscErrorCode PCReset_Composite(PC pc)
19469d2c0f9SBarry Smith {
19569d2c0f9SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
19669d2c0f9SBarry Smith   PetscErrorCode   ierr;
1975f48b12bSBarry Smith   PC_CompositeLink next = jac->head;
19869d2c0f9SBarry Smith 
19969d2c0f9SBarry Smith   PetscFunctionBegin;
20069d2c0f9SBarry Smith   while (next) {
20169d2c0f9SBarry Smith     ierr = PCReset(next->pc);CHKERRQ(ierr);
20269d2c0f9SBarry Smith     next = next->next;
20369d2c0f9SBarry Smith   }
2046bf464f9SBarry Smith   ierr = VecDestroy(&jac->work1);CHKERRQ(ierr);
2056bf464f9SBarry Smith   ierr = VecDestroy(&jac->work2);CHKERRQ(ierr);
20669d2c0f9SBarry Smith   PetscFunctionReturn(0);
20769d2c0f9SBarry Smith }
20869d2c0f9SBarry Smith 
2096849ba73SBarry Smith static PetscErrorCode PCDestroy_Composite(PC pc)
2104b9ad928SBarry Smith {
2114b9ad928SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
212dfbe8321SBarry Smith   PetscErrorCode   ierr;
213724c2c99SHong Zhang   PC_CompositeLink next = jac->head,next_tmp;
2144b9ad928SBarry Smith 
2154b9ad928SBarry Smith   PetscFunctionBegin;
21669d2c0f9SBarry Smith   ierr = PCReset_Composite(pc);CHKERRQ(ierr);
2174b9ad928SBarry Smith   while (next) {
2186bf464f9SBarry Smith     ierr     = PCDestroy(&next->pc);CHKERRQ(ierr);
219724c2c99SHong Zhang     next_tmp = next;
2204b9ad928SBarry Smith     next     = next->next;
221724c2c99SHong Zhang     ierr     = PetscFree(next_tmp);CHKERRQ(ierr);
2224b9ad928SBarry Smith   }
223c31cb41cSBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2244b9ad928SBarry Smith   PetscFunctionReturn(0);
2254b9ad928SBarry Smith }
2264b9ad928SBarry Smith 
2274416b707SBarry Smith static PetscErrorCode PCSetFromOptions_Composite(PetscOptionItems *PetscOptionsObject,PC pc)
2284b9ad928SBarry Smith {
2294b9ad928SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
230dfbe8321SBarry Smith   PetscErrorCode   ierr;
2319dcbbd2bSBarry Smith   PetscInt         nmax = 8,i;
2324b9ad928SBarry Smith   PC_CompositeLink next;
233e5999256SBarry Smith   char             *pcs[8];
234ace3abfcSBarry Smith   PetscBool        flg;
2354b9ad928SBarry Smith 
2364b9ad928SBarry Smith   PetscFunctionBegin;
237e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Composite preconditioner options");CHKERRQ(ierr);
2389dcbbd2bSBarry Smith   ierr = PetscOptionsEnum("-pc_composite_type","Type of composition","PCCompositeSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&jac->type,&flg);CHKERRQ(ierr);
23951f519a2SBarry Smith   if (flg) {
24051f519a2SBarry Smith     ierr = PCCompositeSetType(pc,jac->type);CHKERRQ(ierr);
24151f519a2SBarry Smith   }
2424b9ad928SBarry Smith   ierr = PetscOptionsStringArray("-pc_composite_pcs","List of composite solvers","PCCompositeAddPC",pcs,&nmax,&flg);CHKERRQ(ierr);
2434b9ad928SBarry Smith   if (flg) {
2444b9ad928SBarry Smith     for (i=0; i<nmax; i++) {
2454b9ad928SBarry Smith       ierr = PCCompositeAddPC(pc,pcs[i]);CHKERRQ(ierr);
246724c2c99SHong Zhang       ierr = PetscFree(pcs[i]);CHKERRQ(ierr);   /* deallocate string pcs[i], which is allocated in PetscOptionsStringArray() */
2474b9ad928SBarry Smith     }
2484b9ad928SBarry Smith   }
2494b9ad928SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
2504b9ad928SBarry Smith 
2514b9ad928SBarry Smith   next = jac->head;
2524b9ad928SBarry Smith   while (next) {
2534b9ad928SBarry Smith     ierr = PCSetFromOptions(next->pc);CHKERRQ(ierr);
2544b9ad928SBarry Smith     next = next->next;
2554b9ad928SBarry Smith   }
2564b9ad928SBarry Smith   PetscFunctionReturn(0);
2574b9ad928SBarry Smith }
2584b9ad928SBarry Smith 
2596849ba73SBarry Smith static PetscErrorCode PCView_Composite(PC pc,PetscViewer viewer)
2604b9ad928SBarry Smith {
2614b9ad928SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
262dfbe8321SBarry Smith   PetscErrorCode   ierr;
2634b9ad928SBarry Smith   PC_CompositeLink next = jac->head;
264ace3abfcSBarry Smith   PetscBool        iascii;
2654b9ad928SBarry Smith 
2664b9ad928SBarry Smith   PetscFunctionBegin;
267251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
26832077d6dSBarry Smith   if (iascii) {
2699dcbbd2bSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Composite PC type - %s\n",PCCompositeTypes[jac->type]);CHKERRQ(ierr);
2704b9ad928SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"PCs on composite preconditioner follow\n");CHKERRQ(ierr);
2714b9ad928SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"---------------------------------\n");CHKERRQ(ierr);
2724b9ad928SBarry Smith   }
27332077d6dSBarry Smith   if (iascii) {
2744b9ad928SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
2754b9ad928SBarry Smith   }
2764b9ad928SBarry Smith   while (next) {
2774b9ad928SBarry Smith     ierr = PCView(next->pc,viewer);CHKERRQ(ierr);
2784b9ad928SBarry Smith     next = next->next;
2794b9ad928SBarry Smith   }
28032077d6dSBarry Smith   if (iascii) {
2814b9ad928SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
2824b9ad928SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"---------------------------------\n");CHKERRQ(ierr);
2834b9ad928SBarry Smith   }
2844b9ad928SBarry Smith   PetscFunctionReturn(0);
2854b9ad928SBarry Smith }
2864b9ad928SBarry Smith 
2874b9ad928SBarry Smith /* ------------------------------------------------------------------------------*/
2884b9ad928SBarry Smith 
2891e6b0712SBarry Smith static PetscErrorCode  PCCompositeSpecialSetAlpha_Composite(PC pc,PetscScalar alpha)
2904b9ad928SBarry Smith {
2914b9ad928SBarry Smith   PC_Composite *jac = (PC_Composite*)pc->data;
2925fd66863SKarl Rupp 
2934b9ad928SBarry Smith   PetscFunctionBegin;
2944b9ad928SBarry Smith   jac->alpha = alpha;
2954b9ad928SBarry Smith   PetscFunctionReturn(0);
2964b9ad928SBarry Smith }
2974b9ad928SBarry Smith 
2981e6b0712SBarry Smith static PetscErrorCode  PCCompositeSetType_Composite(PC pc,PCCompositeType type)
2994b9ad928SBarry Smith {
300fad69fbaSJed Brown   PC_Composite *jac = (PC_Composite*)pc->data;
301fad69fbaSJed Brown 
3024b9ad928SBarry Smith   PetscFunctionBegin;
3034b9ad928SBarry Smith   if (type == PC_COMPOSITE_ADDITIVE) {
3044b9ad928SBarry Smith     pc->ops->apply          = PCApply_Composite_Additive;
3052533e041SBarry Smith     pc->ops->applytranspose = PCApplyTranspose_Composite_Additive;
306421e10b8SBarry Smith   } else if (type ==  PC_COMPOSITE_MULTIPLICATIVE || type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
3074b9ad928SBarry Smith     pc->ops->apply          = PCApply_Composite_Multiplicative;
3082533e041SBarry Smith     pc->ops->applytranspose = PCApplyTranspose_Composite_Multiplicative;
3094b9ad928SBarry Smith   } else if (type ==  PC_COMPOSITE_SPECIAL) {
3104b9ad928SBarry Smith     pc->ops->apply          = PCApply_Composite_Special;
3110298fd71SBarry Smith     pc->ops->applytranspose = NULL;
312ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Unkown composite preconditioner type");
313fad69fbaSJed Brown   jac->type = type;
3144b9ad928SBarry Smith   PetscFunctionReturn(0);
3154b9ad928SBarry Smith }
3164b9ad928SBarry Smith 
317c60c7ad4SBarry Smith static PetscErrorCode  PCCompositeGetType_Composite(PC pc,PCCompositeType *type)
318c60c7ad4SBarry Smith {
319c60c7ad4SBarry Smith   PC_Composite *jac = (PC_Composite*)pc->data;
320c60c7ad4SBarry Smith 
321c60c7ad4SBarry Smith   PetscFunctionBegin;
322c60c7ad4SBarry Smith   *type = jac->type;
323c60c7ad4SBarry Smith   PetscFunctionReturn(0);
324c60c7ad4SBarry Smith }
325c60c7ad4SBarry Smith 
3261e6b0712SBarry Smith static PetscErrorCode  PCCompositeAddPC_Composite(PC pc,PCType type)
3274b9ad928SBarry Smith {
3284b9ad928SBarry Smith   PC_Composite     *jac;
3295a9f2f41SSatish Balay   PC_CompositeLink next,ilink;
330dfbe8321SBarry Smith   PetscErrorCode   ierr;
33179416396SBarry Smith   PetscInt         cnt = 0;
3322dcb1b2aSMatthew Knepley   const char       *prefix;
333d726e3a5SJed Brown   char             newprefix[20];
3344b9ad928SBarry Smith 
3354b9ad928SBarry Smith   PetscFunctionBegin;
336b00a9115SJed Brown   ierr        = PetscNewLog(pc,&ilink);CHKERRQ(ierr);
3375a9f2f41SSatish Balay   ilink->next = 0;
338ce94432eSBarry Smith   ierr        = PCCreate(PetscObjectComm((PetscObject)pc),&ilink->pc);CHKERRQ(ierr);
339ace3abfcSBarry Smith   ierr        = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->pc);CHKERRQ(ierr);
3404b9ad928SBarry Smith 
3414b9ad928SBarry Smith   jac  = (PC_Composite*)pc->data;
3424b9ad928SBarry Smith   next = jac->head;
3434b9ad928SBarry Smith   if (!next) {
3445a9f2f41SSatish Balay     jac->head       = ilink;
3450298fd71SBarry Smith     ilink->previous = NULL;
3464b9ad928SBarry Smith   } else {
3474b9ad928SBarry Smith     cnt++;
3484b9ad928SBarry Smith     while (next->next) {
3494b9ad928SBarry Smith       next = next->next;
3504b9ad928SBarry Smith       cnt++;
3514b9ad928SBarry Smith     }
3525a9f2f41SSatish Balay     next->next      = ilink;
353421e10b8SBarry Smith     ilink->previous = next;
3544b9ad928SBarry Smith   }
3554b9ad928SBarry Smith   ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
3565a9f2f41SSatish Balay   ierr = PCSetOptionsPrefix(ilink->pc,prefix);CHKERRQ(ierr);
35713f74950SBarry Smith   sprintf(newprefix,"sub_%d_",(int)cnt);
3585a9f2f41SSatish Balay   ierr = PCAppendOptionsPrefix(ilink->pc,newprefix);CHKERRQ(ierr);
3594b9ad928SBarry Smith   /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */
3605a9f2f41SSatish Balay   ierr = PCSetType(ilink->pc,type);CHKERRQ(ierr);
3614b9ad928SBarry Smith   PetscFunctionReturn(0);
3624b9ad928SBarry Smith }
3634b9ad928SBarry Smith 
3648e6eba06SBarry Smith static PetscErrorCode  PCCompositeGetNumberPC_Composite(PC pc,PetscInt *n)
3658e6eba06SBarry Smith {
3668e6eba06SBarry Smith   PC_Composite     *jac;
3678e6eba06SBarry Smith   PC_CompositeLink next;
3688e6eba06SBarry Smith 
3698e6eba06SBarry Smith   PetscFunctionBegin;
3708e6eba06SBarry Smith   jac  = (PC_Composite*)pc->data;
3718e6eba06SBarry Smith   next = jac->head;
3728e6eba06SBarry Smith   *n = 0;
3738e6eba06SBarry Smith   while (next) {
3748e6eba06SBarry Smith     next = next->next;
3758e6eba06SBarry Smith     (*n) ++;
3768e6eba06SBarry Smith   }
3778e6eba06SBarry Smith   PetscFunctionReturn(0);
3788e6eba06SBarry Smith }
3798e6eba06SBarry Smith 
3801e6b0712SBarry Smith static PetscErrorCode  PCCompositeGetPC_Composite(PC pc,PetscInt n,PC *subpc)
3814b9ad928SBarry Smith {
3824b9ad928SBarry Smith   PC_Composite     *jac;
3834b9ad928SBarry Smith   PC_CompositeLink next;
38479416396SBarry Smith   PetscInt         i;
3854b9ad928SBarry Smith 
3864b9ad928SBarry Smith   PetscFunctionBegin;
3874b9ad928SBarry Smith   jac  = (PC_Composite*)pc->data;
3884b9ad928SBarry Smith   next = jac->head;
3894b9ad928SBarry Smith   for (i=0; i<n; i++) {
390ce94432eSBarry Smith     if (!next->next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Not enough PCs in composite preconditioner");
3914b9ad928SBarry Smith     next = next->next;
3924b9ad928SBarry Smith   }
3934b9ad928SBarry Smith   *subpc = next->pc;
3944b9ad928SBarry Smith   PetscFunctionReturn(0);
3954b9ad928SBarry Smith }
3964b9ad928SBarry Smith 
3974b9ad928SBarry Smith /* -------------------------------------------------------------------------------- */
398f39d8e23SSatish Balay /*@
3994b9ad928SBarry Smith    PCCompositeSetType - Sets the type of composite preconditioner.
4004b9ad928SBarry Smith 
401ad4df100SBarry Smith    Logically Collective on PC
4024b9ad928SBarry Smith 
403c60c7ad4SBarry Smith    Input Parameters:
4042a6744ebSBarry Smith +  pc - the preconditioner context
4052a6744ebSBarry Smith -  type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL
4064b9ad928SBarry Smith 
4074b9ad928SBarry Smith    Options Database Key:
4084b9ad928SBarry Smith .  -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type
4094b9ad928SBarry Smith 
4104b9ad928SBarry Smith    Level: Developer
4114b9ad928SBarry Smith 
4124b9ad928SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative
4134b9ad928SBarry Smith @*/
4147087cfbeSBarry Smith PetscErrorCode  PCCompositeSetType(PC pc,PCCompositeType type)
4154b9ad928SBarry Smith {
4167bb14e67SBarry Smith   PetscErrorCode ierr;
4174b9ad928SBarry Smith 
4184b9ad928SBarry Smith   PetscFunctionBegin;
4190700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
420c5eb9154SBarry Smith   PetscValidLogicalCollectiveEnum(pc,type,2);
4217bb14e67SBarry Smith   ierr = PetscTryMethod(pc,"PCCompositeSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr);
4224b9ad928SBarry Smith   PetscFunctionReturn(0);
4234b9ad928SBarry Smith }
4244b9ad928SBarry Smith 
425c60c7ad4SBarry Smith /*@
426721f67b5SBarry Smith    PCCompositeGetType - Gets the type of composite preconditioner.
427c60c7ad4SBarry Smith 
428c60c7ad4SBarry Smith    Logically Collective on PC
429c60c7ad4SBarry Smith 
430c60c7ad4SBarry Smith    Input Parameter:
431c60c7ad4SBarry Smith .  pc - the preconditioner context
432c60c7ad4SBarry Smith 
433c60c7ad4SBarry Smith    Output Parameter:
434c60c7ad4SBarry Smith .  type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL
435c60c7ad4SBarry Smith 
436c60c7ad4SBarry Smith    Options Database Key:
437c60c7ad4SBarry Smith .  -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type
438c60c7ad4SBarry Smith 
439c60c7ad4SBarry Smith    Level: Developer
440c60c7ad4SBarry Smith 
441c60c7ad4SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative
442c60c7ad4SBarry Smith @*/
443c60c7ad4SBarry Smith PetscErrorCode  PCCompositeGetType(PC pc,PCCompositeType *type)
444c60c7ad4SBarry Smith {
445c60c7ad4SBarry Smith   PetscErrorCode ierr;
446c60c7ad4SBarry Smith 
447c60c7ad4SBarry Smith   PetscFunctionBegin;
448c60c7ad4SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
449c60c7ad4SBarry Smith   ierr = PetscUseMethod(pc,"PCCompositeGetType_C",(PC,PCCompositeType*),(pc,type));CHKERRQ(ierr);
450c60c7ad4SBarry Smith   PetscFunctionReturn(0);
451c60c7ad4SBarry Smith }
452c60c7ad4SBarry Smith 
453f39d8e23SSatish Balay /*@
4544b9ad928SBarry Smith    PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner
4554b9ad928SBarry Smith      for alphaI + R + S
4564b9ad928SBarry Smith 
457ad4df100SBarry Smith    Logically Collective on PC
4584b9ad928SBarry Smith 
4594b9ad928SBarry Smith    Input Parameter:
4604b9ad928SBarry Smith +  pc - the preconditioner context
4614b9ad928SBarry Smith -  alpha - scale on identity
4624b9ad928SBarry Smith 
4634b9ad928SBarry Smith    Level: Developer
4644b9ad928SBarry Smith 
4654b9ad928SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative
4664b9ad928SBarry Smith @*/
4677087cfbeSBarry Smith PetscErrorCode  PCCompositeSpecialSetAlpha(PC pc,PetscScalar alpha)
4684b9ad928SBarry Smith {
4694ac538c5SBarry Smith   PetscErrorCode ierr;
4704b9ad928SBarry Smith 
4714b9ad928SBarry Smith   PetscFunctionBegin;
4720700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
473c5eb9154SBarry Smith   PetscValidLogicalCollectiveScalar(pc,alpha,2);
4744ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCCompositeSpecialSetAlpha_C",(PC,PetscScalar),(pc,alpha));CHKERRQ(ierr);
4754b9ad928SBarry Smith   PetscFunctionReturn(0);
4764b9ad928SBarry Smith }
4774b9ad928SBarry Smith 
4784b9ad928SBarry Smith /*@C
4794b9ad928SBarry Smith    PCCompositeAddPC - Adds another PC to the composite PC.
4804b9ad928SBarry Smith 
4814b9ad928SBarry Smith    Collective on PC
4824b9ad928SBarry Smith 
4834b9ad928SBarry Smith    Input Parameters:
4842a6744ebSBarry Smith +  pc - the preconditioner context
4852a6744ebSBarry Smith -  type - the type of the new preconditioner
4864b9ad928SBarry Smith 
4874b9ad928SBarry Smith    Level: Developer
4884b9ad928SBarry Smith 
4894b9ad928SBarry Smith .keywords: PC, composite preconditioner, add
4904b9ad928SBarry Smith @*/
49119fd82e9SBarry Smith PetscErrorCode  PCCompositeAddPC(PC pc,PCType type)
4924b9ad928SBarry Smith {
4934ac538c5SBarry Smith   PetscErrorCode ierr;
4944b9ad928SBarry Smith 
4954b9ad928SBarry Smith   PetscFunctionBegin;
4960700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
49719fd82e9SBarry Smith   ierr = PetscTryMethod(pc,"PCCompositeAddPC_C",(PC,PCType),(pc,type));CHKERRQ(ierr);
4984b9ad928SBarry Smith   PetscFunctionReturn(0);
4994b9ad928SBarry Smith }
5004b9ad928SBarry Smith 
5018e6eba06SBarry Smith /*@
5028e6eba06SBarry Smith    PCCompositeGetNumberPC - Gets the number of PC objects in the composite PC.
5038e6eba06SBarry Smith 
5048e6eba06SBarry Smith    Not Collective
5058e6eba06SBarry Smith 
5068e6eba06SBarry Smith    Input Parameter:
5078e6eba06SBarry Smith .  pc - the preconditioner context
5088e6eba06SBarry Smith 
5098e6eba06SBarry Smith    Output Parameter:
5108e6eba06SBarry Smith .  num - the number of sub pcs
5118e6eba06SBarry Smith 
5128e6eba06SBarry Smith    Level: Developer
5138e6eba06SBarry Smith 
5148e6eba06SBarry Smith .keywords: PC, get, composite preconditioner, sub preconditioner
5158e6eba06SBarry Smith 
5168e6eba06SBarry Smith .seealso: PCCompositeGetPC()
5178e6eba06SBarry Smith @*/
5188e6eba06SBarry Smith PetscErrorCode  PCCompositeGetNumberPC(PC pc,PetscInt *num)
5198e6eba06SBarry Smith {
5208e6eba06SBarry Smith   PetscErrorCode ierr;
5218e6eba06SBarry Smith 
5228e6eba06SBarry Smith   PetscFunctionBegin;
5238e6eba06SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5248e6eba06SBarry Smith   PetscValidIntPointer(num,2);
5258e6eba06SBarry Smith   ierr = PetscUseMethod(pc,"PCCompositeGetNumberPC_C",(PC,PetscInt*),(pc,num));CHKERRQ(ierr);
5268e6eba06SBarry Smith   PetscFunctionReturn(0);
5278e6eba06SBarry Smith }
5288e6eba06SBarry Smith 
529f39d8e23SSatish Balay /*@
5304b9ad928SBarry Smith    PCCompositeGetPC - Gets one of the PC objects in the composite PC.
5314b9ad928SBarry Smith 
5324b9ad928SBarry Smith    Not Collective
5334b9ad928SBarry Smith 
5344b9ad928SBarry Smith    Input Parameter:
5352a6744ebSBarry Smith +  pc - the preconditioner context
5362a6744ebSBarry Smith -  n - the number of the pc requested
5374b9ad928SBarry Smith 
5384b9ad928SBarry Smith    Output Parameters:
5394b9ad928SBarry Smith .  subpc - the PC requested
5404b9ad928SBarry Smith 
5414b9ad928SBarry Smith    Level: Developer
5424b9ad928SBarry Smith 
543*2b1d202aSBarry Smith     Notes: To use a different operator to construct one of the inner preconditioners first call PCCompositeGetPC(), then
544*2b1d202aSBarry Smith             call PCSetOperators() on that PC.
545*2b1d202aSBarry Smith 
5464b9ad928SBarry Smith .keywords: PC, get, composite preconditioner, sub preconditioner
5474b9ad928SBarry Smith 
548*2b1d202aSBarry Smith .seealso: PCCompositeAddPC(), PCCompositeGetNumberPC(), PCSetOperators()
5494b9ad928SBarry Smith @*/
5507087cfbeSBarry Smith PetscErrorCode  PCCompositeGetPC(PC pc,PetscInt n,PC *subpc)
5514b9ad928SBarry Smith {
5524ac538c5SBarry Smith   PetscErrorCode ierr;
5534b9ad928SBarry Smith 
5544b9ad928SBarry Smith   PetscFunctionBegin;
5550700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5564482741eSBarry Smith   PetscValidPointer(subpc,3);
5574ac538c5SBarry Smith   ierr = PetscUseMethod(pc,"PCCompositeGetPC_C",(PC,PetscInt,PC*),(pc,n,subpc));CHKERRQ(ierr);
5584b9ad928SBarry Smith   PetscFunctionReturn(0);
5594b9ad928SBarry Smith }
5604b9ad928SBarry Smith 
5614b9ad928SBarry Smith /* -------------------------------------------------------------------------------------------*/
5624b9ad928SBarry Smith 
5634b9ad928SBarry Smith /*MC
5644b9ad928SBarry Smith      PCCOMPOSITE - Build a preconditioner by composing together several preconditioners
5654b9ad928SBarry Smith 
5664b9ad928SBarry Smith    Options Database Keys:
5672eab2d5bSJungho Lee +  -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type
568*2b1d202aSBarry Smith .  -pc_use_amat - activates PCSetUseAmat()
56951f519a2SBarry Smith -  -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose
5704b9ad928SBarry Smith 
5714b9ad928SBarry Smith    Level: intermediate
5724b9ad928SBarry Smith 
5734b9ad928SBarry Smith    Concepts: composing solvers
5744b9ad928SBarry Smith 
5754b9ad928SBarry Smith    Notes: To use a Krylov method inside the composite preconditioner, set the PCType of one or more
5764b9ad928SBarry Smith           inner PCs to be PCKSP.
5774b9ad928SBarry Smith           Using a Krylov method inside another Krylov method can be dangerous (you get divergence or
578b3ef52cdSBarry Smith           the incorrect answer) unless you use KSPFGMRES as the outer Krylov method
579*2b1d202aSBarry Smith           To use a different operator to construct one of the inner preconditioners first call PCCompositeGetPC(), then
580*2b1d202aSBarry Smith           call PCSetOperators() on that PC.
5814b9ad928SBarry Smith 
5824b9ad928SBarry Smith 
5834b9ad928SBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
5844b9ad928SBarry Smith            PCSHELL, PCKSP, PCCompositeSetType(), PCCompositeSpecialSetAlpha(), PCCompositeAddPC(),
58549517cdeSBarry Smith            PCCompositeGetPC(), PCSetUseAmat()
5864b9ad928SBarry Smith 
5874b9ad928SBarry Smith M*/
5884b9ad928SBarry Smith 
5898cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc)
5904b9ad928SBarry Smith {
591dfbe8321SBarry Smith   PetscErrorCode ierr;
5924b9ad928SBarry Smith   PC_Composite   *jac;
5934b9ad928SBarry Smith 
5944b9ad928SBarry Smith   PetscFunctionBegin;
595b00a9115SJed Brown   ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr);
5962fa5cd67SKarl Rupp 
5974b9ad928SBarry Smith   pc->ops->apply           = PCApply_Composite_Additive;
5982533e041SBarry Smith   pc->ops->applytranspose  = PCApplyTranspose_Composite_Additive;
5994b9ad928SBarry Smith   pc->ops->setup           = PCSetUp_Composite;
60069d2c0f9SBarry Smith   pc->ops->reset           = PCReset_Composite;
6014b9ad928SBarry Smith   pc->ops->destroy         = PCDestroy_Composite;
6024b9ad928SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_Composite;
6034b9ad928SBarry Smith   pc->ops->view            = PCView_Composite;
6044b9ad928SBarry Smith   pc->ops->applyrichardson = 0;
6054b9ad928SBarry Smith 
6064b9ad928SBarry Smith   pc->data   = (void*)jac;
6074b9ad928SBarry Smith   jac->type  = PC_COMPOSITE_ADDITIVE;
6084b9ad928SBarry Smith   jac->work1 = 0;
6094b9ad928SBarry Smith   jac->work2 = 0;
6104b9ad928SBarry Smith   jac->head  = 0;
6114b9ad928SBarry Smith 
612bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSetType_C",PCCompositeSetType_Composite);CHKERRQ(ierr);
613c60c7ad4SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetType_C",PCCompositeGetType_Composite);CHKERRQ(ierr);
614bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPC_C",PCCompositeAddPC_Composite);CHKERRQ(ierr);
6158e6eba06SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetNumberPC_C",PCCompositeGetNumberPC_Composite);CHKERRQ(ierr);
616bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetPC_C",PCCompositeGetPC_Composite);CHKERRQ(ierr);
617bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSpecialSetAlpha_C",PCCompositeSpecialSetAlpha_Composite);CHKERRQ(ierr);
6184b9ad928SBarry Smith   PetscFunctionReturn(0);
6194b9ad928SBarry Smith }
6204b9ad928SBarry Smith 
621