xref: /petsc/src/ksp/pc/impls/composite/composite.c (revision d726e3a5d645135457890c6df504915a32ebb85d)
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 */
5051f519a2SBarry Smith     ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr);  /* zero since some PC's may not set all entries in the result */
5109b21952SJed Brown     ierr = PCApply(next->pc,jac->work2,jac->work1);CHKERRQ(ierr);  /* work1 <- C work2 */
5209b21952SJed 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 */
534b9ad928SBarry Smith   }
54421e10b8SBarry Smith   if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
55421e10b8SBarry Smith     while (next->previous) {
56421e10b8SBarry Smith       next = next->previous;
57421e10b8SBarry Smith       ierr = MatMult(mat,y,jac->work1);CHKERRQ(ierr);
58421e10b8SBarry Smith       ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr);
59421e10b8SBarry Smith       ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr);  /* zero since some PC's may not set all entries in the result */
60421e10b8SBarry Smith       ierr = PCApply(next->pc,jac->work2,jac->work1);CHKERRQ(ierr);
61421e10b8SBarry Smith       ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
62421e10b8SBarry Smith     }
63421e10b8SBarry Smith   }
644b9ad928SBarry Smith   PetscFunctionReturn(0);
654b9ad928SBarry Smith }
664b9ad928SBarry Smith 
672533e041SBarry Smith static PetscErrorCode PCApplyTranspose_Composite_Multiplicative(PC pc,Vec x,Vec y)
682533e041SBarry Smith {
692533e041SBarry Smith   PetscErrorCode   ierr;
702533e041SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
712533e041SBarry Smith   PC_CompositeLink next = jac->head;
722533e041SBarry Smith   Mat              mat  = pc->pmat;
732533e041SBarry Smith 
742533e041SBarry Smith   PetscFunctionBegin;
75ce94432eSBarry Smith   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
762533e041SBarry Smith   if (next->next && !jac->work2) { /* allocate second work vector */
772533e041SBarry Smith     ierr = VecDuplicate(jac->work1,&jac->work2);CHKERRQ(ierr);
782533e041SBarry Smith   }
7949517cdeSBarry Smith   if (pc->useAmat) mat = pc->mat;
802533e041SBarry Smith   /* locate last PC */
812533e041SBarry Smith   while (next->next) {
822533e041SBarry Smith     next = next->next;
832533e041SBarry Smith   }
842533e041SBarry Smith   ierr = PCApplyTranspose(next->pc,x,y);CHKERRQ(ierr);
852533e041SBarry Smith   while (next->previous) {
862533e041SBarry Smith     next = next->previous;
872533e041SBarry Smith     ierr = MatMultTranspose(mat,y,jac->work1);CHKERRQ(ierr);
882533e041SBarry Smith     ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr);
892533e041SBarry Smith     ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr);  /* zero since some PC's may not set all entries in the result */
902533e041SBarry Smith     ierr = PCApplyTranspose(next->pc,jac->work2,jac->work1);CHKERRQ(ierr);
912533e041SBarry Smith     ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
922533e041SBarry Smith   }
932533e041SBarry Smith   if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
942533e041SBarry Smith     next = jac->head;
952533e041SBarry Smith     while (next->next) {
962533e041SBarry Smith       next = next->next;
972533e041SBarry Smith       ierr = MatMultTranspose(mat,y,jac->work1);CHKERRQ(ierr);
982533e041SBarry Smith       ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr);
992533e041SBarry Smith       ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr);  /* zero since some PC's may not set all entries in the result */
1002533e041SBarry Smith       ierr = PCApplyTranspose(next->pc,jac->work2,jac->work1);CHKERRQ(ierr);
1012533e041SBarry Smith       ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
1022533e041SBarry Smith     }
1032533e041SBarry Smith   }
1042533e041SBarry Smith   PetscFunctionReturn(0);
1052533e041SBarry Smith }
1062533e041SBarry Smith 
1074b9ad928SBarry Smith /*
1084b9ad928SBarry Smith     This is very special for a matrix of the form alpha I + R + S
1094b9ad928SBarry Smith where first preconditioner is built from alpha I + S and second from
1104b9ad928SBarry Smith alpha I + R
1114b9ad928SBarry Smith */
1126849ba73SBarry Smith static PetscErrorCode PCApply_Composite_Special(PC pc,Vec x,Vec y)
1134b9ad928SBarry Smith {
114dfbe8321SBarry Smith   PetscErrorCode   ierr;
1154b9ad928SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
1164b9ad928SBarry Smith   PC_CompositeLink next = jac->head;
1174b9ad928SBarry Smith 
1184b9ad928SBarry Smith   PetscFunctionBegin;
119ce94432eSBarry Smith   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
120ce94432eSBarry Smith   if (!next->next || next->next->next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Special composite preconditioners requires exactly two PCs");
1214b9ad928SBarry Smith 
122450d59ebSPatrick Farrell   /* Set the reuse flag on children PCs */
123450d59ebSPatrick Farrell   ierr = PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);CHKERRQ(ierr);
124450d59ebSPatrick Farrell   ierr = PCSetReusePreconditioner(next->next->pc,pc->reusepreconditioner);CHKERRQ(ierr);
125450d59ebSPatrick Farrell 
126d8fd42c4SBarry Smith   ierr = PCApply(next->pc,x,jac->work1);CHKERRQ(ierr);
127d8fd42c4SBarry Smith   ierr = PCApply(next->next->pc,jac->work1,y);CHKERRQ(ierr);
1284b9ad928SBarry Smith   PetscFunctionReturn(0);
1294b9ad928SBarry Smith }
1304b9ad928SBarry Smith 
1316849ba73SBarry Smith static PetscErrorCode PCApply_Composite_Additive(PC pc,Vec x,Vec y)
1324b9ad928SBarry Smith {
133dfbe8321SBarry Smith   PetscErrorCode   ierr;
1344b9ad928SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
1354b9ad928SBarry Smith   PC_CompositeLink next = jac->head;
1364b9ad928SBarry Smith 
1374b9ad928SBarry Smith   PetscFunctionBegin;
138ce94432eSBarry Smith   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
139450d59ebSPatrick Farrell 
140450d59ebSPatrick Farrell   /* Set the reuse flag on children PCs */
141450d59ebSPatrick Farrell   while (next) {
142450d59ebSPatrick Farrell     ierr = PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);CHKERRQ(ierr);
143450d59ebSPatrick Farrell     next = next->next;
144450d59ebSPatrick Farrell   }
145450d59ebSPatrick Farrell   next = jac->head;
146450d59ebSPatrick Farrell 
147d8fd42c4SBarry Smith   ierr = PCApply(next->pc,x,y);CHKERRQ(ierr);
1484b9ad928SBarry Smith   while (next->next) {
1494b9ad928SBarry Smith     next = next->next;
15051f519a2SBarry Smith     ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr);  /* zero since some PC's may not set all entries in the result */
151d8fd42c4SBarry Smith     ierr = PCApply(next->pc,x,jac->work1);CHKERRQ(ierr);
152efb30889SBarry Smith     ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
1534b9ad928SBarry Smith   }
1544b9ad928SBarry Smith   PetscFunctionReturn(0);
1554b9ad928SBarry Smith }
1564b9ad928SBarry Smith 
1572533e041SBarry Smith static PetscErrorCode PCApplyTranspose_Composite_Additive(PC pc,Vec x,Vec y)
1582533e041SBarry Smith {
1592533e041SBarry Smith   PetscErrorCode   ierr;
1602533e041SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
1612533e041SBarry Smith   PC_CompositeLink next = jac->head;
1622533e041SBarry Smith 
1632533e041SBarry Smith   PetscFunctionBegin;
164ce94432eSBarry Smith   if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs");
1652533e041SBarry Smith   ierr = PCApplyTranspose(next->pc,x,y);CHKERRQ(ierr);
1662533e041SBarry Smith   while (next->next) {
1672533e041SBarry Smith     next = next->next;
1682533e041SBarry Smith     ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr);  /* zero since some PC's may not set all entries in the result */
1692533e041SBarry Smith     ierr = PCApplyTranspose(next->pc,x,jac->work1);CHKERRQ(ierr);
1702533e041SBarry Smith     ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr);
1712533e041SBarry Smith   }
1722533e041SBarry Smith   PetscFunctionReturn(0);
1732533e041SBarry Smith }
1742533e041SBarry Smith 
1756849ba73SBarry Smith static PetscErrorCode PCSetUp_Composite(PC pc)
1764b9ad928SBarry Smith {
177dfbe8321SBarry Smith   PetscErrorCode   ierr;
1784b9ad928SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
1794b9ad928SBarry Smith   PC_CompositeLink next = jac->head;
1805a78d018SMatthew G. Knepley   DM               dm;
1814b9ad928SBarry Smith 
1824b9ad928SBarry Smith   PetscFunctionBegin;
1834b9ad928SBarry Smith   if (!jac->work1) {
1842a7a6963SBarry Smith     ierr = MatCreateVecs(pc->pmat,&jac->work1,0);CHKERRQ(ierr);
1854b9ad928SBarry Smith   }
1865a78d018SMatthew G. Knepley   ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
1874b9ad928SBarry Smith   while (next) {
1885a78d018SMatthew G. Knepley     ierr = PCSetDM(next->pc,dm);CHKERRQ(ierr);
18923ee1639SBarry Smith     ierr = PCSetOperators(next->pc,pc->mat,pc->pmat);CHKERRQ(ierr);
1904b9ad928SBarry Smith     next = next->next;
1914b9ad928SBarry Smith   }
1924b9ad928SBarry Smith   PetscFunctionReturn(0);
1934b9ad928SBarry Smith }
1944b9ad928SBarry Smith 
19569d2c0f9SBarry Smith static PetscErrorCode PCReset_Composite(PC pc)
19669d2c0f9SBarry Smith {
19769d2c0f9SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
19869d2c0f9SBarry Smith   PetscErrorCode   ierr;
1995f48b12bSBarry Smith   PC_CompositeLink next = jac->head;
20069d2c0f9SBarry Smith 
20169d2c0f9SBarry Smith   PetscFunctionBegin;
20269d2c0f9SBarry Smith   while (next) {
20369d2c0f9SBarry Smith     ierr = PCReset(next->pc);CHKERRQ(ierr);
20469d2c0f9SBarry Smith     next = next->next;
20569d2c0f9SBarry Smith   }
2066bf464f9SBarry Smith   ierr = VecDestroy(&jac->work1);CHKERRQ(ierr);
2076bf464f9SBarry Smith   ierr = VecDestroy(&jac->work2);CHKERRQ(ierr);
20869d2c0f9SBarry Smith   PetscFunctionReturn(0);
20969d2c0f9SBarry Smith }
21069d2c0f9SBarry Smith 
2116849ba73SBarry Smith static PetscErrorCode PCDestroy_Composite(PC pc)
2124b9ad928SBarry Smith {
2134b9ad928SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
214dfbe8321SBarry Smith   PetscErrorCode   ierr;
215724c2c99SHong Zhang   PC_CompositeLink next = jac->head,next_tmp;
2164b9ad928SBarry Smith 
2174b9ad928SBarry Smith   PetscFunctionBegin;
21869d2c0f9SBarry Smith   ierr = PCReset_Composite(pc);CHKERRQ(ierr);
2194b9ad928SBarry Smith   while (next) {
2206bf464f9SBarry Smith     ierr     = PCDestroy(&next->pc);CHKERRQ(ierr);
221724c2c99SHong Zhang     next_tmp = next;
2224b9ad928SBarry Smith     next     = next->next;
223724c2c99SHong Zhang     ierr     = PetscFree(next_tmp);CHKERRQ(ierr);
2244b9ad928SBarry Smith   }
225c31cb41cSBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2264b9ad928SBarry Smith   PetscFunctionReturn(0);
2274b9ad928SBarry Smith }
2284b9ad928SBarry Smith 
2294416b707SBarry Smith static PetscErrorCode PCSetFromOptions_Composite(PetscOptionItems *PetscOptionsObject,PC pc)
2304b9ad928SBarry Smith {
2314b9ad928SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
232dfbe8321SBarry Smith   PetscErrorCode   ierr;
2339dcbbd2bSBarry Smith   PetscInt         nmax = 8,i;
2344b9ad928SBarry Smith   PC_CompositeLink next;
235e5999256SBarry Smith   char             *pcs[8];
236ace3abfcSBarry Smith   PetscBool        flg;
2374b9ad928SBarry Smith 
2384b9ad928SBarry Smith   PetscFunctionBegin;
239e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Composite preconditioner options");CHKERRQ(ierr);
2409dcbbd2bSBarry Smith   ierr = PetscOptionsEnum("-pc_composite_type","Type of composition","PCCompositeSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&jac->type,&flg);CHKERRQ(ierr);
24151f519a2SBarry Smith   if (flg) {
24251f519a2SBarry Smith     ierr = PCCompositeSetType(pc,jac->type);CHKERRQ(ierr);
24351f519a2SBarry Smith   }
2444b9ad928SBarry Smith   ierr = PetscOptionsStringArray("-pc_composite_pcs","List of composite solvers","PCCompositeAddPC",pcs,&nmax,&flg);CHKERRQ(ierr);
2454b9ad928SBarry Smith   if (flg) {
2464b9ad928SBarry Smith     for (i=0; i<nmax; i++) {
2474b9ad928SBarry Smith       ierr = PCCompositeAddPC(pc,pcs[i]);CHKERRQ(ierr);
248724c2c99SHong Zhang       ierr = PetscFree(pcs[i]);CHKERRQ(ierr);   /* deallocate string pcs[i], which is allocated in PetscOptionsStringArray() */
2494b9ad928SBarry Smith     }
2504b9ad928SBarry Smith   }
2514b9ad928SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
2524b9ad928SBarry Smith 
2534b9ad928SBarry Smith   next = jac->head;
2544b9ad928SBarry Smith   while (next) {
2554b9ad928SBarry Smith     ierr = PCSetFromOptions(next->pc);CHKERRQ(ierr);
2564b9ad928SBarry Smith     next = next->next;
2574b9ad928SBarry Smith   }
2584b9ad928SBarry Smith   PetscFunctionReturn(0);
2594b9ad928SBarry Smith }
2604b9ad928SBarry Smith 
2616849ba73SBarry Smith static PetscErrorCode PCView_Composite(PC pc,PetscViewer viewer)
2624b9ad928SBarry Smith {
2634b9ad928SBarry Smith   PC_Composite     *jac = (PC_Composite*)pc->data;
264dfbe8321SBarry Smith   PetscErrorCode   ierr;
2654b9ad928SBarry Smith   PC_CompositeLink next = jac->head;
266ace3abfcSBarry Smith   PetscBool        iascii;
2674b9ad928SBarry Smith 
2684b9ad928SBarry Smith   PetscFunctionBegin;
269251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
27032077d6dSBarry Smith   if (iascii) {
2719dcbbd2bSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Composite PC type - %s\n",PCCompositeTypes[jac->type]);CHKERRQ(ierr);
2724b9ad928SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"PCs on composite preconditioner follow\n");CHKERRQ(ierr);
2734b9ad928SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"---------------------------------\n");CHKERRQ(ierr);
2744b9ad928SBarry Smith   }
27532077d6dSBarry Smith   if (iascii) {
2764b9ad928SBarry Smith     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
2774b9ad928SBarry Smith   }
2784b9ad928SBarry Smith   while (next) {
2794b9ad928SBarry Smith     ierr = PCView(next->pc,viewer);CHKERRQ(ierr);
2804b9ad928SBarry Smith     next = next->next;
2814b9ad928SBarry Smith   }
28232077d6dSBarry Smith   if (iascii) {
2834b9ad928SBarry Smith     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
2844b9ad928SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"---------------------------------\n");CHKERRQ(ierr);
2854b9ad928SBarry Smith   }
2864b9ad928SBarry Smith   PetscFunctionReturn(0);
2874b9ad928SBarry Smith }
2884b9ad928SBarry Smith 
2894b9ad928SBarry Smith /* ------------------------------------------------------------------------------*/
2904b9ad928SBarry Smith 
2911e6b0712SBarry Smith static PetscErrorCode  PCCompositeSpecialSetAlpha_Composite(PC pc,PetscScalar alpha)
2924b9ad928SBarry Smith {
2934b9ad928SBarry Smith   PC_Composite *jac = (PC_Composite*)pc->data;
2945fd66863SKarl Rupp 
2954b9ad928SBarry Smith   PetscFunctionBegin;
2964b9ad928SBarry Smith   jac->alpha = alpha;
2974b9ad928SBarry Smith   PetscFunctionReturn(0);
2984b9ad928SBarry Smith }
2994b9ad928SBarry Smith 
3001e6b0712SBarry Smith static PetscErrorCode  PCCompositeSetType_Composite(PC pc,PCCompositeType type)
3014b9ad928SBarry Smith {
302fad69fbaSJed Brown   PC_Composite *jac = (PC_Composite*)pc->data;
303fad69fbaSJed Brown 
3044b9ad928SBarry Smith   PetscFunctionBegin;
3054b9ad928SBarry Smith   if (type == PC_COMPOSITE_ADDITIVE) {
3064b9ad928SBarry Smith     pc->ops->apply          = PCApply_Composite_Additive;
3072533e041SBarry Smith     pc->ops->applytranspose = PCApplyTranspose_Composite_Additive;
308421e10b8SBarry Smith   } else if (type ==  PC_COMPOSITE_MULTIPLICATIVE || type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) {
3094b9ad928SBarry Smith     pc->ops->apply          = PCApply_Composite_Multiplicative;
3102533e041SBarry Smith     pc->ops->applytranspose = PCApplyTranspose_Composite_Multiplicative;
3114b9ad928SBarry Smith   } else if (type ==  PC_COMPOSITE_SPECIAL) {
3124b9ad928SBarry Smith     pc->ops->apply          = PCApply_Composite_Special;
3130298fd71SBarry Smith     pc->ops->applytranspose = NULL;
314ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Unkown composite preconditioner type");
315fad69fbaSJed Brown   jac->type = type;
3164b9ad928SBarry Smith   PetscFunctionReturn(0);
3174b9ad928SBarry Smith }
3184b9ad928SBarry Smith 
319c60c7ad4SBarry Smith static PetscErrorCode  PCCompositeGetType_Composite(PC pc,PCCompositeType *type)
320c60c7ad4SBarry Smith {
321c60c7ad4SBarry Smith   PC_Composite *jac = (PC_Composite*)pc->data;
322c60c7ad4SBarry Smith 
323c60c7ad4SBarry Smith   PetscFunctionBegin;
324c60c7ad4SBarry Smith   *type = jac->type;
325c60c7ad4SBarry Smith   PetscFunctionReturn(0);
326c60c7ad4SBarry Smith }
327c60c7ad4SBarry Smith 
3281e6b0712SBarry Smith static PetscErrorCode  PCCompositeAddPC_Composite(PC pc,PCType type)
3294b9ad928SBarry Smith {
3304b9ad928SBarry Smith   PC_Composite     *jac;
3315a9f2f41SSatish Balay   PC_CompositeLink next,ilink;
332dfbe8321SBarry Smith   PetscErrorCode   ierr;
33379416396SBarry Smith   PetscInt         cnt = 0;
3342dcb1b2aSMatthew Knepley   const char       *prefix;
335*d726e3a5SJed Brown   char             newprefix[20];
3364b9ad928SBarry Smith 
3374b9ad928SBarry Smith   PetscFunctionBegin;
338b00a9115SJed Brown   ierr        = PetscNewLog(pc,&ilink);CHKERRQ(ierr);
3395a9f2f41SSatish Balay   ilink->next = 0;
340ce94432eSBarry Smith   ierr        = PCCreate(PetscObjectComm((PetscObject)pc),&ilink->pc);CHKERRQ(ierr);
341ace3abfcSBarry Smith   ierr        = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->pc);CHKERRQ(ierr);
3424b9ad928SBarry Smith 
3434b9ad928SBarry Smith   jac  = (PC_Composite*)pc->data;
3444b9ad928SBarry Smith   next = jac->head;
3454b9ad928SBarry Smith   if (!next) {
3465a9f2f41SSatish Balay     jac->head       = ilink;
3470298fd71SBarry Smith     ilink->previous = NULL;
3484b9ad928SBarry Smith   } else {
3494b9ad928SBarry Smith     cnt++;
3504b9ad928SBarry Smith     while (next->next) {
3514b9ad928SBarry Smith       next = next->next;
3524b9ad928SBarry Smith       cnt++;
3534b9ad928SBarry Smith     }
3545a9f2f41SSatish Balay     next->next      = ilink;
355421e10b8SBarry Smith     ilink->previous = next;
3564b9ad928SBarry Smith   }
3574b9ad928SBarry Smith   ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
3585a9f2f41SSatish Balay   ierr = PCSetOptionsPrefix(ilink->pc,prefix);CHKERRQ(ierr);
35913f74950SBarry Smith   sprintf(newprefix,"sub_%d_",(int)cnt);
3605a9f2f41SSatish Balay   ierr = PCAppendOptionsPrefix(ilink->pc,newprefix);CHKERRQ(ierr);
3614b9ad928SBarry Smith   /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */
3625a9f2f41SSatish Balay   ierr = PCSetType(ilink->pc,type);CHKERRQ(ierr);
3634b9ad928SBarry Smith   PetscFunctionReturn(0);
3644b9ad928SBarry Smith }
3654b9ad928SBarry Smith 
3668e6eba06SBarry Smith static PetscErrorCode  PCCompositeGetNumberPC_Composite(PC pc,PetscInt *n)
3678e6eba06SBarry Smith {
3688e6eba06SBarry Smith   PC_Composite     *jac;
3698e6eba06SBarry Smith   PC_CompositeLink next;
3708e6eba06SBarry Smith 
3718e6eba06SBarry Smith   PetscFunctionBegin;
3728e6eba06SBarry Smith   jac  = (PC_Composite*)pc->data;
3738e6eba06SBarry Smith   next = jac->head;
3748e6eba06SBarry Smith   *n = 0;
3758e6eba06SBarry Smith   while (next) {
3768e6eba06SBarry Smith     next = next->next;
3778e6eba06SBarry Smith     (*n) ++;
3788e6eba06SBarry Smith   }
3798e6eba06SBarry Smith   PetscFunctionReturn(0);
3808e6eba06SBarry Smith }
3818e6eba06SBarry Smith 
3821e6b0712SBarry Smith static PetscErrorCode  PCCompositeGetPC_Composite(PC pc,PetscInt n,PC *subpc)
3834b9ad928SBarry Smith {
3844b9ad928SBarry Smith   PC_Composite     *jac;
3854b9ad928SBarry Smith   PC_CompositeLink next;
38679416396SBarry Smith   PetscInt         i;
3874b9ad928SBarry Smith 
3884b9ad928SBarry Smith   PetscFunctionBegin;
3894b9ad928SBarry Smith   jac  = (PC_Composite*)pc->data;
3904b9ad928SBarry Smith   next = jac->head;
3914b9ad928SBarry Smith   for (i=0; i<n; i++) {
392ce94432eSBarry Smith     if (!next->next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Not enough PCs in composite preconditioner");
3934b9ad928SBarry Smith     next = next->next;
3944b9ad928SBarry Smith   }
3954b9ad928SBarry Smith   *subpc = next->pc;
3964b9ad928SBarry Smith   PetscFunctionReturn(0);
3974b9ad928SBarry Smith }
3984b9ad928SBarry Smith 
3994b9ad928SBarry Smith /* -------------------------------------------------------------------------------- */
400f39d8e23SSatish Balay /*@
4014b9ad928SBarry Smith    PCCompositeSetType - Sets the type of composite preconditioner.
4024b9ad928SBarry Smith 
403ad4df100SBarry Smith    Logically Collective on PC
4044b9ad928SBarry Smith 
405c60c7ad4SBarry Smith    Input Parameters:
4062a6744ebSBarry Smith +  pc - the preconditioner context
4072a6744ebSBarry Smith -  type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL
4084b9ad928SBarry Smith 
4094b9ad928SBarry Smith    Options Database Key:
4104b9ad928SBarry Smith .  -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type
4114b9ad928SBarry Smith 
4124b9ad928SBarry Smith    Level: Developer
4134b9ad928SBarry Smith 
4144b9ad928SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative
4154b9ad928SBarry Smith @*/
4167087cfbeSBarry Smith PetscErrorCode  PCCompositeSetType(PC pc,PCCompositeType type)
4174b9ad928SBarry Smith {
4187bb14e67SBarry Smith   PetscErrorCode ierr;
4194b9ad928SBarry Smith 
4204b9ad928SBarry Smith   PetscFunctionBegin;
4210700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
422c5eb9154SBarry Smith   PetscValidLogicalCollectiveEnum(pc,type,2);
4237bb14e67SBarry Smith   ierr = PetscTryMethod(pc,"PCCompositeSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr);
4244b9ad928SBarry Smith   PetscFunctionReturn(0);
4254b9ad928SBarry Smith }
4264b9ad928SBarry Smith 
427c60c7ad4SBarry Smith /*@
428721f67b5SBarry Smith    PCCompositeGetType - Gets the type of composite preconditioner.
429c60c7ad4SBarry Smith 
430c60c7ad4SBarry Smith    Logically Collective on PC
431c60c7ad4SBarry Smith 
432c60c7ad4SBarry Smith    Input Parameter:
433c60c7ad4SBarry Smith .  pc - the preconditioner context
434c60c7ad4SBarry Smith 
435c60c7ad4SBarry Smith    Output Parameter:
436c60c7ad4SBarry Smith .  type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL
437c60c7ad4SBarry Smith 
438c60c7ad4SBarry Smith    Options Database Key:
439c60c7ad4SBarry Smith .  -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type
440c60c7ad4SBarry Smith 
441c60c7ad4SBarry Smith    Level: Developer
442c60c7ad4SBarry Smith 
443c60c7ad4SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative
444c60c7ad4SBarry Smith @*/
445c60c7ad4SBarry Smith PetscErrorCode  PCCompositeGetType(PC pc,PCCompositeType *type)
446c60c7ad4SBarry Smith {
447c60c7ad4SBarry Smith   PetscErrorCode ierr;
448c60c7ad4SBarry Smith 
449c60c7ad4SBarry Smith   PetscFunctionBegin;
450c60c7ad4SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
451c60c7ad4SBarry Smith   ierr = PetscUseMethod(pc,"PCCompositeGetType_C",(PC,PCCompositeType*),(pc,type));CHKERRQ(ierr);
452c60c7ad4SBarry Smith   PetscFunctionReturn(0);
453c60c7ad4SBarry Smith }
454c60c7ad4SBarry Smith 
455f39d8e23SSatish Balay /*@
4564b9ad928SBarry Smith    PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner
4574b9ad928SBarry Smith      for alphaI + R + S
4584b9ad928SBarry Smith 
459ad4df100SBarry Smith    Logically Collective on PC
4604b9ad928SBarry Smith 
4614b9ad928SBarry Smith    Input Parameter:
4624b9ad928SBarry Smith +  pc - the preconditioner context
4634b9ad928SBarry Smith -  alpha - scale on identity
4644b9ad928SBarry Smith 
4654b9ad928SBarry Smith    Level: Developer
4664b9ad928SBarry Smith 
4674b9ad928SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative
4684b9ad928SBarry Smith @*/
4697087cfbeSBarry Smith PetscErrorCode  PCCompositeSpecialSetAlpha(PC pc,PetscScalar alpha)
4704b9ad928SBarry Smith {
4714ac538c5SBarry Smith   PetscErrorCode ierr;
4724b9ad928SBarry Smith 
4734b9ad928SBarry Smith   PetscFunctionBegin;
4740700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
475c5eb9154SBarry Smith   PetscValidLogicalCollectiveScalar(pc,alpha,2);
4764ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCCompositeSpecialSetAlpha_C",(PC,PetscScalar),(pc,alpha));CHKERRQ(ierr);
4774b9ad928SBarry Smith   PetscFunctionReturn(0);
4784b9ad928SBarry Smith }
4794b9ad928SBarry Smith 
4804b9ad928SBarry Smith /*@C
4814b9ad928SBarry Smith    PCCompositeAddPC - Adds another PC to the composite PC.
4824b9ad928SBarry Smith 
4834b9ad928SBarry Smith    Collective on PC
4844b9ad928SBarry Smith 
4854b9ad928SBarry Smith    Input Parameters:
4862a6744ebSBarry Smith +  pc - the preconditioner context
4872a6744ebSBarry Smith -  type - the type of the new preconditioner
4884b9ad928SBarry Smith 
4894b9ad928SBarry Smith    Level: Developer
4904b9ad928SBarry Smith 
4914b9ad928SBarry Smith .keywords: PC, composite preconditioner, add
4924b9ad928SBarry Smith @*/
49319fd82e9SBarry Smith PetscErrorCode  PCCompositeAddPC(PC pc,PCType type)
4944b9ad928SBarry Smith {
4954ac538c5SBarry Smith   PetscErrorCode ierr;
4964b9ad928SBarry Smith 
4974b9ad928SBarry Smith   PetscFunctionBegin;
4980700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
49919fd82e9SBarry Smith   ierr = PetscTryMethod(pc,"PCCompositeAddPC_C",(PC,PCType),(pc,type));CHKERRQ(ierr);
5004b9ad928SBarry Smith   PetscFunctionReturn(0);
5014b9ad928SBarry Smith }
5024b9ad928SBarry Smith 
5038e6eba06SBarry Smith /*@
5048e6eba06SBarry Smith    PCCompositeGetNumberPC - Gets the number of PC objects in the composite PC.
5058e6eba06SBarry Smith 
5068e6eba06SBarry Smith    Not Collective
5078e6eba06SBarry Smith 
5088e6eba06SBarry Smith    Input Parameter:
5098e6eba06SBarry Smith .  pc - the preconditioner context
5108e6eba06SBarry Smith 
5118e6eba06SBarry Smith    Output Parameter:
5128e6eba06SBarry Smith .  num - the number of sub pcs
5138e6eba06SBarry Smith 
5148e6eba06SBarry Smith    Level: Developer
5158e6eba06SBarry Smith 
5168e6eba06SBarry Smith .keywords: PC, get, composite preconditioner, sub preconditioner
5178e6eba06SBarry Smith 
5188e6eba06SBarry Smith .seealso: PCCompositeGetPC()
5198e6eba06SBarry Smith @*/
5208e6eba06SBarry Smith PetscErrorCode  PCCompositeGetNumberPC(PC pc,PetscInt *num)
5218e6eba06SBarry Smith {
5228e6eba06SBarry Smith   PetscErrorCode ierr;
5238e6eba06SBarry Smith 
5248e6eba06SBarry Smith   PetscFunctionBegin;
5258e6eba06SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5268e6eba06SBarry Smith   PetscValidIntPointer(num,2);
5278e6eba06SBarry Smith   ierr = PetscUseMethod(pc,"PCCompositeGetNumberPC_C",(PC,PetscInt*),(pc,num));CHKERRQ(ierr);
5288e6eba06SBarry Smith   PetscFunctionReturn(0);
5298e6eba06SBarry Smith }
5308e6eba06SBarry Smith 
531f39d8e23SSatish Balay /*@
5324b9ad928SBarry Smith    PCCompositeGetPC - Gets one of the PC objects in the composite PC.
5334b9ad928SBarry Smith 
5344b9ad928SBarry Smith    Not Collective
5354b9ad928SBarry Smith 
5364b9ad928SBarry Smith    Input Parameter:
5372a6744ebSBarry Smith +  pc - the preconditioner context
5382a6744ebSBarry Smith -  n - the number of the pc requested
5394b9ad928SBarry Smith 
5404b9ad928SBarry Smith    Output Parameters:
5414b9ad928SBarry Smith .  subpc - the PC requested
5424b9ad928SBarry Smith 
5434b9ad928SBarry Smith    Level: Developer
5444b9ad928SBarry Smith 
5454b9ad928SBarry Smith .keywords: PC, get, composite preconditioner, sub preconditioner
5464b9ad928SBarry Smith 
5478e6eba06SBarry Smith .seealso: PCCompositeAddPC(), PCCompositeGetNumberPC()
5484b9ad928SBarry Smith @*/
5497087cfbeSBarry Smith PetscErrorCode  PCCompositeGetPC(PC pc,PetscInt n,PC *subpc)
5504b9ad928SBarry Smith {
5514ac538c5SBarry Smith   PetscErrorCode ierr;
5524b9ad928SBarry Smith 
5534b9ad928SBarry Smith   PetscFunctionBegin;
5540700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5554482741eSBarry Smith   PetscValidPointer(subpc,3);
5564ac538c5SBarry Smith   ierr = PetscUseMethod(pc,"PCCompositeGetPC_C",(PC,PetscInt,PC*),(pc,n,subpc));CHKERRQ(ierr);
5574b9ad928SBarry Smith   PetscFunctionReturn(0);
5584b9ad928SBarry Smith }
5594b9ad928SBarry Smith 
5604b9ad928SBarry Smith /* -------------------------------------------------------------------------------------------*/
5614b9ad928SBarry Smith 
5624b9ad928SBarry Smith /*MC
5634b9ad928SBarry Smith      PCCOMPOSITE - Build a preconditioner by composing together several preconditioners
5644b9ad928SBarry Smith 
5654b9ad928SBarry Smith    Options Database Keys:
5662eab2d5bSJungho Lee +  -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type
56749517cdeSBarry Smith .  -pc_use_amat - Activates PCSetUseAmat()
56851f519a2SBarry Smith -  -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose
5694b9ad928SBarry Smith 
5704b9ad928SBarry Smith    Level: intermediate
5714b9ad928SBarry Smith 
5724b9ad928SBarry Smith    Concepts: composing solvers
5734b9ad928SBarry Smith 
5744b9ad928SBarry Smith    Notes: To use a Krylov method inside the composite preconditioner, set the PCType of one or more
5754b9ad928SBarry Smith           inner PCs to be PCKSP.
5764b9ad928SBarry Smith           Using a Krylov method inside another Krylov method can be dangerous (you get divergence or
577b3ef52cdSBarry Smith           the incorrect answer) unless you use KSPFGMRES as the outer Krylov method
5784b9ad928SBarry Smith 
5794b9ad928SBarry Smith 
5804b9ad928SBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
5814b9ad928SBarry Smith            PCSHELL, PCKSP, PCCompositeSetType(), PCCompositeSpecialSetAlpha(), PCCompositeAddPC(),
58249517cdeSBarry Smith            PCCompositeGetPC(), PCSetUseAmat()
5834b9ad928SBarry Smith 
5844b9ad928SBarry Smith M*/
5854b9ad928SBarry Smith 
5868cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc)
5874b9ad928SBarry Smith {
588dfbe8321SBarry Smith   PetscErrorCode ierr;
5894b9ad928SBarry Smith   PC_Composite   *jac;
5904b9ad928SBarry Smith 
5914b9ad928SBarry Smith   PetscFunctionBegin;
592b00a9115SJed Brown   ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr);
5932fa5cd67SKarl Rupp 
5944b9ad928SBarry Smith   pc->ops->apply           = PCApply_Composite_Additive;
5952533e041SBarry Smith   pc->ops->applytranspose  = PCApplyTranspose_Composite_Additive;
5964b9ad928SBarry Smith   pc->ops->setup           = PCSetUp_Composite;
59769d2c0f9SBarry Smith   pc->ops->reset           = PCReset_Composite;
5984b9ad928SBarry Smith   pc->ops->destroy         = PCDestroy_Composite;
5994b9ad928SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_Composite;
6004b9ad928SBarry Smith   pc->ops->view            = PCView_Composite;
6014b9ad928SBarry Smith   pc->ops->applyrichardson = 0;
6024b9ad928SBarry Smith 
6034b9ad928SBarry Smith   pc->data   = (void*)jac;
6044b9ad928SBarry Smith   jac->type  = PC_COMPOSITE_ADDITIVE;
6054b9ad928SBarry Smith   jac->work1 = 0;
6064b9ad928SBarry Smith   jac->work2 = 0;
6074b9ad928SBarry Smith   jac->head  = 0;
6084b9ad928SBarry Smith 
609bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSetType_C",PCCompositeSetType_Composite);CHKERRQ(ierr);
610c60c7ad4SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetType_C",PCCompositeGetType_Composite);CHKERRQ(ierr);
611bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPC_C",PCCompositeAddPC_Composite);CHKERRQ(ierr);
6128e6eba06SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetNumberPC_C",PCCompositeGetNumberPC_Composite);CHKERRQ(ierr);
613bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetPC_C",PCCompositeGetPC_Composite);CHKERRQ(ierr);
614bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSpecialSetAlpha_C",PCCompositeSpecialSetAlpha_Composite);CHKERRQ(ierr);
6154b9ad928SBarry Smith   PetscFunctionReturn(0);
6164b9ad928SBarry Smith }
6174b9ad928SBarry Smith 
618