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