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 { 254b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 264b9ad928SBarry Smith PC_CompositeLink next = jac->head; 274b9ad928SBarry Smith Mat mat = pc->pmat; 284b9ad928SBarry Smith 294b9ad928SBarry Smith PetscFunctionBegin; 30450d59ebSPatrick Farrell 3128b400f6SJacob Faibussowitsch PetscCheck(next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 32450d59ebSPatrick Farrell 33450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 34450d59ebSPatrick Farrell while (next) { 359566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->pc,pc->reusepreconditioner)); 36450d59ebSPatrick Farrell next = next->next; 37450d59ebSPatrick Farrell } 38450d59ebSPatrick Farrell next = jac->head; 39450d59ebSPatrick Farrell 404b9ad928SBarry Smith if (next->next && !jac->work2) { /* allocate second work vector */ 419566063dSJacob Faibussowitsch PetscCall(VecDuplicate(jac->work1,&jac->work2)); 424b9ad928SBarry Smith } 4349517cdeSBarry Smith if (pc->useAmat) mat = pc->mat; 449566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc,x,y)); /* y <- B x */ 454b9ad928SBarry Smith while (next->next) { 464b9ad928SBarry Smith next = next->next; 479566063dSJacob Faibussowitsch PetscCall(MatMult(mat,y,jac->work1)); /* work1 <- A y */ 489566063dSJacob Faibussowitsch PetscCall(VecWAXPY(jac->work2,-1.0,jac->work1,x)); /* work2 <- x - work1 */ 499566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc,jac->work2,jac->work1)); /* work1 <- C work2 */ 509566063dSJacob Faibussowitsch PetscCall(VecAXPY(y,1.0,jac->work1)); /* y <- y + work1 = B x + C (x - A B x) = (B + C (1 - A B)) x */ 514b9ad928SBarry Smith } 52421e10b8SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 53421e10b8SBarry Smith while (next->previous) { 54421e10b8SBarry Smith next = next->previous; 559566063dSJacob Faibussowitsch PetscCall(MatMult(mat,y,jac->work1)); 569566063dSJacob Faibussowitsch PetscCall(VecWAXPY(jac->work2,-1.0,jac->work1,x)); 579566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc,jac->work2,jac->work1)); 589566063dSJacob Faibussowitsch PetscCall(VecAXPY(y,1.0,jac->work1)); 59421e10b8SBarry Smith } 60421e10b8SBarry Smith } 614b9ad928SBarry Smith PetscFunctionReturn(0); 624b9ad928SBarry Smith } 634b9ad928SBarry Smith 642533e041SBarry Smith static PetscErrorCode PCApplyTranspose_Composite_Multiplicative(PC pc,Vec x,Vec y) 652533e041SBarry Smith { 662533e041SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 672533e041SBarry Smith PC_CompositeLink next = jac->head; 682533e041SBarry Smith Mat mat = pc->pmat; 692533e041SBarry Smith 702533e041SBarry Smith PetscFunctionBegin; 7128b400f6SJacob Faibussowitsch PetscCheck(next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 722533e041SBarry Smith if (next->next && !jac->work2) { /* allocate second work vector */ 739566063dSJacob Faibussowitsch PetscCall(VecDuplicate(jac->work1,&jac->work2)); 742533e041SBarry Smith } 7549517cdeSBarry Smith if (pc->useAmat) mat = pc->mat; 762533e041SBarry Smith /* locate last PC */ 772533e041SBarry Smith while (next->next) { 782533e041SBarry Smith next = next->next; 792533e041SBarry Smith } 809566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc,x,y)); 812533e041SBarry Smith while (next->previous) { 822533e041SBarry Smith next = next->previous; 839566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(mat,y,jac->work1)); 849566063dSJacob Faibussowitsch PetscCall(VecWAXPY(jac->work2,-1.0,jac->work1,x)); 859566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc,jac->work2,jac->work1)); 869566063dSJacob Faibussowitsch PetscCall(VecAXPY(y,1.0,jac->work1)); 872533e041SBarry Smith } 882533e041SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 892533e041SBarry Smith next = jac->head; 902533e041SBarry Smith while (next->next) { 912533e041SBarry Smith next = next->next; 929566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(mat,y,jac->work1)); 939566063dSJacob Faibussowitsch PetscCall(VecWAXPY(jac->work2,-1.0,jac->work1,x)); 949566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc,jac->work2,jac->work1)); 959566063dSJacob Faibussowitsch PetscCall(VecAXPY(y,1.0,jac->work1)); 962533e041SBarry Smith } 972533e041SBarry Smith } 982533e041SBarry Smith PetscFunctionReturn(0); 992533e041SBarry Smith } 1002533e041SBarry Smith 1014b9ad928SBarry Smith /* 1024b9ad928SBarry Smith This is very special for a matrix of the form alpha I + R + S 1034b9ad928SBarry Smith where first preconditioner is built from alpha I + S and second from 1044b9ad928SBarry Smith alpha I + R 1054b9ad928SBarry Smith */ 1066849ba73SBarry Smith static PetscErrorCode PCApply_Composite_Special(PC pc,Vec x,Vec y) 1074b9ad928SBarry Smith { 1084b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 1094b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1104b9ad928SBarry Smith 1114b9ad928SBarry Smith PetscFunctionBegin; 11228b400f6SJacob Faibussowitsch PetscCheck(next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 1137827d75bSBarry Smith PetscCheck(next->next && !next->next->next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Special composite preconditioners requires exactly two PCs"); 1144b9ad928SBarry Smith 115450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 1169566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->pc,pc->reusepreconditioner)); 1179566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->next->pc,pc->reusepreconditioner)); 118450d59ebSPatrick Farrell 1199566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc,x,jac->work1)); 1209566063dSJacob Faibussowitsch PetscCall(PCApply(next->next->pc,jac->work1,y)); 1214b9ad928SBarry Smith PetscFunctionReturn(0); 1224b9ad928SBarry Smith } 1234b9ad928SBarry Smith 1246849ba73SBarry Smith static PetscErrorCode PCApply_Composite_Additive(PC pc,Vec x,Vec y) 1254b9ad928SBarry Smith { 1264b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 1274b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1284b9ad928SBarry Smith 1294b9ad928SBarry Smith PetscFunctionBegin; 13028b400f6SJacob Faibussowitsch PetscCheck(next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 131450d59ebSPatrick Farrell 132450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 133450d59ebSPatrick Farrell while (next) { 1349566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->pc,pc->reusepreconditioner)); 135450d59ebSPatrick Farrell next = next->next; 136450d59ebSPatrick Farrell } 137450d59ebSPatrick Farrell next = jac->head; 138450d59ebSPatrick Farrell 1399566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc,x,y)); 1404b9ad928SBarry Smith while (next->next) { 1414b9ad928SBarry Smith next = next->next; 1429566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc,x,jac->work1)); 1439566063dSJacob Faibussowitsch PetscCall(VecAXPY(y,1.0,jac->work1)); 1444b9ad928SBarry Smith } 1454b9ad928SBarry Smith PetscFunctionReturn(0); 1464b9ad928SBarry Smith } 1474b9ad928SBarry Smith 1482533e041SBarry Smith static PetscErrorCode PCApplyTranspose_Composite_Additive(PC pc,Vec x,Vec y) 1492533e041SBarry Smith { 1502533e041SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 1512533e041SBarry Smith PC_CompositeLink next = jac->head; 1522533e041SBarry Smith 1532533e041SBarry Smith PetscFunctionBegin; 15428b400f6SJacob Faibussowitsch PetscCheck(next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 1559566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc,x,y)); 1562533e041SBarry Smith while (next->next) { 1572533e041SBarry Smith next = next->next; 1589566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc,x,jac->work1)); 1599566063dSJacob Faibussowitsch PetscCall(VecAXPY(y,1.0,jac->work1)); 1602533e041SBarry Smith } 1612533e041SBarry Smith PetscFunctionReturn(0); 1622533e041SBarry Smith } 1632533e041SBarry Smith 1646849ba73SBarry Smith static PetscErrorCode PCSetUp_Composite(PC pc) 1654b9ad928SBarry Smith { 1664b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 1674b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1685a78d018SMatthew G. Knepley DM dm; 1694b9ad928SBarry Smith 1704b9ad928SBarry Smith PetscFunctionBegin; 1714b9ad928SBarry Smith if (!jac->work1) { 1729566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat,&jac->work1,NULL)); 1734b9ad928SBarry Smith } 1749566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc,&dm)); 1754b9ad928SBarry Smith while (next) { 1762b1d202aSBarry Smith if (!next->pc->dm) { 1779566063dSJacob Faibussowitsch PetscCall(PCSetDM(next->pc,dm)); 1782b1d202aSBarry Smith } 1792b1d202aSBarry Smith if (!next->pc->mat) { 1809566063dSJacob Faibussowitsch PetscCall(PCSetOperators(next->pc,pc->mat,pc->pmat)); 1812b1d202aSBarry Smith } 1824b9ad928SBarry Smith next = next->next; 1834b9ad928SBarry Smith } 1844b9ad928SBarry Smith PetscFunctionReturn(0); 1854b9ad928SBarry Smith } 1864b9ad928SBarry Smith 18769d2c0f9SBarry Smith static PetscErrorCode PCReset_Composite(PC pc) 18869d2c0f9SBarry Smith { 18969d2c0f9SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 1905f48b12bSBarry Smith PC_CompositeLink next = jac->head; 19169d2c0f9SBarry Smith 19269d2c0f9SBarry Smith PetscFunctionBegin; 19369d2c0f9SBarry Smith while (next) { 1949566063dSJacob Faibussowitsch PetscCall(PCReset(next->pc)); 19569d2c0f9SBarry Smith next = next->next; 19669d2c0f9SBarry Smith } 1979566063dSJacob Faibussowitsch PetscCall(VecDestroy(&jac->work1)); 1989566063dSJacob Faibussowitsch PetscCall(VecDestroy(&jac->work2)); 19969d2c0f9SBarry Smith PetscFunctionReturn(0); 20069d2c0f9SBarry Smith } 20169d2c0f9SBarry Smith 2026849ba73SBarry Smith static PetscErrorCode PCDestroy_Composite(PC pc) 2034b9ad928SBarry Smith { 2044b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 205724c2c99SHong Zhang PC_CompositeLink next = jac->head,next_tmp; 2064b9ad928SBarry Smith 2074b9ad928SBarry Smith PetscFunctionBegin; 2089566063dSJacob Faibussowitsch PetscCall(PCReset_Composite(pc)); 2094b9ad928SBarry Smith while (next) { 2109566063dSJacob Faibussowitsch PetscCall(PCDestroy(&next->pc)); 211724c2c99SHong Zhang next_tmp = next; 2124b9ad928SBarry Smith next = next->next; 2139566063dSJacob Faibussowitsch PetscCall(PetscFree(next_tmp)); 2144b9ad928SBarry Smith } 215*2e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSetType_C",NULL)); 216*2e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetType_C",NULL)); 217*2e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPCType_C",NULL)); 218*2e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPC_C",NULL)); 219*2e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetNumberPC_C",NULL)); 220*2e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetPC_C",NULL)); 221*2e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSpecialSetAlpha_C",NULL)); 2229566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 2234b9ad928SBarry Smith PetscFunctionReturn(0); 2244b9ad928SBarry Smith } 2254b9ad928SBarry Smith 2264416b707SBarry Smith static PetscErrorCode PCSetFromOptions_Composite(PetscOptionItems *PetscOptionsObject,PC pc) 2274b9ad928SBarry Smith { 2284b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 2299dcbbd2bSBarry Smith PetscInt nmax = 8,i; 2304b9ad928SBarry Smith PC_CompositeLink next; 231e5999256SBarry Smith char *pcs[8]; 232ace3abfcSBarry Smith PetscBool flg; 2334b9ad928SBarry Smith 2344b9ad928SBarry Smith PetscFunctionBegin; 235d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject,"Composite preconditioner options"); 2369566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-pc_composite_type","Type of composition","PCCompositeSetType",PCCompositeTypes,(PetscEnum)jac->type,(PetscEnum*)&jac->type,&flg)); 23751f519a2SBarry Smith if (flg) { 2389566063dSJacob Faibussowitsch PetscCall(PCCompositeSetType(pc,jac->type)); 23951f519a2SBarry Smith } 2409566063dSJacob Faibussowitsch PetscCall(PetscOptionsStringArray("-pc_composite_pcs","List of composite solvers","PCCompositeAddPCType",pcs,&nmax,&flg)); 2414b9ad928SBarry Smith if (flg) { 2424b9ad928SBarry Smith for (i=0; i<nmax; i++) { 2439566063dSJacob Faibussowitsch PetscCall(PCCompositeAddPCType(pc,pcs[i])); 2449566063dSJacob Faibussowitsch PetscCall(PetscFree(pcs[i])); /* deallocate string pcs[i], which is allocated in PetscOptionsStringArray() */ 2454b9ad928SBarry Smith } 2464b9ad928SBarry Smith } 247d0609cedSBarry Smith PetscOptionsHeadEnd(); 2484b9ad928SBarry Smith 2494b9ad928SBarry Smith next = jac->head; 2504b9ad928SBarry Smith while (next) { 2519566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(next->pc)); 2524b9ad928SBarry Smith next = next->next; 2534b9ad928SBarry Smith } 2544b9ad928SBarry Smith PetscFunctionReturn(0); 2554b9ad928SBarry Smith } 2564b9ad928SBarry Smith 2576849ba73SBarry Smith static PetscErrorCode PCView_Composite(PC pc,PetscViewer viewer) 2584b9ad928SBarry Smith { 2594b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 2604b9ad928SBarry Smith PC_CompositeLink next = jac->head; 261ace3abfcSBarry Smith PetscBool iascii; 2624b9ad928SBarry Smith 2634b9ad928SBarry Smith PetscFunctionBegin; 2649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 26532077d6dSBarry Smith if (iascii) { 2669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"Composite PC type - %s\n",PCCompositeTypes[jac->type])); 2679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"PCs on composite preconditioner follow\n")); 2689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"---------------------------------\n")); 2694b9ad928SBarry Smith } 27032077d6dSBarry Smith if (iascii) { 2719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 2724b9ad928SBarry Smith } 2734b9ad928SBarry Smith while (next) { 2749566063dSJacob Faibussowitsch PetscCall(PCView(next->pc,viewer)); 2754b9ad928SBarry Smith next = next->next; 2764b9ad928SBarry Smith } 27732077d6dSBarry Smith if (iascii) { 2789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 2799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"---------------------------------\n")); 2804b9ad928SBarry Smith } 2814b9ad928SBarry Smith PetscFunctionReturn(0); 2824b9ad928SBarry Smith } 2834b9ad928SBarry Smith 2844b9ad928SBarry Smith /* ------------------------------------------------------------------------------*/ 2854b9ad928SBarry Smith 2861e6b0712SBarry Smith static PetscErrorCode PCCompositeSpecialSetAlpha_Composite(PC pc,PetscScalar alpha) 2874b9ad928SBarry Smith { 2884b9ad928SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 2895fd66863SKarl Rupp 2904b9ad928SBarry Smith PetscFunctionBegin; 2914b9ad928SBarry Smith jac->alpha = alpha; 2924b9ad928SBarry Smith PetscFunctionReturn(0); 2934b9ad928SBarry Smith } 2944b9ad928SBarry Smith 2951e6b0712SBarry Smith static PetscErrorCode PCCompositeSetType_Composite(PC pc,PCCompositeType type) 2964b9ad928SBarry Smith { 297fad69fbaSJed Brown PC_Composite *jac = (PC_Composite*)pc->data; 298fad69fbaSJed Brown 2994b9ad928SBarry Smith PetscFunctionBegin; 3004b9ad928SBarry Smith if (type == PC_COMPOSITE_ADDITIVE) { 3014b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 3022533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 303421e10b8SBarry Smith } else if (type == PC_COMPOSITE_MULTIPLICATIVE || type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 3044b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Multiplicative; 3052533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Multiplicative; 3064b9ad928SBarry Smith } else if (type == PC_COMPOSITE_SPECIAL) { 3074b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Special; 3080298fd71SBarry Smith pc->ops->applytranspose = NULL; 309a7261c6bSprj- } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Unknown composite preconditioner type"); 310fad69fbaSJed Brown jac->type = type; 3114b9ad928SBarry Smith PetscFunctionReturn(0); 3124b9ad928SBarry Smith } 3134b9ad928SBarry Smith 314c60c7ad4SBarry Smith static PetscErrorCode PCCompositeGetType_Composite(PC pc,PCCompositeType *type) 315c60c7ad4SBarry Smith { 316c60c7ad4SBarry Smith PC_Composite *jac = (PC_Composite*)pc->data; 317c60c7ad4SBarry Smith 318c60c7ad4SBarry Smith PetscFunctionBegin; 319c60c7ad4SBarry Smith *type = jac->type; 320c60c7ad4SBarry Smith PetscFunctionReturn(0); 321c60c7ad4SBarry Smith } 322c60c7ad4SBarry Smith 3238aa07aa6SMatthew G. Knepley static PetscErrorCode PCCompositeAddPC_Composite(PC pc, PC subpc) 3244b9ad928SBarry Smith { 3254b9ad928SBarry Smith PC_Composite *jac; 3265a9f2f41SSatish Balay PC_CompositeLink next, ilink; 32779416396SBarry Smith PetscInt cnt = 0; 3282dcb1b2aSMatthew Knepley const char *prefix; 329d726e3a5SJed Brown char newprefix[20]; 3304b9ad928SBarry Smith 3314b9ad928SBarry Smith PetscFunctionBegin; 3329566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc, &ilink)); 3330a545947SLisandro Dalcin ilink->next = NULL; 3348aa07aa6SMatthew G. Knepley ilink->pc = subpc; 3354b9ad928SBarry Smith 3364b9ad928SBarry Smith jac = (PC_Composite *) pc->data; 3374b9ad928SBarry Smith next = jac->head; 3384b9ad928SBarry Smith if (!next) { 3395a9f2f41SSatish Balay jac->head = ilink; 3400298fd71SBarry Smith ilink->previous = NULL; 3414b9ad928SBarry Smith } else { 3424b9ad928SBarry Smith cnt++; 3434b9ad928SBarry Smith while (next->next) { 3444b9ad928SBarry Smith next = next->next; 3454b9ad928SBarry Smith cnt++; 3464b9ad928SBarry Smith } 3475a9f2f41SSatish Balay next->next = ilink; 348421e10b8SBarry Smith ilink->previous = next; 3494b9ad928SBarry Smith } 3509566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix)); 3519566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(subpc, prefix)); 3529566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(newprefix, 20, "sub_%d_", (int) cnt)); 3539566063dSJacob Faibussowitsch PetscCall(PCAppendOptionsPrefix(subpc, newprefix)); 3549566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject) subpc)); 3558aa07aa6SMatthew G. Knepley PetscFunctionReturn(0); 3568aa07aa6SMatthew G. Knepley } 3578aa07aa6SMatthew G. Knepley 3588aa07aa6SMatthew G. Knepley static PetscErrorCode PCCompositeAddPCType_Composite(PC pc, PCType type) 3598aa07aa6SMatthew G. Knepley { 3608aa07aa6SMatthew G. Knepley PC subpc; 3618aa07aa6SMatthew G. Knepley 3628aa07aa6SMatthew G. Knepley PetscFunctionBegin; 3639566063dSJacob Faibussowitsch PetscCall(PCCreate(PetscObjectComm((PetscObject)pc), &subpc)); 3649566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject) subpc, (PetscObject) pc, 1)); 3659566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject) pc, (PetscObject) subpc)); 3669566063dSJacob Faibussowitsch PetscCall(PCCompositeAddPC_Composite(pc, subpc)); 3674b9ad928SBarry Smith /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */ 3689566063dSJacob Faibussowitsch PetscCall(PCSetType(subpc, type)); 3699566063dSJacob Faibussowitsch PetscCall(PCDestroy(&subpc)); 3704b9ad928SBarry Smith PetscFunctionReturn(0); 3714b9ad928SBarry Smith } 3724b9ad928SBarry Smith 3738e6eba06SBarry Smith static PetscErrorCode PCCompositeGetNumberPC_Composite(PC pc,PetscInt *n) 3748e6eba06SBarry Smith { 3758e6eba06SBarry Smith PC_Composite *jac; 3768e6eba06SBarry Smith PC_CompositeLink next; 3778e6eba06SBarry Smith 3788e6eba06SBarry Smith PetscFunctionBegin; 3798e6eba06SBarry Smith jac = (PC_Composite*)pc->data; 3808e6eba06SBarry Smith next = jac->head; 3818e6eba06SBarry Smith *n = 0; 3828e6eba06SBarry Smith while (next) { 3838e6eba06SBarry Smith next = next->next; 3848e6eba06SBarry Smith (*n) ++; 3858e6eba06SBarry Smith } 3868e6eba06SBarry Smith PetscFunctionReturn(0); 3878e6eba06SBarry Smith } 3888e6eba06SBarry Smith 3891e6b0712SBarry Smith static PetscErrorCode PCCompositeGetPC_Composite(PC pc,PetscInt n,PC *subpc) 3904b9ad928SBarry Smith { 3914b9ad928SBarry Smith PC_Composite *jac; 3924b9ad928SBarry Smith PC_CompositeLink next; 39379416396SBarry Smith PetscInt i; 3944b9ad928SBarry Smith 3954b9ad928SBarry Smith PetscFunctionBegin; 3964b9ad928SBarry Smith jac = (PC_Composite*)pc->data; 3974b9ad928SBarry Smith next = jac->head; 3984b9ad928SBarry Smith for (i=0; i<n; i++) { 39928b400f6SJacob Faibussowitsch PetscCheck(next->next,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Not enough PCs in composite preconditioner"); 4004b9ad928SBarry Smith next = next->next; 4014b9ad928SBarry Smith } 4024b9ad928SBarry Smith *subpc = next->pc; 4034b9ad928SBarry Smith PetscFunctionReturn(0); 4044b9ad928SBarry Smith } 4054b9ad928SBarry Smith 4064b9ad928SBarry Smith /* -------------------------------------------------------------------------------- */ 407f39d8e23SSatish Balay /*@ 4084b9ad928SBarry Smith PCCompositeSetType - Sets the type of composite preconditioner. 4094b9ad928SBarry Smith 410ad4df100SBarry Smith Logically Collective on PC 4114b9ad928SBarry Smith 412c60c7ad4SBarry Smith Input Parameters: 4132a6744ebSBarry Smith + pc - the preconditioner context 4142a6744ebSBarry Smith - type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL 4154b9ad928SBarry Smith 4164b9ad928SBarry Smith Options Database Key: 4174b9ad928SBarry Smith . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 4184b9ad928SBarry Smith 4194b9ad928SBarry Smith Level: Developer 4204b9ad928SBarry Smith 4214b9ad928SBarry Smith @*/ 4227087cfbeSBarry Smith PetscErrorCode PCCompositeSetType(PC pc,PCCompositeType type) 4234b9ad928SBarry Smith { 4244b9ad928SBarry Smith PetscFunctionBegin; 4250700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 426c5eb9154SBarry Smith PetscValidLogicalCollectiveEnum(pc,type,2); 427cac4c232SBarry Smith PetscTryMethod(pc,"PCCompositeSetType_C",(PC,PCCompositeType),(pc,type)); 4284b9ad928SBarry Smith PetscFunctionReturn(0); 4294b9ad928SBarry Smith } 4304b9ad928SBarry Smith 431c60c7ad4SBarry Smith /*@ 432721f67b5SBarry Smith PCCompositeGetType - Gets the type of composite preconditioner. 433c60c7ad4SBarry Smith 434c60c7ad4SBarry Smith Logically Collective on PC 435c60c7ad4SBarry Smith 436c60c7ad4SBarry Smith Input Parameter: 437c60c7ad4SBarry Smith . pc - the preconditioner context 438c60c7ad4SBarry Smith 439c60c7ad4SBarry Smith Output Parameter: 440c60c7ad4SBarry Smith . type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL 441c60c7ad4SBarry Smith 442c60c7ad4SBarry Smith Options Database Key: 443c60c7ad4SBarry Smith . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 444c60c7ad4SBarry Smith 445c60c7ad4SBarry Smith Level: Developer 446c60c7ad4SBarry Smith 447c60c7ad4SBarry Smith @*/ 448c60c7ad4SBarry Smith PetscErrorCode PCCompositeGetType(PC pc,PCCompositeType *type) 449c60c7ad4SBarry Smith { 450c60c7ad4SBarry Smith PetscFunctionBegin; 451c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 452cac4c232SBarry Smith PetscUseMethod(pc,"PCCompositeGetType_C",(PC,PCCompositeType*),(pc,type)); 453c60c7ad4SBarry Smith PetscFunctionReturn(0); 454c60c7ad4SBarry Smith } 455c60c7ad4SBarry Smith 456f39d8e23SSatish Balay /*@ 4574b9ad928SBarry Smith PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner 4584b9ad928SBarry Smith for alphaI + R + S 4594b9ad928SBarry Smith 460ad4df100SBarry Smith Logically Collective on PC 4614b9ad928SBarry Smith 462d8d19677SJose E. Roman Input Parameters: 4634b9ad928SBarry Smith + pc - the preconditioner context 4644b9ad928SBarry Smith - alpha - scale on identity 4654b9ad928SBarry Smith 4664b9ad928SBarry Smith Level: Developer 4674b9ad928SBarry Smith 4684b9ad928SBarry Smith @*/ 4697087cfbeSBarry Smith PetscErrorCode PCCompositeSpecialSetAlpha(PC pc,PetscScalar alpha) 4704b9ad928SBarry Smith { 4714b9ad928SBarry Smith PetscFunctionBegin; 4720700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 473c5eb9154SBarry Smith PetscValidLogicalCollectiveScalar(pc,alpha,2); 474cac4c232SBarry Smith PetscTryMethod(pc,"PCCompositeSpecialSetAlpha_C",(PC,PetscScalar),(pc,alpha)); 4754b9ad928SBarry Smith PetscFunctionReturn(0); 4764b9ad928SBarry Smith } 4774b9ad928SBarry Smith 4784b9ad928SBarry Smith /*@C 4798aa07aa6SMatthew G. Knepley PCCompositeAddPCType - Adds another PC of the given type 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 489db781477SPatrick Sanan .seealso: `PCCompositeAddPC()` 4904b9ad928SBarry Smith @*/ 4918aa07aa6SMatthew G. Knepley PetscErrorCode PCCompositeAddPCType(PC pc,PCType type) 4924b9ad928SBarry Smith { 4934b9ad928SBarry Smith PetscFunctionBegin; 4940700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 495cac4c232SBarry Smith PetscTryMethod(pc,"PCCompositeAddPCType_C",(PC,PCType),(pc,type)); 4968aa07aa6SMatthew G. Knepley PetscFunctionReturn(0); 4978aa07aa6SMatthew G. Knepley } 4988aa07aa6SMatthew G. Knepley 4998aa07aa6SMatthew G. Knepley /*@ 5008aa07aa6SMatthew G. Knepley PCCompositeAddPC - Adds another PC to the composite PC. 5018aa07aa6SMatthew G. Knepley 5028aa07aa6SMatthew G. Knepley Collective on PC 5038aa07aa6SMatthew G. Knepley 5048aa07aa6SMatthew G. Knepley Input Parameters: 5058aa07aa6SMatthew G. Knepley + pc - the preconditioner context 5068aa07aa6SMatthew G. Knepley - subpc - the new preconditioner 5078aa07aa6SMatthew G. Knepley 5088aa07aa6SMatthew G. Knepley Level: Developer 5098aa07aa6SMatthew G. Knepley 510db781477SPatrick Sanan .seealso: `PCCompositeAddPCType()` 5118aa07aa6SMatthew G. Knepley @*/ 5128aa07aa6SMatthew G. Knepley PetscErrorCode PCCompositeAddPC(PC pc, PC subpc) 5138aa07aa6SMatthew G. Knepley { 5148aa07aa6SMatthew G. Knepley PetscFunctionBegin; 5158aa07aa6SMatthew G. Knepley PetscValidHeaderSpecific(pc,PC_CLASSID,1); 5168aa07aa6SMatthew G. Knepley PetscValidHeaderSpecific(subpc,PC_CLASSID,2); 517cac4c232SBarry Smith PetscTryMethod(pc,"PCCompositeAddPC_C",(PC,PC),(pc,subpc)); 5184b9ad928SBarry Smith PetscFunctionReturn(0); 5194b9ad928SBarry Smith } 5204b9ad928SBarry Smith 5218e6eba06SBarry Smith /*@ 5228e6eba06SBarry Smith PCCompositeGetNumberPC - Gets the number of PC objects in the composite PC. 5238e6eba06SBarry Smith 5248e6eba06SBarry Smith Not Collective 5258e6eba06SBarry Smith 5268e6eba06SBarry Smith Input Parameter: 5278e6eba06SBarry Smith . pc - the preconditioner context 5288e6eba06SBarry Smith 5298e6eba06SBarry Smith Output Parameter: 5308e6eba06SBarry Smith . num - the number of sub pcs 5318e6eba06SBarry Smith 5328e6eba06SBarry Smith Level: Developer 5338e6eba06SBarry Smith 534db781477SPatrick Sanan .seealso: `PCCompositeGetPC()` 5358e6eba06SBarry Smith @*/ 5368e6eba06SBarry Smith PetscErrorCode PCCompositeGetNumberPC(PC pc,PetscInt *num) 5378e6eba06SBarry Smith { 5388e6eba06SBarry Smith PetscFunctionBegin; 5398e6eba06SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 5408e6eba06SBarry Smith PetscValidIntPointer(num,2); 541cac4c232SBarry Smith PetscUseMethod(pc,"PCCompositeGetNumberPC_C",(PC,PetscInt*),(pc,num)); 5428e6eba06SBarry Smith PetscFunctionReturn(0); 5438e6eba06SBarry Smith } 5448e6eba06SBarry Smith 545f39d8e23SSatish Balay /*@ 5464b9ad928SBarry Smith PCCompositeGetPC - Gets one of the PC objects in the composite PC. 5474b9ad928SBarry Smith 5484b9ad928SBarry Smith Not Collective 5494b9ad928SBarry Smith 550d8d19677SJose E. Roman Input Parameters: 5512a6744ebSBarry Smith + pc - the preconditioner context 5522a6744ebSBarry Smith - n - the number of the pc requested 5534b9ad928SBarry Smith 5544b9ad928SBarry Smith Output Parameters: 5554b9ad928SBarry Smith . subpc - the PC requested 5564b9ad928SBarry Smith 5574b9ad928SBarry Smith Level: Developer 5584b9ad928SBarry Smith 55995452b02SPatrick Sanan Notes: 56095452b02SPatrick Sanan To use a different operator to construct one of the inner preconditioners first call PCCompositeGetPC(), then 5612b1d202aSBarry Smith call PCSetOperators() on that PC. 5622b1d202aSBarry Smith 563db781477SPatrick Sanan .seealso: `PCCompositeAddPCType()`, `PCCompositeGetNumberPC()`, `PCSetOperators()` 5644b9ad928SBarry Smith @*/ 5657087cfbeSBarry Smith PetscErrorCode PCCompositeGetPC(PC pc,PetscInt n,PC *subpc) 5664b9ad928SBarry Smith { 5674b9ad928SBarry Smith PetscFunctionBegin; 5680700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 5694482741eSBarry Smith PetscValidPointer(subpc,3); 570cac4c232SBarry Smith PetscUseMethod(pc,"PCCompositeGetPC_C",(PC,PetscInt,PC*),(pc,n,subpc)); 5714b9ad928SBarry Smith PetscFunctionReturn(0); 5724b9ad928SBarry Smith } 5734b9ad928SBarry Smith 5744b9ad928SBarry Smith /* -------------------------------------------------------------------------------------------*/ 5754b9ad928SBarry Smith 5764b9ad928SBarry Smith /*MC 5774b9ad928SBarry Smith PCCOMPOSITE - Build a preconditioner by composing together several preconditioners 5784b9ad928SBarry Smith 5794b9ad928SBarry Smith Options Database Keys: 5802eab2d5bSJungho Lee + -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type 5812b1d202aSBarry Smith . -pc_use_amat - activates PCSetUseAmat() 58251f519a2SBarry Smith - -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose 5834b9ad928SBarry Smith 5844b9ad928SBarry Smith Level: intermediate 5854b9ad928SBarry Smith 58695452b02SPatrick Sanan Notes: 58795452b02SPatrick Sanan To use a Krylov method inside the composite preconditioner, set the PCType of one or more 5884b9ad928SBarry Smith inner PCs to be PCKSP. 5894b9ad928SBarry Smith Using a Krylov method inside another Krylov method can be dangerous (you get divergence or 590b3ef52cdSBarry Smith the incorrect answer) unless you use KSPFGMRES as the outer Krylov method 5912b1d202aSBarry Smith To use a different operator to construct one of the inner preconditioners first call PCCompositeGetPC(), then 5922b1d202aSBarry Smith call PCSetOperators() on that PC. 5934b9ad928SBarry Smith 594db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, 595db781477SPatrick Sanan `PCSHELL`, `PCKSP`, `PCCompositeSetType()`, `PCCompositeSpecialSetAlpha()`, `PCCompositeAddPCType()`, 596db781477SPatrick Sanan `PCCompositeGetPC()`, `PCSetUseAmat()` 5974b9ad928SBarry Smith 5984b9ad928SBarry Smith M*/ 5994b9ad928SBarry Smith 6008cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc) 6014b9ad928SBarry Smith { 6024b9ad928SBarry Smith PC_Composite *jac; 6034b9ad928SBarry Smith 6044b9ad928SBarry Smith PetscFunctionBegin; 6059566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc,&jac)); 6062fa5cd67SKarl Rupp 6074b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 6082533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 6094b9ad928SBarry Smith pc->ops->setup = PCSetUp_Composite; 61069d2c0f9SBarry Smith pc->ops->reset = PCReset_Composite; 6114b9ad928SBarry Smith pc->ops->destroy = PCDestroy_Composite; 6124b9ad928SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Composite; 6134b9ad928SBarry Smith pc->ops->view = PCView_Composite; 6140a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 6154b9ad928SBarry Smith 6164b9ad928SBarry Smith pc->data = (void*)jac; 6174b9ad928SBarry Smith jac->type = PC_COMPOSITE_ADDITIVE; 6180a545947SLisandro Dalcin jac->work1 = NULL; 6190a545947SLisandro Dalcin jac->work2 = NULL; 6200a545947SLisandro Dalcin jac->head = NULL; 6214b9ad928SBarry Smith 6229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSetType_C",PCCompositeSetType_Composite)); 6239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetType_C",PCCompositeGetType_Composite)); 6249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPCType_C",PCCompositeAddPCType_Composite)); 6259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeAddPC_C",PCCompositeAddPC_Composite)); 6269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetNumberPC_C",PCCompositeGetNumberPC_Composite)); 6279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeGetPC_C",PCCompositeGetPC_Composite)); 6289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCCompositeSpecialSetAlpha_C",PCCompositeSpecialSetAlpha_Composite)); 6294b9ad928SBarry Smith PetscFunctionReturn(0); 6304b9ad928SBarry Smith } 631