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 32*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 33450d59ebSPatrick Farrell 34450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 35450d59ebSPatrick Farrell while (next) { 36450d59ebSPatrick Farrell ierr = PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);CHKERRQ(ierr); 37450d59ebSPatrick Farrell next = next->next; 38450d59ebSPatrick Farrell } 39450d59ebSPatrick Farrell next = jac->head; 40450d59ebSPatrick Farrell 414b9ad928SBarry Smith if (next->next && !jac->work2) { /* allocate second work vector */ 424b9ad928SBarry Smith ierr = VecDuplicate(jac->work1,&jac->work2);CHKERRQ(ierr); 434b9ad928SBarry Smith } 4449517cdeSBarry Smith if (pc->useAmat) mat = pc->mat; 4509b21952SJed Brown ierr = PCApply(next->pc,x,y);CHKERRQ(ierr); /* y <- B x */ 464b9ad928SBarry Smith while (next->next) { 474b9ad928SBarry Smith next = next->next; 4809b21952SJed Brown ierr = MatMult(mat,y,jac->work1);CHKERRQ(ierr); /* work1 <- A y */ 4909b21952SJed Brown ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr); /* work2 <- x - work1 */ 5009b21952SJed Brown ierr = PCApply(next->pc,jac->work2,jac->work1);CHKERRQ(ierr); /* work1 <- C work2 */ 5109b21952SJed Brown ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr); /* y <- y + work1 = B x + C (x - A B x) = (B + C (1 - A B)) x */ 524b9ad928SBarry Smith } 53421e10b8SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 54421e10b8SBarry Smith while (next->previous) { 55421e10b8SBarry Smith next = next->previous; 56421e10b8SBarry Smith ierr = MatMult(mat,y,jac->work1);CHKERRQ(ierr); 57421e10b8SBarry Smith ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr); 58421e10b8SBarry Smith ierr = PCApply(next->pc,jac->work2,jac->work1);CHKERRQ(ierr); 59421e10b8SBarry Smith ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr); 60421e10b8SBarry Smith } 61421e10b8SBarry Smith } 624b9ad928SBarry Smith PetscFunctionReturn(0); 634b9ad928SBarry Smith } 644b9ad928SBarry Smith 652533e041SBarry Smith static PetscErrorCode PCApplyTranspose_Composite_Multiplicative(PC pc,Vec x,Vec y) 662533e041SBarry Smith { 672533e041SBarry Smith PetscErrorCode ierr; 682533e041SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 692533e041SBarry Smith PC_CompositeLink next = jac->head; 702533e041SBarry Smith Mat mat = pc->pmat; 712533e041SBarry Smith 722533e041SBarry Smith PetscFunctionBegin; 73*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 742533e041SBarry Smith if (next->next && !jac->work2) { /* allocate second work vector */ 752533e041SBarry Smith ierr = VecDuplicate(jac->work1,&jac->work2);CHKERRQ(ierr); 762533e041SBarry Smith } 7749517cdeSBarry Smith if (pc->useAmat) mat = pc->mat; 782533e041SBarry Smith /* locate last PC */ 792533e041SBarry Smith while (next->next) { 802533e041SBarry Smith next = next->next; 812533e041SBarry Smith } 822533e041SBarry Smith ierr = PCApplyTranspose(next->pc,x,y);CHKERRQ(ierr); 832533e041SBarry Smith while (next->previous) { 842533e041SBarry Smith next = next->previous; 852533e041SBarry Smith ierr = MatMultTranspose(mat,y,jac->work1);CHKERRQ(ierr); 862533e041SBarry Smith ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr); 872533e041SBarry Smith ierr = PCApplyTranspose(next->pc,jac->work2,jac->work1);CHKERRQ(ierr); 882533e041SBarry Smith ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr); 892533e041SBarry Smith } 902533e041SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 912533e041SBarry Smith next = jac->head; 922533e041SBarry Smith while (next->next) { 932533e041SBarry Smith next = next->next; 942533e041SBarry Smith ierr = MatMultTranspose(mat,y,jac->work1);CHKERRQ(ierr); 952533e041SBarry Smith ierr = VecWAXPY(jac->work2,-1.0,jac->work1,x);CHKERRQ(ierr); 962533e041SBarry Smith ierr = PCApplyTranspose(next->pc,jac->work2,jac->work1);CHKERRQ(ierr); 972533e041SBarry Smith ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr); 982533e041SBarry Smith } 992533e041SBarry Smith } 1002533e041SBarry Smith PetscFunctionReturn(0); 1012533e041SBarry Smith } 1022533e041SBarry Smith 1034b9ad928SBarry Smith /* 1044b9ad928SBarry Smith This is very special for a matrix of the form alpha I + R + S 1054b9ad928SBarry Smith where first preconditioner is built from alpha I + S and second from 1064b9ad928SBarry Smith alpha I + R 1074b9ad928SBarry Smith */ 1086849ba73SBarry Smith static PetscErrorCode PCApply_Composite_Special(PC pc,Vec x,Vec y) 1094b9ad928SBarry Smith { 110dfbe8321SBarry Smith PetscErrorCode ierr; 1114b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 1124b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1134b9ad928SBarry Smith 1144b9ad928SBarry Smith PetscFunctionBegin; 115*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 116*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!next->next || next->next->next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Special composite preconditioners requires exactly two PCs"); 1174b9ad928SBarry Smith 118450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 119450d59ebSPatrick Farrell ierr = PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);CHKERRQ(ierr); 120450d59ebSPatrick Farrell ierr = PCSetReusePreconditioner(next->next->pc,pc->reusepreconditioner);CHKERRQ(ierr); 121450d59ebSPatrick Farrell 122d8fd42c4SBarry Smith ierr = PCApply(next->pc,x,jac->work1);CHKERRQ(ierr); 123d8fd42c4SBarry Smith ierr = PCApply(next->next->pc,jac->work1,y);CHKERRQ(ierr); 1244b9ad928SBarry Smith PetscFunctionReturn(0); 1254b9ad928SBarry Smith } 1264b9ad928SBarry Smith 1276849ba73SBarry Smith static PetscErrorCode PCApply_Composite_Additive(PC pc,Vec x,Vec y) 1284b9ad928SBarry Smith { 129dfbe8321SBarry Smith PetscErrorCode ierr; 1304b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 1314b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1324b9ad928SBarry Smith 1334b9ad928SBarry Smith PetscFunctionBegin; 134*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 135450d59ebSPatrick Farrell 136450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 137450d59ebSPatrick Farrell while (next) { 138450d59ebSPatrick Farrell ierr = PCSetReusePreconditioner(next->pc,pc->reusepreconditioner);CHKERRQ(ierr); 139450d59ebSPatrick Farrell next = next->next; 140450d59ebSPatrick Farrell } 141450d59ebSPatrick Farrell next = jac->head; 142450d59ebSPatrick Farrell 143d8fd42c4SBarry Smith ierr = PCApply(next->pc,x,y);CHKERRQ(ierr); 1444b9ad928SBarry Smith while (next->next) { 1454b9ad928SBarry Smith next = next->next; 146d8fd42c4SBarry Smith ierr = PCApply(next->pc,x,jac->work1);CHKERRQ(ierr); 147efb30889SBarry Smith ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr); 1484b9ad928SBarry Smith } 1494b9ad928SBarry Smith PetscFunctionReturn(0); 1504b9ad928SBarry Smith } 1514b9ad928SBarry Smith 1522533e041SBarry Smith static PetscErrorCode PCApplyTranspose_Composite_Additive(PC pc,Vec x,Vec y) 1532533e041SBarry Smith { 1542533e041SBarry Smith PetscErrorCode ierr; 1552533e041SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 1562533e041SBarry Smith PC_CompositeLink next = jac->head; 1572533e041SBarry Smith 1582533e041SBarry Smith PetscFunctionBegin; 159*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 1602533e041SBarry Smith ierr = PCApplyTranspose(next->pc,x,y);CHKERRQ(ierr); 1612533e041SBarry Smith while (next->next) { 1622533e041SBarry Smith next = next->next; 1632533e041SBarry Smith ierr = PCApplyTranspose(next->pc,x,jac->work1);CHKERRQ(ierr); 1642533e041SBarry Smith ierr = VecAXPY(y,1.0,jac->work1);CHKERRQ(ierr); 1652533e041SBarry Smith } 1662533e041SBarry Smith PetscFunctionReturn(0); 1672533e041SBarry Smith } 1682533e041SBarry Smith 1696849ba73SBarry Smith static PetscErrorCode PCSetUp_Composite(PC pc) 1704b9ad928SBarry Smith { 171dfbe8321SBarry Smith PetscErrorCode ierr; 1724b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 1734b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1745a78d018SMatthew G. Knepley DM dm; 1754b9ad928SBarry Smith 1764b9ad928SBarry Smith PetscFunctionBegin; 1774b9ad928SBarry Smith if (!jac->work1) { 1780a545947SLisandro Dalcin ierr = MatCreateVecs(pc->pmat,&jac->work1,NULL);CHKERRQ(ierr); 1794b9ad928SBarry Smith } 1805a78d018SMatthew G. Knepley ierr = PCGetDM(pc,&dm);CHKERRQ(ierr); 1814b9ad928SBarry Smith while (next) { 1822b1d202aSBarry Smith if (!next->pc->dm) { 1835a78d018SMatthew G. Knepley ierr = PCSetDM(next->pc,dm);CHKERRQ(ierr); 1842b1d202aSBarry Smith } 1852b1d202aSBarry Smith if (!next->pc->mat) { 18623ee1639SBarry Smith ierr = PCSetOperators(next->pc,pc->mat,pc->pmat);CHKERRQ(ierr); 1872b1d202aSBarry Smith } 1884b9ad928SBarry Smith next = next->next; 1894b9ad928SBarry Smith } 1904b9ad928SBarry Smith PetscFunctionReturn(0); 1914b9ad928SBarry Smith } 1924b9ad928SBarry Smith 19369d2c0f9SBarry Smith static PetscErrorCode PCReset_Composite(PC pc) 19469d2c0f9SBarry Smith { 19569d2c0f9SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 19669d2c0f9SBarry Smith PetscErrorCode ierr; 1975f48b12bSBarry Smith PC_CompositeLink next = jac->head; 19869d2c0f9SBarry Smith 19969d2c0f9SBarry Smith PetscFunctionBegin; 20069d2c0f9SBarry Smith while (next) { 20169d2c0f9SBarry Smith ierr = PCReset(next->pc);CHKERRQ(ierr); 20269d2c0f9SBarry Smith next = next->next; 20369d2c0f9SBarry Smith } 2046bf464f9SBarry Smith ierr = VecDestroy(&jac->work1);CHKERRQ(ierr); 2056bf464f9SBarry Smith ierr = VecDestroy(&jac->work2);CHKERRQ(ierr); 20669d2c0f9SBarry Smith PetscFunctionReturn(0); 20769d2c0f9SBarry Smith } 20869d2c0f9SBarry Smith 2096849ba73SBarry Smith static PetscErrorCode PCDestroy_Composite(PC pc) 2104b9ad928SBarry Smith { 2114b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 212dfbe8321SBarry Smith PetscErrorCode ierr; 213724c2c99SHong Zhang PC_CompositeLink next = jac->head,next_tmp; 2144b9ad928SBarry Smith 2154b9ad928SBarry Smith PetscFunctionBegin; 21669d2c0f9SBarry Smith ierr = PCReset_Composite(pc);CHKERRQ(ierr); 2174b9ad928SBarry Smith while (next) { 2186bf464f9SBarry Smith ierr = PCDestroy(&next->pc);CHKERRQ(ierr); 219724c2c99SHong Zhang next_tmp = next; 2204b9ad928SBarry Smith next = next->next; 221724c2c99SHong Zhang ierr = PetscFree(next_tmp);CHKERRQ(ierr); 2224b9ad928SBarry Smith } 223c31cb41cSBarry Smith ierr = PetscFree(pc->data);CHKERRQ(ierr); 2244b9ad928SBarry Smith PetscFunctionReturn(0); 2254b9ad928SBarry Smith } 2264b9ad928SBarry Smith 2274416b707SBarry Smith static PetscErrorCode PCSetFromOptions_Composite(PetscOptionItems *PetscOptionsObject,PC pc) 2284b9ad928SBarry Smith { 2294b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 230dfbe8321SBarry Smith PetscErrorCode ierr; 2319dcbbd2bSBarry Smith PetscInt nmax = 8,i; 2324b9ad928SBarry Smith PC_CompositeLink next; 233e5999256SBarry Smith char *pcs[8]; 234ace3abfcSBarry Smith PetscBool flg; 2354b9ad928SBarry Smith 2364b9ad928SBarry Smith PetscFunctionBegin; 237e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"Composite preconditioner options");CHKERRQ(ierr); 2389dcbbd2bSBarry Smith ierr = PetscOptionsEnum("-pc_composite_type","Type of composition","PCCompositeSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&jac->type,&flg);CHKERRQ(ierr); 23951f519a2SBarry Smith if (flg) { 24051f519a2SBarry Smith ierr = PCCompositeSetType(pc,jac->type);CHKERRQ(ierr); 24151f519a2SBarry Smith } 2428aa07aa6SMatthew G. Knepley ierr = PetscOptionsStringArray("-pc_composite_pcs","List of composite solvers","PCCompositeAddPCType",pcs,&nmax,&flg);CHKERRQ(ierr); 2434b9ad928SBarry Smith if (flg) { 2444b9ad928SBarry Smith for (i=0; i<nmax; i++) { 2458aa07aa6SMatthew G. Knepley ierr = PCCompositeAddPCType(pc,pcs[i]);CHKERRQ(ierr); 246724c2c99SHong Zhang ierr = PetscFree(pcs[i]);CHKERRQ(ierr); /* deallocate string pcs[i], which is allocated in PetscOptionsStringArray() */ 2474b9ad928SBarry Smith } 2484b9ad928SBarry Smith } 2494b9ad928SBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 2504b9ad928SBarry Smith 2514b9ad928SBarry Smith next = jac->head; 2524b9ad928SBarry Smith while (next) { 2534b9ad928SBarry Smith ierr = PCSetFromOptions(next->pc);CHKERRQ(ierr); 2544b9ad928SBarry Smith next = next->next; 2554b9ad928SBarry Smith } 2564b9ad928SBarry Smith PetscFunctionReturn(0); 2574b9ad928SBarry Smith } 2584b9ad928SBarry Smith 2596849ba73SBarry Smith static PetscErrorCode PCView_Composite(PC pc,PetscViewer viewer) 2604b9ad928SBarry Smith { 2614b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 262dfbe8321SBarry Smith PetscErrorCode ierr; 2634b9ad928SBarry Smith PC_CompositeLink next = jac->head; 264ace3abfcSBarry Smith PetscBool iascii; 2654b9ad928SBarry Smith 2664b9ad928SBarry Smith PetscFunctionBegin; 267251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 26832077d6dSBarry Smith if (iascii) { 2699dcbbd2bSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Composite PC type - %s\n",PCCompositeTypes[jac->type]);CHKERRQ(ierr); 2704b9ad928SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"PCs on composite preconditioner follow\n");CHKERRQ(ierr); 2714b9ad928SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"---------------------------------\n");CHKERRQ(ierr); 2724b9ad928SBarry Smith } 27332077d6dSBarry Smith if (iascii) { 2744b9ad928SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 2754b9ad928SBarry Smith } 2764b9ad928SBarry Smith while (next) { 2774b9ad928SBarry Smith ierr = PCView(next->pc,viewer);CHKERRQ(ierr); 2784b9ad928SBarry Smith next = next->next; 2794b9ad928SBarry Smith } 28032077d6dSBarry Smith if (iascii) { 2814b9ad928SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 2824b9ad928SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"---------------------------------\n");CHKERRQ(ierr); 2834b9ad928SBarry Smith } 2844b9ad928SBarry Smith PetscFunctionReturn(0); 2854b9ad928SBarry Smith } 2864b9ad928SBarry Smith 2874b9ad928SBarry Smith /* ------------------------------------------------------------------------------*/ 2884b9ad928SBarry Smith 2891e6b0712SBarry Smith static PetscErrorCode PCCompositeSpecialSetAlpha_Composite(PC pc,PetscScalar alpha) 2904b9ad928SBarry Smith { 2914b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 2925fd66863SKarl Rupp 2934b9ad928SBarry Smith PetscFunctionBegin; 2944b9ad928SBarry Smith jac->alpha = alpha; 2954b9ad928SBarry Smith PetscFunctionReturn(0); 2964b9ad928SBarry Smith } 2974b9ad928SBarry Smith 2981e6b0712SBarry Smith static PetscErrorCode PCCompositeSetType_Composite(PC pc,PCCompositeType type) 2994b9ad928SBarry Smith { 300fad69fbaSJed Brown PC_Composite *jac = (PC_Composite*)pc->data; 301fad69fbaSJed Brown 3024b9ad928SBarry Smith PetscFunctionBegin; 3034b9ad928SBarry Smith if (type == PC_COMPOSITE_ADDITIVE) { 3044b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 3052533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 306421e10b8SBarry Smith } else if (type == PC_COMPOSITE_MULTIPLICATIVE || type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 3074b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Multiplicative; 3082533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Multiplicative; 3094b9ad928SBarry Smith } else if (type == PC_COMPOSITE_SPECIAL) { 3104b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Special; 3110298fd71SBarry Smith pc->ops->applytranspose = NULL; 312a7261c6bSprj- } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Unknown composite preconditioner type"); 313fad69fbaSJed Brown jac->type = type; 3144b9ad928SBarry Smith PetscFunctionReturn(0); 3154b9ad928SBarry Smith } 3164b9ad928SBarry Smith 317c60c7ad4SBarry Smith static PetscErrorCode PCCompositeGetType_Composite(PC pc,PCCompositeType *type) 318c60c7ad4SBarry Smith { 319c60c7ad4SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 320c60c7ad4SBarry Smith 321c60c7ad4SBarry Smith PetscFunctionBegin; 322c60c7ad4SBarry Smith *type = jac->type; 323c60c7ad4SBarry Smith PetscFunctionReturn(0); 324c60c7ad4SBarry Smith } 325c60c7ad4SBarry Smith 3268aa07aa6SMatthew G. Knepley static PetscErrorCode PCCompositeAddPC_Composite(PC pc, PC subpc) 3274b9ad928SBarry Smith { 3284b9ad928SBarry Smith PC_Composite *jac; 3295a9f2f41SSatish Balay PC_CompositeLink next, ilink; 33079416396SBarry Smith PetscInt cnt = 0; 3312dcb1b2aSMatthew Knepley const char *prefix; 332d726e3a5SJed Brown char newprefix[20]; 3338aa07aa6SMatthew G. Knepley PetscErrorCode ierr; 3344b9ad928SBarry Smith 3354b9ad928SBarry Smith PetscFunctionBegin; 336b00a9115SJed Brown ierr = PetscNewLog(pc, &ilink);CHKERRQ(ierr); 3370a545947SLisandro Dalcin ilink->next = NULL; 3388aa07aa6SMatthew G. Knepley ilink->pc = subpc; 3394b9ad928SBarry Smith 3404b9ad928SBarry Smith jac = (PC_Composite *) pc->data; 3414b9ad928SBarry Smith next = jac->head; 3424b9ad928SBarry Smith if (!next) { 3435a9f2f41SSatish Balay jac->head = ilink; 3440298fd71SBarry Smith ilink->previous = NULL; 3454b9ad928SBarry Smith } else { 3464b9ad928SBarry Smith cnt++; 3474b9ad928SBarry Smith while (next->next) { 3484b9ad928SBarry Smith next = next->next; 3494b9ad928SBarry Smith cnt++; 3504b9ad928SBarry Smith } 3515a9f2f41SSatish Balay next->next = ilink; 352421e10b8SBarry Smith ilink->previous = next; 3534b9ad928SBarry Smith } 3544b9ad928SBarry Smith ierr = PCGetOptionsPrefix(pc, &prefix);CHKERRQ(ierr); 3558aa07aa6SMatthew G. Knepley ierr = PCSetOptionsPrefix(subpc, prefix);CHKERRQ(ierr); 3568aa07aa6SMatthew G. Knepley ierr = PetscSNPrintf(newprefix, 20, "sub_%d_", (int) cnt);CHKERRQ(ierr); 3578aa07aa6SMatthew G. Knepley ierr = PCAppendOptionsPrefix(subpc, newprefix);CHKERRQ(ierr); 3588aa07aa6SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) subpc);CHKERRQ(ierr); 3598aa07aa6SMatthew G. Knepley PetscFunctionReturn(0); 3608aa07aa6SMatthew G. Knepley } 3618aa07aa6SMatthew G. Knepley 3628aa07aa6SMatthew G. Knepley static PetscErrorCode PCCompositeAddPCType_Composite(PC pc, PCType type) 3638aa07aa6SMatthew G. Knepley { 3648aa07aa6SMatthew G. Knepley PC subpc; 3658aa07aa6SMatthew G. Knepley PetscErrorCode ierr; 3668aa07aa6SMatthew G. Knepley 3678aa07aa6SMatthew G. Knepley PetscFunctionBegin; 3688aa07aa6SMatthew G. Knepley ierr = PCCreate(PetscObjectComm((PetscObject)pc), &subpc);CHKERRQ(ierr); 3698aa07aa6SMatthew G. Knepley ierr = PetscObjectIncrementTabLevel((PetscObject) subpc, (PetscObject) pc, 1);CHKERRQ(ierr); 3708aa07aa6SMatthew G. Knepley ierr = PetscLogObjectParent((PetscObject) pc, (PetscObject) subpc);CHKERRQ(ierr); 3718aa07aa6SMatthew G. Knepley ierr = PCCompositeAddPC_Composite(pc, subpc);CHKERRQ(ierr); 3724b9ad928SBarry Smith /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */ 3738aa07aa6SMatthew G. Knepley ierr = PCSetType(subpc, type);CHKERRQ(ierr); 3748aa07aa6SMatthew G. Knepley ierr = PCDestroy(&subpc);CHKERRQ(ierr); 3754b9ad928SBarry Smith PetscFunctionReturn(0); 3764b9ad928SBarry Smith } 3774b9ad928SBarry Smith 3788e6eba06SBarry Smith static PetscErrorCode PCCompositeGetNumberPC_Composite(PC pc,PetscInt *n) 3798e6eba06SBarry Smith { 3808e6eba06SBarry Smith PC_Composite *jac; 3818e6eba06SBarry Smith PC_CompositeLink next; 3828e6eba06SBarry Smith 3838e6eba06SBarry Smith PetscFunctionBegin; 3848e6eba06SBarry Smith jac = (PC_Composite*)pc->data; 3858e6eba06SBarry Smith next = jac->head; 3868e6eba06SBarry Smith *n = 0; 3878e6eba06SBarry Smith while (next) { 3888e6eba06SBarry Smith next = next->next; 3898e6eba06SBarry Smith (*n) ++; 3908e6eba06SBarry Smith } 3918e6eba06SBarry Smith PetscFunctionReturn(0); 3928e6eba06SBarry Smith } 3938e6eba06SBarry Smith 3941e6b0712SBarry Smith static PetscErrorCode PCCompositeGetPC_Composite(PC pc,PetscInt n,PC *subpc) 3954b9ad928SBarry Smith { 3964b9ad928SBarry Smith PC_Composite *jac; 3974b9ad928SBarry Smith PC_CompositeLink next; 39879416396SBarry Smith PetscInt i; 3994b9ad928SBarry Smith 4004b9ad928SBarry Smith PetscFunctionBegin; 4014b9ad928SBarry Smith jac = (PC_Composite*)pc->data; 4024b9ad928SBarry Smith next = jac->head; 4034b9ad928SBarry Smith for (i=0; i<n; i++) { 404*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!next->next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Not enough PCs in composite preconditioner"); 4054b9ad928SBarry Smith next = next->next; 4064b9ad928SBarry Smith } 4074b9ad928SBarry Smith *subpc = next->pc; 4084b9ad928SBarry Smith PetscFunctionReturn(0); 4094b9ad928SBarry Smith } 4104b9ad928SBarry Smith 4114b9ad928SBarry Smith /* -------------------------------------------------------------------------------- */ 412f39d8e23SSatish Balay /*@ 4134b9ad928SBarry Smith PCCompositeSetType - Sets the type of composite preconditioner. 4144b9ad928SBarry Smith 415ad4df100SBarry Smith Logically Collective on PC 4164b9ad928SBarry Smith 417c60c7ad4SBarry Smith Input Parameters: 4182a6744ebSBarry Smith + pc - the preconditioner context 4192a6744ebSBarry Smith - type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL 4204b9ad928SBarry Smith 4214b9ad928SBarry Smith Options Database Key: 4224b9ad928SBarry Smith . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 4234b9ad928SBarry Smith 4244b9ad928SBarry Smith Level: Developer 4254b9ad928SBarry Smith 4264b9ad928SBarry Smith @*/ 4277087cfbeSBarry Smith PetscErrorCode PCCompositeSetType(PC pc,PCCompositeType type) 4284b9ad928SBarry Smith { 4297bb14e67SBarry Smith PetscErrorCode ierr; 4304b9ad928SBarry Smith 4314b9ad928SBarry Smith PetscFunctionBegin; 4320700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 433c5eb9154SBarry Smith PetscValidLogicalCollectiveEnum(pc,type,2); 4347bb14e67SBarry Smith ierr = PetscTryMethod(pc,"PCCompositeSetType_C",(PC,PCCompositeType),(pc,type));CHKERRQ(ierr); 4354b9ad928SBarry Smith PetscFunctionReturn(0); 4364b9ad928SBarry Smith } 4374b9ad928SBarry Smith 438c60c7ad4SBarry Smith /*@ 439721f67b5SBarry Smith PCCompositeGetType - Gets the type of composite preconditioner. 440c60c7ad4SBarry Smith 441c60c7ad4SBarry Smith Logically Collective on PC 442c60c7ad4SBarry Smith 443c60c7ad4SBarry Smith Input Parameter: 444c60c7ad4SBarry Smith . pc - the preconditioner context 445c60c7ad4SBarry Smith 446c60c7ad4SBarry Smith Output Parameter: 447c60c7ad4SBarry Smith . type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL 448c60c7ad4SBarry Smith 449c60c7ad4SBarry Smith Options Database Key: 450c60c7ad4SBarry Smith . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 451c60c7ad4SBarry Smith 452c60c7ad4SBarry Smith Level: Developer 453c60c7ad4SBarry Smith 454c60c7ad4SBarry Smith @*/ 455c60c7ad4SBarry Smith PetscErrorCode PCCompositeGetType(PC pc,PCCompositeType *type) 456c60c7ad4SBarry Smith { 457c60c7ad4SBarry Smith PetscErrorCode ierr; 458c60c7ad4SBarry Smith 459c60c7ad4SBarry Smith PetscFunctionBegin; 460c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 461c60c7ad4SBarry Smith ierr = PetscUseMethod(pc,"PCCompositeGetType_C",(PC,PCCompositeType*),(pc,type));CHKERRQ(ierr); 462c60c7ad4SBarry Smith PetscFunctionReturn(0); 463c60c7ad4SBarry Smith } 464c60c7ad4SBarry Smith 465f39d8e23SSatish Balay /*@ 4664b9ad928SBarry Smith PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner 4674b9ad928SBarry Smith for alphaI + R + S 4684b9ad928SBarry Smith 469ad4df100SBarry Smith Logically Collective on PC 4704b9ad928SBarry Smith 471d8d19677SJose E. Roman Input Parameters: 4724b9ad928SBarry Smith + pc - the preconditioner context 4734b9ad928SBarry Smith - alpha - scale on identity 4744b9ad928SBarry Smith 4754b9ad928SBarry Smith Level: Developer 4764b9ad928SBarry Smith 4774b9ad928SBarry Smith @*/ 4787087cfbeSBarry Smith PetscErrorCode PCCompositeSpecialSetAlpha(PC pc,PetscScalar alpha) 4794b9ad928SBarry Smith { 4804ac538c5SBarry Smith PetscErrorCode ierr; 4814b9ad928SBarry Smith 4824b9ad928SBarry Smith PetscFunctionBegin; 4830700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 484c5eb9154SBarry Smith PetscValidLogicalCollectiveScalar(pc,alpha,2); 4854ac538c5SBarry Smith ierr = PetscTryMethod(pc,"PCCompositeSpecialSetAlpha_C",(PC,PetscScalar),(pc,alpha));CHKERRQ(ierr); 4864b9ad928SBarry Smith PetscFunctionReturn(0); 4874b9ad928SBarry Smith } 4884b9ad928SBarry Smith 4894b9ad928SBarry Smith /*@C 4908aa07aa6SMatthew G. Knepley PCCompositeAddPCType - Adds another PC of the given type to the composite PC. 4914b9ad928SBarry Smith 4924b9ad928SBarry Smith Collective on PC 4934b9ad928SBarry Smith 4944b9ad928SBarry Smith Input Parameters: 4952a6744ebSBarry Smith + pc - the preconditioner context 4962a6744ebSBarry Smith - type - the type of the new preconditioner 4974b9ad928SBarry Smith 4984b9ad928SBarry Smith Level: Developer 4994b9ad928SBarry Smith 5008aa07aa6SMatthew G. Knepley .seealso: PCCompositeAddPC() 5014b9ad928SBarry Smith @*/ 5028aa07aa6SMatthew G. Knepley PetscErrorCode PCCompositeAddPCType(PC pc,PCType type) 5034b9ad928SBarry Smith { 5044ac538c5SBarry Smith PetscErrorCode ierr; 5054b9ad928SBarry Smith 5064b9ad928SBarry Smith PetscFunctionBegin; 5070700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 5088aa07aa6SMatthew G. Knepley ierr = PetscTryMethod(pc,"PCCompositeAddPCType_C",(PC,PCType),(pc,type));CHKERRQ(ierr); 5098aa07aa6SMatthew G. Knepley PetscFunctionReturn(0); 5108aa07aa6SMatthew G. Knepley } 5118aa07aa6SMatthew G. Knepley 5128aa07aa6SMatthew G. Knepley /*@ 5138aa07aa6SMatthew G. Knepley PCCompositeAddPC - Adds another PC to the composite PC. 5148aa07aa6SMatthew G. Knepley 5158aa07aa6SMatthew G. Knepley Collective on PC 5168aa07aa6SMatthew G. Knepley 5178aa07aa6SMatthew G. Knepley Input Parameters: 5188aa07aa6SMatthew G. Knepley + pc - the preconditioner context 5198aa07aa6SMatthew G. Knepley - subpc - the new preconditioner 5208aa07aa6SMatthew G. Knepley 5218aa07aa6SMatthew G. Knepley Level: Developer 5228aa07aa6SMatthew G. Knepley 5238aa07aa6SMatthew G. Knepley .seealso: PCCompositeAddPCType() 5248aa07aa6SMatthew G. Knepley @*/ 5258aa07aa6SMatthew G. Knepley PetscErrorCode PCCompositeAddPC(PC pc, PC subpc) 5268aa07aa6SMatthew G. Knepley { 5278aa07aa6SMatthew G. Knepley PetscErrorCode ierr; 5288aa07aa6SMatthew G. Knepley 5298aa07aa6SMatthew G. Knepley PetscFunctionBegin; 5308aa07aa6SMatthew G. Knepley PetscValidHeaderSpecific(pc,PC_CLASSID,1); 5318aa07aa6SMatthew G. Knepley PetscValidHeaderSpecific(subpc,PC_CLASSID,2); 5328aa07aa6SMatthew G. Knepley ierr = PetscTryMethod(pc,"PCCompositeAddPC_C",(PC,PC),(pc,subpc));CHKERRQ(ierr); 5334b9ad928SBarry Smith PetscFunctionReturn(0); 5344b9ad928SBarry Smith } 5354b9ad928SBarry Smith 5368e6eba06SBarry Smith /*@ 5378e6eba06SBarry Smith PCCompositeGetNumberPC - Gets the number of PC objects in the composite PC. 5388e6eba06SBarry Smith 5398e6eba06SBarry Smith Not Collective 5408e6eba06SBarry Smith 5418e6eba06SBarry Smith Input Parameter: 5428e6eba06SBarry Smith . pc - the preconditioner context 5438e6eba06SBarry Smith 5448e6eba06SBarry Smith Output Parameter: 5458e6eba06SBarry Smith . num - the number of sub pcs 5468e6eba06SBarry Smith 5478e6eba06SBarry Smith Level: Developer 5488e6eba06SBarry Smith 5498e6eba06SBarry Smith .seealso: PCCompositeGetPC() 5508e6eba06SBarry Smith @*/ 5518e6eba06SBarry Smith PetscErrorCode PCCompositeGetNumberPC(PC pc,PetscInt *num) 5528e6eba06SBarry Smith { 5538e6eba06SBarry Smith PetscErrorCode ierr; 5548e6eba06SBarry Smith 5558e6eba06SBarry Smith PetscFunctionBegin; 5568e6eba06SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 5578e6eba06SBarry Smith PetscValidIntPointer(num,2); 5588e6eba06SBarry Smith ierr = PetscUseMethod(pc,"PCCompositeGetNumberPC_C",(PC,PetscInt*),(pc,num));CHKERRQ(ierr); 5598e6eba06SBarry Smith PetscFunctionReturn(0); 5608e6eba06SBarry Smith } 5618e6eba06SBarry Smith 562f39d8e23SSatish Balay /*@ 5634b9ad928SBarry Smith PCCompositeGetPC - Gets one of the PC objects in the composite PC. 5644b9ad928SBarry Smith 5654b9ad928SBarry Smith Not Collective 5664b9ad928SBarry Smith 567d8d19677SJose E. Roman Input Parameters: 5682a6744ebSBarry Smith + pc - the preconditioner context 5692a6744ebSBarry Smith - n - the number of the pc requested 5704b9ad928SBarry Smith 5714b9ad928SBarry Smith Output Parameters: 5724b9ad928SBarry Smith . subpc - the PC requested 5734b9ad928SBarry Smith 5744b9ad928SBarry Smith Level: Developer 5754b9ad928SBarry Smith 57695452b02SPatrick Sanan Notes: 57795452b02SPatrick Sanan To use a different operator to construct one of the inner preconditioners first call PCCompositeGetPC(), then 5782b1d202aSBarry Smith call PCSetOperators() on that PC. 5792b1d202aSBarry Smith 5808aa07aa6SMatthew G. Knepley .seealso: PCCompositeAddPCType(), PCCompositeGetNumberPC(), PCSetOperators() 5814b9ad928SBarry Smith @*/ 5827087cfbeSBarry Smith PetscErrorCode PCCompositeGetPC(PC pc,PetscInt n,PC *subpc) 5834b9ad928SBarry Smith { 5844ac538c5SBarry Smith PetscErrorCode ierr; 5854b9ad928SBarry Smith 5864b9ad928SBarry Smith PetscFunctionBegin; 5870700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 5884482741eSBarry Smith PetscValidPointer(subpc,3); 5894ac538c5SBarry Smith ierr = PetscUseMethod(pc,"PCCompositeGetPC_C",(PC,PetscInt,PC*),(pc,n,subpc));CHKERRQ(ierr); 5904b9ad928SBarry Smith PetscFunctionReturn(0); 5914b9ad928SBarry Smith } 5924b9ad928SBarry Smith 5934b9ad928SBarry Smith /* -------------------------------------------------------------------------------------------*/ 5944b9ad928SBarry Smith 5954b9ad928SBarry Smith /*MC 5964b9ad928SBarry Smith PCCOMPOSITE - Build a preconditioner by composing together several preconditioners 5974b9ad928SBarry Smith 5984b9ad928SBarry Smith Options Database Keys: 5992eab2d5bSJungho Lee + -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type 6002b1d202aSBarry Smith . -pc_use_amat - activates PCSetUseAmat() 60151f519a2SBarry Smith - -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose 6024b9ad928SBarry Smith 6034b9ad928SBarry Smith Level: intermediate 6044b9ad928SBarry Smith 60595452b02SPatrick Sanan Notes: 60695452b02SPatrick Sanan To use a Krylov method inside the composite preconditioner, set the PCType of one or more 6074b9ad928SBarry Smith inner PCs to be PCKSP. 6084b9ad928SBarry Smith Using a Krylov method inside another Krylov method can be dangerous (you get divergence or 609b3ef52cdSBarry Smith the incorrect answer) unless you use KSPFGMRES as the outer Krylov method 6102b1d202aSBarry Smith To use a different operator to construct one of the inner preconditioners first call PCCompositeGetPC(), then 6112b1d202aSBarry Smith call PCSetOperators() on that PC. 6124b9ad928SBarry Smith 6134b9ad928SBarry Smith .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 6148aa07aa6SMatthew G. Knepley PCSHELL, PCKSP, PCCompositeSetType(), PCCompositeSpecialSetAlpha(), PCCompositeAddPCType(), 61549517cdeSBarry Smith PCCompositeGetPC(), PCSetUseAmat() 6164b9ad928SBarry Smith 6174b9ad928SBarry Smith M*/ 6184b9ad928SBarry Smith 6198cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc) 6204b9ad928SBarry Smith { 621dfbe8321SBarry Smith PetscErrorCode ierr; 6224b9ad928SBarry Smith PC_Composite *jac; 6234b9ad928SBarry Smith 6244b9ad928SBarry Smith PetscFunctionBegin; 625b00a9115SJed Brown ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr); 6262fa5cd67SKarl Rupp 6274b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 6282533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 6294b9ad928SBarry Smith pc->ops->setup = PCSetUp_Composite; 63069d2c0f9SBarry Smith pc->ops->reset = PCReset_Composite; 6314b9ad928SBarry Smith pc->ops->destroy = PCDestroy_Composite; 6324b9ad928SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Composite; 6334b9ad928SBarry Smith pc->ops->view = PCView_Composite; 6340a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 6354b9ad928SBarry Smith 6364b9ad928SBarry Smith pc->data = (void*)jac; 6374b9ad928SBarry Smith jac->type = PC_COMPOSITE_ADDITIVE; 6380a545947SLisandro Dalcin jac->work1 = NULL; 6390a545947SLisandro Dalcin jac->work2 = NULL; 6400a545947SLisandro Dalcin jac->head = NULL; 6414b9ad928SBarry Smith 642bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSetType_C",PCCompositeSetType_Composite);CHKERRQ(ierr); 643c60c7ad4SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetType_C",PCCompositeGetType_Composite);CHKERRQ(ierr); 6448aa07aa6SMatthew G. Knepley ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPCType_C",PCCompositeAddPCType_Composite);CHKERRQ(ierr); 645bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPC_C",PCCompositeAddPC_Composite);CHKERRQ(ierr); 6468e6eba06SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetNumberPC_C",PCCompositeGetNumberPC_Composite);CHKERRQ(ierr); 647bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetPC_C",PCCompositeGetPC_Composite);CHKERRQ(ierr); 648bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSpecialSetAlpha_C",PCCompositeSpecialSetAlpha_Composite);CHKERRQ(ierr); 6494b9ad928SBarry Smith PetscFunctionReturn(0); 6504b9ad928SBarry Smith } 651