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