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 234b9ad928SBarry Smith #undef __FUNCT__ 244b9ad928SBarry Smith #define __FUNCT__ "PCApply_Composite_Multiplicative" 256849ba73SBarry Smith static PetscErrorCode PCApply_Composite_Multiplicative(PC pc,Vec x,Vec y) 264b9ad928SBarry Smith { 27dfbe8321SBarry Smith PetscErrorCode ierr; 284b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 294b9ad928SBarry Smith PC_CompositeLink next = jac->head; 304b9ad928SBarry Smith Mat mat = pc->pmat; 314b9ad928SBarry Smith 324b9ad928SBarry Smith PetscFunctionBegin; 33*450d59ebSPatrick Farrell 34ce94432eSBarry Smith if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs"); 35*450d59ebSPatrick Farrell 36*450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 37*450d59ebSPatrick Farrell while (next) { 38*450d59ebSPatrick Farrell ierr = PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);CHKERRQ(ierr); 39*450d59ebSPatrick Farrell next = next->next; 40*450d59ebSPatrick Farrell } 41*450d59ebSPatrick Farrell next = jac->head; 42*450d59ebSPatrick Farrell 434b9ad928SBarry Smith if (next->next && !jac->work2) { /* allocate second work vector */ 444b9ad928SBarry Smith ierr = VecDuplicate(jac->work1,&jac->work2);CHKERRQ(ierr); 454b9ad928SBarry Smith } 4649517cdeSBarry Smith if (pc->useAmat) mat = pc->mat; 4709b21952SJed Brown ierr = PCApply(next->pc,x,y);CHKERRQ(ierr); /* y <- B x */ 484b9ad928SBarry Smith while (next->next) { 494b9ad928SBarry Smith next = next->next; 5009b21952SJed Brown ierr = MatMult(mat,y,jac->work1);CHKERRQ(ierr); /* work1 <- A y */ 5109b21952SJed Brown ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr); /* work2 <- x - work1 */ 5251f519a2SBarry Smith ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr); /* zero since some PC's may not set all entries in the result */ 5309b21952SJed Brown ierr = PCApply(next->pc,jac->work2,jac->work1);CHKERRQ(ierr); /* work1 <- C work2 */ 5409b21952SJed 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 */ 554b9ad928SBarry Smith } 56421e10b8SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 57421e10b8SBarry Smith while (next->previous) { 58421e10b8SBarry Smith next = next->previous; 59421e10b8SBarry Smith ierr = MatMult(mat,y,jac->work1);CHKERRQ(ierr); 60421e10b8SBarry Smith ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr); 61421e10b8SBarry Smith ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr); /* zero since some PC's may not set all entries in the result */ 62421e10b8SBarry Smith ierr = PCApply(next->pc,jac->work2,jac->work1);CHKERRQ(ierr); 63421e10b8SBarry Smith ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr); 64421e10b8SBarry Smith } 65421e10b8SBarry Smith } 664b9ad928SBarry Smith PetscFunctionReturn(0); 674b9ad928SBarry Smith } 684b9ad928SBarry Smith 692533e041SBarry Smith #undef __FUNCT__ 702533e041SBarry Smith #define __FUNCT__ "PCApplyTranspose_Composite_Multiplicative" 712533e041SBarry Smith static PetscErrorCode PCApplyTranspose_Composite_Multiplicative(PC pc,Vec x,Vec y) 722533e041SBarry Smith { 732533e041SBarry Smith PetscErrorCode ierr; 742533e041SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 752533e041SBarry Smith PC_CompositeLink next = jac->head; 762533e041SBarry Smith Mat mat = pc->pmat; 772533e041SBarry Smith 782533e041SBarry Smith PetscFunctionBegin; 79ce94432eSBarry Smith if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs"); 802533e041SBarry Smith if (next->next && !jac->work2) { /* allocate second work vector */ 812533e041SBarry Smith ierr = VecDuplicate(jac->work1,&jac->work2);CHKERRQ(ierr); 822533e041SBarry Smith } 8349517cdeSBarry Smith if (pc->useAmat) mat = pc->mat; 842533e041SBarry Smith /* locate last PC */ 852533e041SBarry Smith while (next->next) { 862533e041SBarry Smith next = next->next; 872533e041SBarry Smith } 882533e041SBarry Smith ierr = PCApplyTranspose(next->pc,x,y);CHKERRQ(ierr); 892533e041SBarry Smith while (next->previous) { 902533e041SBarry Smith next = next->previous; 912533e041SBarry Smith ierr = MatMultTranspose(mat,y,jac->work1);CHKERRQ(ierr); 922533e041SBarry Smith ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr); 932533e041SBarry Smith ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr); /* zero since some PC's may not set all entries in the result */ 942533e041SBarry Smith ierr = PCApplyTranspose(next->pc,jac->work2,jac->work1);CHKERRQ(ierr); 952533e041SBarry Smith ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr); 962533e041SBarry Smith } 972533e041SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 982533e041SBarry Smith next = jac->head; 992533e041SBarry Smith while (next->next) { 1002533e041SBarry Smith next = next->next; 1012533e041SBarry Smith ierr = MatMultTranspose(mat,y,jac->work1);CHKERRQ(ierr); 1022533e041SBarry Smith ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr); 1032533e041SBarry Smith ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr); /* zero since some PC's may not set all entries in the result */ 1042533e041SBarry Smith ierr = PCApplyTranspose(next->pc,jac->work2,jac->work1);CHKERRQ(ierr); 1052533e041SBarry Smith ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr); 1062533e041SBarry Smith } 1072533e041SBarry Smith } 1082533e041SBarry Smith PetscFunctionReturn(0); 1092533e041SBarry Smith } 1102533e041SBarry Smith 1114b9ad928SBarry Smith /* 1124b9ad928SBarry Smith This is very special for a matrix of the form alpha I + R + S 1134b9ad928SBarry Smith where first preconditioner is built from alpha I + S and second from 1144b9ad928SBarry Smith alpha I + R 1154b9ad928SBarry Smith */ 1164b9ad928SBarry Smith #undef __FUNCT__ 1174b9ad928SBarry Smith #define __FUNCT__ "PCApply_Composite_Special" 1186849ba73SBarry Smith static PetscErrorCode PCApply_Composite_Special(PC pc,Vec x,Vec y) 1194b9ad928SBarry Smith { 120dfbe8321SBarry Smith PetscErrorCode ierr; 1214b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 1224b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1234b9ad928SBarry Smith 1244b9ad928SBarry Smith PetscFunctionBegin; 125ce94432eSBarry Smith if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs"); 126ce94432eSBarry Smith if (!next->next || next->next->next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Special composite preconditioners requires exactly two PCs"); 1274b9ad928SBarry Smith 128*450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 129*450d59ebSPatrick Farrell ierr = PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);CHKERRQ(ierr); 130*450d59ebSPatrick Farrell ierr = PCSetReusePreconditioner(next->next->pc,pc->reusepreconditioner);CHKERRQ(ierr); 131*450d59ebSPatrick Farrell 132d8fd42c4SBarry Smith ierr = PCApply(next->pc,x,jac->work1);CHKERRQ(ierr); 133d8fd42c4SBarry Smith ierr = PCApply(next->next->pc,jac->work1,y);CHKERRQ(ierr); 1344b9ad928SBarry Smith PetscFunctionReturn(0); 1354b9ad928SBarry Smith } 1364b9ad928SBarry Smith 1374b9ad928SBarry Smith #undef __FUNCT__ 1384b9ad928SBarry Smith #define __FUNCT__ "PCApply_Composite_Additive" 1396849ba73SBarry Smith static PetscErrorCode PCApply_Composite_Additive(PC pc,Vec x,Vec y) 1404b9ad928SBarry Smith { 141dfbe8321SBarry Smith PetscErrorCode ierr; 1424b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 1434b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1444b9ad928SBarry Smith 1454b9ad928SBarry Smith PetscFunctionBegin; 146ce94432eSBarry Smith if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs"); 147*450d59ebSPatrick Farrell 148*450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 149*450d59ebSPatrick Farrell while (next) { 150*450d59ebSPatrick Farrell ierr = PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);CHKERRQ(ierr); 151*450d59ebSPatrick Farrell next = next->next; 152*450d59ebSPatrick Farrell } 153*450d59ebSPatrick Farrell next = jac->head; 154*450d59ebSPatrick Farrell 155d8fd42c4SBarry Smith ierr = PCApply(next->pc,x,y);CHKERRQ(ierr); 1564b9ad928SBarry Smith while (next->next) { 1574b9ad928SBarry Smith next = next->next; 15851f519a2SBarry Smith ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr); /* zero since some PC's may not set all entries in the result */ 159d8fd42c4SBarry Smith ierr = PCApply(next->pc,x,jac->work1);CHKERRQ(ierr); 160efb30889SBarry Smith ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr); 1614b9ad928SBarry Smith } 1624b9ad928SBarry Smith PetscFunctionReturn(0); 1634b9ad928SBarry Smith } 1644b9ad928SBarry Smith 1654b9ad928SBarry Smith #undef __FUNCT__ 1662533e041SBarry Smith #define __FUNCT__ "PCApplyTranspose_Composite_Additive" 1672533e041SBarry Smith static PetscErrorCode PCApplyTranspose_Composite_Additive(PC pc,Vec x,Vec y) 1682533e041SBarry Smith { 1692533e041SBarry Smith PetscErrorCode ierr; 1702533e041SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 1712533e041SBarry Smith PC_CompositeLink next = jac->head; 1722533e041SBarry Smith 1732533e041SBarry Smith PetscFunctionBegin; 174ce94432eSBarry Smith if (!next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPC() or -pc_composite_pcs"); 1752533e041SBarry Smith ierr = PCApplyTranspose(next->pc,x,y);CHKERRQ(ierr); 1762533e041SBarry Smith while (next->next) { 1772533e041SBarry Smith next = next->next; 1782533e041SBarry Smith ierr = VecSet(jac->work1,0.0);CHKERRQ(ierr); /* zero since some PC's may not set all entries in the result */ 1792533e041SBarry Smith ierr = PCApplyTranspose(next->pc,x,jac->work1);CHKERRQ(ierr); 1802533e041SBarry Smith ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr); 1812533e041SBarry Smith } 1822533e041SBarry Smith PetscFunctionReturn(0); 1832533e041SBarry Smith } 1842533e041SBarry Smith 1852533e041SBarry Smith #undef __FUNCT__ 1864b9ad928SBarry Smith #define __FUNCT__ "PCSetUp_Composite" 1876849ba73SBarry Smith static PetscErrorCode PCSetUp_Composite(PC pc) 1884b9ad928SBarry Smith { 189dfbe8321SBarry Smith PetscErrorCode ierr; 1904b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 1914b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1924b9ad928SBarry Smith 1934b9ad928SBarry Smith PetscFunctionBegin; 1944b9ad928SBarry Smith if (!jac->work1) { 1952a7a6963SBarry Smith ierr = MatCreateVecs(pc->pmat,&jac->work1,0);CHKERRQ(ierr); 1964b9ad928SBarry Smith } 1974b9ad928SBarry Smith while (next) { 19823ee1639SBarry Smith ierr = PCSetOperators(next->pc,pc->mat,pc->pmat);CHKERRQ(ierr); 1994b9ad928SBarry Smith next = next->next; 2004b9ad928SBarry Smith } 2014b9ad928SBarry Smith PetscFunctionReturn(0); 2024b9ad928SBarry Smith } 2034b9ad928SBarry Smith 2044b9ad928SBarry Smith #undef __FUNCT__ 20569d2c0f9SBarry Smith #define __FUNCT__ "PCReset_Composite" 20669d2c0f9SBarry Smith static PetscErrorCode PCReset_Composite(PC pc) 20769d2c0f9SBarry Smith { 20869d2c0f9SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 20969d2c0f9SBarry Smith PetscErrorCode ierr; 2105f48b12bSBarry Smith PC_CompositeLink next = jac->head; 21169d2c0f9SBarry Smith 21269d2c0f9SBarry Smith PetscFunctionBegin; 21369d2c0f9SBarry Smith while (next) { 21469d2c0f9SBarry Smith ierr = PCReset(next->pc);CHKERRQ(ierr); 21569d2c0f9SBarry Smith next = next->next; 21669d2c0f9SBarry Smith } 2176bf464f9SBarry Smith ierr = VecDestroy(&jac->work1);CHKERRQ(ierr); 2186bf464f9SBarry Smith ierr = VecDestroy(&jac->work2);CHKERRQ(ierr); 21969d2c0f9SBarry Smith PetscFunctionReturn(0); 22069d2c0f9SBarry Smith } 22169d2c0f9SBarry Smith 22269d2c0f9SBarry Smith #undef __FUNCT__ 2234b9ad928SBarry Smith #define __FUNCT__ "PCDestroy_Composite" 2246849ba73SBarry Smith static PetscErrorCode PCDestroy_Composite(PC pc) 2254b9ad928SBarry Smith { 2264b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 227dfbe8321SBarry Smith PetscErrorCode ierr; 228724c2c99SHong Zhang PC_CompositeLink next = jac->head,next_tmp; 2294b9ad928SBarry Smith 2304b9ad928SBarry Smith PetscFunctionBegin; 23169d2c0f9SBarry Smith ierr = PCReset_Composite(pc);CHKERRQ(ierr); 2324b9ad928SBarry Smith while (next) { 2336bf464f9SBarry Smith ierr = PCDestroy(&next->pc);CHKERRQ(ierr); 234724c2c99SHong Zhang next_tmp = next; 2354b9ad928SBarry Smith next = next->next; 236724c2c99SHong Zhang ierr = PetscFree(next_tmp);CHKERRQ(ierr); 2374b9ad928SBarry Smith } 238c31cb41cSBarry Smith ierr = PetscFree(pc->data);CHKERRQ(ierr); 2394b9ad928SBarry Smith PetscFunctionReturn(0); 2404b9ad928SBarry Smith } 2414b9ad928SBarry Smith 2424b9ad928SBarry Smith #undef __FUNCT__ 2434b9ad928SBarry Smith #define __FUNCT__ "PCSetFromOptions_Composite" 2448c34d3f5SBarry Smith static PetscErrorCode PCSetFromOptions_Composite(PetscOptions *PetscOptionsObject,PC pc) 2454b9ad928SBarry Smith { 2464b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 247dfbe8321SBarry Smith PetscErrorCode ierr; 2489dcbbd2bSBarry Smith PetscInt nmax = 8,i; 2494b9ad928SBarry Smith PC_CompositeLink next; 250e5999256SBarry Smith char *pcs[8]; 251ace3abfcSBarry Smith PetscBool flg; 2524b9ad928SBarry Smith 2534b9ad928SBarry Smith PetscFunctionBegin; 254e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"Composite preconditioner options");CHKERRQ(ierr); 2559dcbbd2bSBarry Smith ierr = PetscOptionsEnum("-pc_composite_type","Type of composition","PCCompositeSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&jac->type,&flg);CHKERRQ(ierr); 25651f519a2SBarry Smith if (flg) { 25751f519a2SBarry Smith ierr = PCCompositeSetType(pc,jac->type);CHKERRQ(ierr); 25851f519a2SBarry Smith } 2594b9ad928SBarry Smith ierr = PetscOptionsStringArray("-pc_composite_pcs","List of composite solvers","PCCompositeAddPC",pcs,&nmax,&flg);CHKERRQ(ierr); 2604b9ad928SBarry Smith if (flg) { 2614b9ad928SBarry Smith for (i=0; i<nmax; i++) { 2624b9ad928SBarry Smith ierr = PCCompositeAddPC(pc,pcs[i]);CHKERRQ(ierr); 263724c2c99SHong Zhang ierr = PetscFree(pcs[i]);CHKERRQ(ierr); /* deallocate string pcs[i], which is allocated in PetscOptionsStringArray() */ 2644b9ad928SBarry Smith } 2654b9ad928SBarry Smith } 2664b9ad928SBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 2674b9ad928SBarry Smith 2684b9ad928SBarry Smith next = jac->head; 2694b9ad928SBarry Smith while (next) { 2704b9ad928SBarry Smith ierr = PCSetFromOptions(next->pc);CHKERRQ(ierr); 2714b9ad928SBarry Smith next = next->next; 2724b9ad928SBarry Smith } 2734b9ad928SBarry Smith PetscFunctionReturn(0); 2744b9ad928SBarry Smith } 2754b9ad928SBarry Smith 2764b9ad928SBarry Smith #undef __FUNCT__ 2774b9ad928SBarry Smith #define __FUNCT__ "PCView_Composite" 2786849ba73SBarry Smith static PetscErrorCode PCView_Composite(PC pc,PetscViewer viewer) 2794b9ad928SBarry Smith { 2804b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 281dfbe8321SBarry Smith PetscErrorCode ierr; 2824b9ad928SBarry Smith PC_CompositeLink next = jac->head; 283ace3abfcSBarry Smith PetscBool iascii; 2844b9ad928SBarry Smith 2854b9ad928SBarry Smith PetscFunctionBegin; 286251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 28732077d6dSBarry Smith if (iascii) { 2889dcbbd2bSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Composite PC type - %s\n",PCCompositeTypes[jac->type]);CHKERRQ(ierr); 2894b9ad928SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"PCs on composite preconditioner follow\n");CHKERRQ(ierr); 2904b9ad928SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"---------------------------------\n");CHKERRQ(ierr); 2914b9ad928SBarry Smith } 29232077d6dSBarry Smith if (iascii) { 2934b9ad928SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 2944b9ad928SBarry Smith } 2954b9ad928SBarry Smith while (next) { 2964b9ad928SBarry Smith ierr = PCView(next->pc,viewer);CHKERRQ(ierr); 2974b9ad928SBarry Smith next = next->next; 2984b9ad928SBarry Smith } 29932077d6dSBarry Smith if (iascii) { 3004b9ad928SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 3014b9ad928SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"---------------------------------\n");CHKERRQ(ierr); 3024b9ad928SBarry Smith } 3034b9ad928SBarry Smith PetscFunctionReturn(0); 3044b9ad928SBarry Smith } 3054b9ad928SBarry Smith 3064b9ad928SBarry Smith /* ------------------------------------------------------------------------------*/ 3074b9ad928SBarry Smith 3084b9ad928SBarry Smith #undef __FUNCT__ 3094b9ad928SBarry Smith #define __FUNCT__ "PCCompositeSpecialSetAlpha_Composite" 3101e6b0712SBarry Smith static PetscErrorCode PCCompositeSpecialSetAlpha_Composite(PC pc,PetscScalar alpha) 3114b9ad928SBarry Smith { 3124b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 3135fd66863SKarl Rupp 3144b9ad928SBarry Smith PetscFunctionBegin; 3154b9ad928SBarry Smith jac->alpha = alpha; 3164b9ad928SBarry Smith PetscFunctionReturn(0); 3174b9ad928SBarry Smith } 3184b9ad928SBarry Smith 3194b9ad928SBarry Smith #undef __FUNCT__ 3204b9ad928SBarry Smith #define __FUNCT__ "PCCompositeSetType_Composite" 3211e6b0712SBarry Smith static PetscErrorCode PCCompositeSetType_Composite(PC pc,PCCompositeType type) 3224b9ad928SBarry Smith { 323fad69fbaSJed Brown PC_Composite *jac = (PC_Composite*)pc->data; 324fad69fbaSJed Brown 3254b9ad928SBarry Smith PetscFunctionBegin; 3264b9ad928SBarry Smith if (type == PC_COMPOSITE_ADDITIVE) { 3274b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 3282533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 329421e10b8SBarry Smith } else if (type == PC_COMPOSITE_MULTIPLICATIVE || type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 3304b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Multiplicative; 3312533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Multiplicative; 3324b9ad928SBarry Smith } else if (type == PC_COMPOSITE_SPECIAL) { 3334b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Special; 3340298fd71SBarry Smith pc->ops->applytranspose = NULL; 335ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Unkown composite preconditioner type"); 336fad69fbaSJed Brown jac->type = type; 3374b9ad928SBarry Smith PetscFunctionReturn(0); 3384b9ad928SBarry Smith } 3394b9ad928SBarry Smith 3404b9ad928SBarry Smith #undef __FUNCT__ 341c60c7ad4SBarry Smith #define __FUNCT__ "PCCompositeGetType_Composite" 342c60c7ad4SBarry Smith static PetscErrorCode PCCompositeGetType_Composite(PC pc,PCCompositeType *type) 343c60c7ad4SBarry Smith { 344c60c7ad4SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 345c60c7ad4SBarry Smith 346c60c7ad4SBarry Smith PetscFunctionBegin; 347c60c7ad4SBarry Smith *type = jac->type; 348c60c7ad4SBarry Smith PetscFunctionReturn(0); 349c60c7ad4SBarry Smith } 350c60c7ad4SBarry Smith 351c60c7ad4SBarry Smith #undef __FUNCT__ 3524b9ad928SBarry Smith #define __FUNCT__ "PCCompositeAddPC_Composite" 3531e6b0712SBarry Smith static PetscErrorCode PCCompositeAddPC_Composite(PC pc,PCType type) 3544b9ad928SBarry Smith { 3554b9ad928SBarry Smith PC_Composite *jac; 3565a9f2f41SSatish Balay PC_CompositeLink next,ilink; 357dfbe8321SBarry Smith PetscErrorCode ierr; 35879416396SBarry Smith PetscInt cnt = 0; 3592dcb1b2aSMatthew Knepley const char *prefix; 3602dcb1b2aSMatthew Knepley char newprefix[8]; 3614b9ad928SBarry Smith 3624b9ad928SBarry Smith PetscFunctionBegin; 363b00a9115SJed Brown ierr = PetscNewLog(pc,&ilink);CHKERRQ(ierr); 3645a9f2f41SSatish Balay ilink->next = 0; 365ce94432eSBarry Smith ierr = PCCreate(PetscObjectComm((PetscObject)pc),&ilink->pc);CHKERRQ(ierr); 366ace3abfcSBarry Smith ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ilink->pc);CHKERRQ(ierr); 3674b9ad928SBarry Smith 3684b9ad928SBarry Smith jac = (PC_Composite*)pc->data; 3694b9ad928SBarry Smith next = jac->head; 3704b9ad928SBarry Smith if (!next) { 3715a9f2f41SSatish Balay jac->head = ilink; 3720298fd71SBarry Smith ilink->previous = NULL; 3734b9ad928SBarry Smith } else { 3744b9ad928SBarry Smith cnt++; 3754b9ad928SBarry Smith while (next->next) { 3764b9ad928SBarry Smith next = next->next; 3774b9ad928SBarry Smith cnt++; 3784b9ad928SBarry Smith } 3795a9f2f41SSatish Balay next->next = ilink; 380421e10b8SBarry Smith ilink->previous = next; 3814b9ad928SBarry Smith } 3824b9ad928SBarry Smith ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 3835a9f2f41SSatish Balay ierr = PCSetOptionsPrefix(ilink->pc,prefix);CHKERRQ(ierr); 38413f74950SBarry Smith sprintf(newprefix,"sub_%d_",(int)cnt); 3855a9f2f41SSatish Balay ierr = PCAppendOptionsPrefix(ilink->pc,newprefix);CHKERRQ(ierr); 3864b9ad928SBarry Smith /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */ 3875a9f2f41SSatish Balay ierr = PCSetType(ilink->pc,type);CHKERRQ(ierr); 3884b9ad928SBarry Smith PetscFunctionReturn(0); 3894b9ad928SBarry Smith } 3904b9ad928SBarry Smith 3914b9ad928SBarry Smith #undef __FUNCT__ 3928e6eba06SBarry Smith #define __FUNCT__ "PCCompositeGetNumberPC_Composite" 3938e6eba06SBarry Smith static PetscErrorCode PCCompositeGetNumberPC_Composite(PC pc,PetscInt *n) 3948e6eba06SBarry Smith { 3958e6eba06SBarry Smith PC_Composite *jac; 3968e6eba06SBarry Smith PC_CompositeLink next; 3978e6eba06SBarry Smith 3988e6eba06SBarry Smith PetscFunctionBegin; 3998e6eba06SBarry Smith jac = (PC_Composite*)pc->data; 4008e6eba06SBarry Smith next = jac->head; 4018e6eba06SBarry Smith *n = 0; 4028e6eba06SBarry Smith while (next) { 4038e6eba06SBarry Smith next = next->next; 4048e6eba06SBarry Smith (*n) ++; 4058e6eba06SBarry Smith } 4068e6eba06SBarry Smith PetscFunctionReturn(0); 4078e6eba06SBarry Smith } 4088e6eba06SBarry Smith 4098e6eba06SBarry Smith #undef __FUNCT__ 4104b9ad928SBarry Smith #define __FUNCT__ "PCCompositeGetPC_Composite" 4111e6b0712SBarry Smith static PetscErrorCode PCCompositeGetPC_Composite(PC pc,PetscInt n,PC *subpc) 4124b9ad928SBarry Smith { 4134b9ad928SBarry Smith PC_Composite *jac; 4144b9ad928SBarry Smith PC_CompositeLink next; 41579416396SBarry Smith PetscInt i; 4164b9ad928SBarry Smith 4174b9ad928SBarry Smith PetscFunctionBegin; 4184b9ad928SBarry Smith jac = (PC_Composite*)pc->data; 4194b9ad928SBarry Smith next = jac->head; 4204b9ad928SBarry Smith for (i=0; i<n; i++) { 421ce94432eSBarry Smith if (!next->next) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Not enough PCs in composite preconditioner"); 4224b9ad928SBarry Smith next = next->next; 4234b9ad928SBarry Smith } 4244b9ad928SBarry Smith *subpc = next->pc; 4254b9ad928SBarry Smith PetscFunctionReturn(0); 4264b9ad928SBarry Smith } 4274b9ad928SBarry Smith 4284b9ad928SBarry Smith /* -------------------------------------------------------------------------------- */ 4294b9ad928SBarry Smith #undef __FUNCT__ 4304b9ad928SBarry Smith #define __FUNCT__ "PCCompositeSetType" 431f39d8e23SSatish Balay /*@ 4324b9ad928SBarry Smith PCCompositeSetType - Sets the type of composite preconditioner. 4334b9ad928SBarry Smith 434ad4df100SBarry Smith Logically Collective on PC 4354b9ad928SBarry Smith 436c60c7ad4SBarry Smith Input Parameters: 4372a6744ebSBarry Smith + pc - the preconditioner context 4382a6744ebSBarry Smith - type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL 4394b9ad928SBarry Smith 4404b9ad928SBarry Smith Options Database Key: 4414b9ad928SBarry Smith . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 4424b9ad928SBarry Smith 4434b9ad928SBarry Smith Level: Developer 4444b9ad928SBarry Smith 4454b9ad928SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative 4464b9ad928SBarry Smith @*/ 4477087cfbeSBarry Smith PetscErrorCode PCCompositeSetType(PC pc,PCCompositeType type) 4484b9ad928SBarry Smith { 4497bb14e67SBarry Smith PetscErrorCode ierr; 4504b9ad928SBarry Smith 4514b9ad928SBarry Smith PetscFunctionBegin; 4520700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 453c5eb9154SBarry Smith PetscValidLogicalCollectiveEnum(pc,type,2); 4547bb14e67SBarry Smith ierr = PetscTryMethod(pc,"PCCompositeSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr); 4554b9ad928SBarry Smith PetscFunctionReturn(0); 4564b9ad928SBarry Smith } 4574b9ad928SBarry Smith 4584b9ad928SBarry Smith #undef __FUNCT__ 459c60c7ad4SBarry Smith #define __FUNCT__ "PCCompositeGetType" 460c60c7ad4SBarry Smith /*@ 461721f67b5SBarry Smith PCCompositeGetType - Gets the type of composite preconditioner. 462c60c7ad4SBarry Smith 463c60c7ad4SBarry Smith Logically Collective on PC 464c60c7ad4SBarry Smith 465c60c7ad4SBarry Smith Input Parameter: 466c60c7ad4SBarry Smith . pc - the preconditioner context 467c60c7ad4SBarry Smith 468c60c7ad4SBarry Smith Output Parameter: 469c60c7ad4SBarry Smith . type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL 470c60c7ad4SBarry Smith 471c60c7ad4SBarry Smith Options Database Key: 472c60c7ad4SBarry Smith . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 473c60c7ad4SBarry Smith 474c60c7ad4SBarry Smith Level: Developer 475c60c7ad4SBarry Smith 476c60c7ad4SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative 477c60c7ad4SBarry Smith @*/ 478c60c7ad4SBarry Smith PetscErrorCode PCCompositeGetType(PC pc,PCCompositeType *type) 479c60c7ad4SBarry Smith { 480c60c7ad4SBarry Smith PetscErrorCode ierr; 481c60c7ad4SBarry Smith 482c60c7ad4SBarry Smith PetscFunctionBegin; 483c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 484c60c7ad4SBarry Smith ierr = PetscUseMethod(pc,"PCCompositeGetType_C",(PC,PCCompositeType*),(pc,type));CHKERRQ(ierr); 485c60c7ad4SBarry Smith PetscFunctionReturn(0); 486c60c7ad4SBarry Smith } 487c60c7ad4SBarry Smith 488c60c7ad4SBarry Smith #undef __FUNCT__ 4894b9ad928SBarry Smith #define __FUNCT__ "PCCompositeSpecialSetAlpha" 490f39d8e23SSatish Balay /*@ 4914b9ad928SBarry Smith PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner 4924b9ad928SBarry Smith for alphaI + R + S 4934b9ad928SBarry Smith 494ad4df100SBarry Smith Logically Collective on PC 4954b9ad928SBarry Smith 4964b9ad928SBarry Smith Input Parameter: 4974b9ad928SBarry Smith + pc - the preconditioner context 4984b9ad928SBarry Smith - alpha - scale on identity 4994b9ad928SBarry Smith 5004b9ad928SBarry Smith Level: Developer 5014b9ad928SBarry Smith 5024b9ad928SBarry Smith .keywords: PC, set, type, composite preconditioner, additive, multiplicative 5034b9ad928SBarry Smith @*/ 5047087cfbeSBarry Smith PetscErrorCode PCCompositeSpecialSetAlpha(PC pc,PetscScalar alpha) 5054b9ad928SBarry Smith { 5064ac538c5SBarry Smith PetscErrorCode ierr; 5074b9ad928SBarry Smith 5084b9ad928SBarry Smith PetscFunctionBegin; 5090700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 510c5eb9154SBarry Smith PetscValidLogicalCollectiveScalar(pc,alpha,2); 5114ac538c5SBarry Smith ierr = PetscTryMethod(pc,"PCCompositeSpecialSetAlpha_C",(PC,PetscScalar),(pc,alpha));CHKERRQ(ierr); 5124b9ad928SBarry Smith PetscFunctionReturn(0); 5134b9ad928SBarry Smith } 5144b9ad928SBarry Smith 5154b9ad928SBarry Smith #undef __FUNCT__ 5164b9ad928SBarry Smith #define __FUNCT__ "PCCompositeAddPC" 5174b9ad928SBarry Smith /*@C 5184b9ad928SBarry Smith PCCompositeAddPC - Adds another PC to the composite PC. 5194b9ad928SBarry Smith 5204b9ad928SBarry Smith Collective on PC 5214b9ad928SBarry Smith 5224b9ad928SBarry Smith Input Parameters: 5232a6744ebSBarry Smith + pc - the preconditioner context 5242a6744ebSBarry Smith - type - the type of the new preconditioner 5254b9ad928SBarry Smith 5264b9ad928SBarry Smith Level: Developer 5274b9ad928SBarry Smith 5284b9ad928SBarry Smith .keywords: PC, composite preconditioner, add 5294b9ad928SBarry Smith @*/ 53019fd82e9SBarry Smith PetscErrorCode PCCompositeAddPC(PC pc,PCType type) 5314b9ad928SBarry Smith { 5324ac538c5SBarry Smith PetscErrorCode ierr; 5334b9ad928SBarry Smith 5344b9ad928SBarry Smith PetscFunctionBegin; 5350700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 53619fd82e9SBarry Smith ierr = PetscTryMethod(pc,"PCCompositeAddPC_C",(PC,PCType),(pc,type));CHKERRQ(ierr); 5374b9ad928SBarry Smith PetscFunctionReturn(0); 5384b9ad928SBarry Smith } 5394b9ad928SBarry Smith 5404b9ad928SBarry Smith #undef __FUNCT__ 5418e6eba06SBarry Smith #define __FUNCT__ "PCCompositeGetNumberPC" 5428e6eba06SBarry Smith /*@ 5438e6eba06SBarry Smith PCCompositeGetNumberPC - Gets the number of PC objects in the composite PC. 5448e6eba06SBarry Smith 5458e6eba06SBarry Smith Not Collective 5468e6eba06SBarry Smith 5478e6eba06SBarry Smith Input Parameter: 5488e6eba06SBarry Smith . pc - the preconditioner context 5498e6eba06SBarry Smith 5508e6eba06SBarry Smith Output Parameter: 5518e6eba06SBarry Smith . num - the number of sub pcs 5528e6eba06SBarry Smith 5538e6eba06SBarry Smith Level: Developer 5548e6eba06SBarry Smith 5558e6eba06SBarry Smith .keywords: PC, get, composite preconditioner, sub preconditioner 5568e6eba06SBarry Smith 5578e6eba06SBarry Smith .seealso: PCCompositeGetPC() 5588e6eba06SBarry Smith @*/ 5598e6eba06SBarry Smith PetscErrorCode PCCompositeGetNumberPC(PC pc,PetscInt *num) 5608e6eba06SBarry Smith { 5618e6eba06SBarry Smith PetscErrorCode ierr; 5628e6eba06SBarry Smith 5638e6eba06SBarry Smith PetscFunctionBegin; 5648e6eba06SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 5658e6eba06SBarry Smith PetscValidIntPointer(num,2); 5668e6eba06SBarry Smith ierr = PetscUseMethod(pc,"PCCompositeGetNumberPC_C",(PC,PetscInt*),(pc,num));CHKERRQ(ierr); 5678e6eba06SBarry Smith PetscFunctionReturn(0); 5688e6eba06SBarry Smith } 5698e6eba06SBarry Smith 5708e6eba06SBarry Smith #undef __FUNCT__ 5714b9ad928SBarry Smith #define __FUNCT__ "PCCompositeGetPC" 572f39d8e23SSatish Balay /*@ 5734b9ad928SBarry Smith PCCompositeGetPC - Gets one of the PC objects in the composite PC. 5744b9ad928SBarry Smith 5754b9ad928SBarry Smith Not Collective 5764b9ad928SBarry Smith 5774b9ad928SBarry Smith Input Parameter: 5782a6744ebSBarry Smith + pc - the preconditioner context 5792a6744ebSBarry Smith - n - the number of the pc requested 5804b9ad928SBarry Smith 5814b9ad928SBarry Smith Output Parameters: 5824b9ad928SBarry Smith . subpc - the PC requested 5834b9ad928SBarry Smith 5844b9ad928SBarry Smith Level: Developer 5854b9ad928SBarry Smith 5864b9ad928SBarry Smith .keywords: PC, get, composite preconditioner, sub preconditioner 5874b9ad928SBarry Smith 5888e6eba06SBarry Smith .seealso: PCCompositeAddPC(), PCCompositeGetNumberPC() 5894b9ad928SBarry Smith @*/ 5907087cfbeSBarry Smith PetscErrorCode PCCompositeGetPC(PC pc,PetscInt n,PC *subpc) 5914b9ad928SBarry Smith { 5924ac538c5SBarry Smith PetscErrorCode ierr; 5934b9ad928SBarry Smith 5944b9ad928SBarry Smith PetscFunctionBegin; 5950700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 5964482741eSBarry Smith PetscValidPointer(subpc,3); 5974ac538c5SBarry Smith ierr = PetscUseMethod(pc,"PCCompositeGetPC_C",(PC,PetscInt,PC*),(pc,n,subpc));CHKERRQ(ierr); 5984b9ad928SBarry Smith PetscFunctionReturn(0); 5994b9ad928SBarry Smith } 6004b9ad928SBarry Smith 6014b9ad928SBarry Smith /* -------------------------------------------------------------------------------------------*/ 6024b9ad928SBarry Smith 6034b9ad928SBarry Smith /*MC 6044b9ad928SBarry Smith PCCOMPOSITE - Build a preconditioner by composing together several preconditioners 6054b9ad928SBarry Smith 6064b9ad928SBarry Smith Options Database Keys: 6072eab2d5bSJungho Lee + -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type 60849517cdeSBarry Smith . -pc_use_amat - Activates PCSetUseAmat() 60951f519a2SBarry Smith - -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose 6104b9ad928SBarry Smith 6114b9ad928SBarry Smith Level: intermediate 6124b9ad928SBarry Smith 6134b9ad928SBarry Smith Concepts: composing solvers 6144b9ad928SBarry Smith 6154b9ad928SBarry Smith Notes: To use a Krylov method inside the composite preconditioner, set the PCType of one or more 6164b9ad928SBarry Smith inner PCs to be PCKSP. 6174b9ad928SBarry Smith Using a Krylov method inside another Krylov method can be dangerous (you get divergence or 618b3ef52cdSBarry Smith the incorrect answer) unless you use KSPFGMRES as the outer Krylov method 6194b9ad928SBarry Smith 6204b9ad928SBarry Smith 6214b9ad928SBarry Smith .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 6224b9ad928SBarry Smith PCSHELL, PCKSP, PCCompositeSetType(), PCCompositeSpecialSetAlpha(), PCCompositeAddPC(), 62349517cdeSBarry Smith PCCompositeGetPC(), PCSetUseAmat() 6244b9ad928SBarry Smith 6254b9ad928SBarry Smith M*/ 6264b9ad928SBarry Smith 6274b9ad928SBarry Smith #undef __FUNCT__ 6284b9ad928SBarry Smith #define __FUNCT__ "PCCreate_Composite" 6298cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc) 6304b9ad928SBarry Smith { 631dfbe8321SBarry Smith PetscErrorCode ierr; 6324b9ad928SBarry Smith PC_Composite *jac; 6334b9ad928SBarry Smith 6344b9ad928SBarry Smith PetscFunctionBegin; 635b00a9115SJed Brown ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr); 6362fa5cd67SKarl Rupp 6374b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 6382533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 6394b9ad928SBarry Smith pc->ops->setup = PCSetUp_Composite; 64069d2c0f9SBarry Smith pc->ops->reset = PCReset_Composite; 6414b9ad928SBarry Smith pc->ops->destroy = PCDestroy_Composite; 6424b9ad928SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Composite; 6434b9ad928SBarry Smith pc->ops->view = PCView_Composite; 6444b9ad928SBarry Smith pc->ops->applyrichardson = 0; 6454b9ad928SBarry Smith 6464b9ad928SBarry Smith pc->data = (void*)jac; 6474b9ad928SBarry Smith jac->type = PC_COMPOSITE_ADDITIVE; 6484b9ad928SBarry Smith jac->work1 = 0; 6494b9ad928SBarry Smith jac->work2 = 0; 6504b9ad928SBarry Smith jac->head = 0; 6514b9ad928SBarry Smith 652bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSetType_C",PCCompositeSetType_Composite);CHKERRQ(ierr); 653c60c7ad4SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetType_C",PCCompositeGetType_Composite);CHKERRQ(ierr); 654bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPC_C",PCCompositeAddPC_Composite);CHKERRQ(ierr); 6558e6eba06SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetNumberPC_C",PCCompositeGetNumberPC_Composite);CHKERRQ(ierr); 656bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetPC_C",PCCompositeGetPC_Composite);CHKERRQ(ierr); 657bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSpecialSetAlpha_C",PCCompositeSpecialSetAlpha_Composite);CHKERRQ(ierr); 6584b9ad928SBarry Smith PetscFunctionReturn(0); 6594b9ad928SBarry Smith } 6604b9ad928SBarry Smith 661