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 23d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_Composite_Multiplicative(PC pc, Vec x, Vec y) 24d71ae5a4SJacob Faibussowitsch { 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 64d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_Composite_Multiplicative(PC pc, Vec x, Vec y) 65d71ae5a4SJacob Faibussowitsch { 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 */ 77ad540459SPierre Jolivet while (next->next) next = next->next; 789566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc, x, y)); 792533e041SBarry Smith while (next->previous) { 802533e041SBarry Smith next = next->previous; 819566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(mat, y, jac->work1)); 829566063dSJacob Faibussowitsch PetscCall(VecWAXPY(jac->work2, -1.0, jac->work1, x)); 839566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc, jac->work2, jac->work1)); 849566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); 852533e041SBarry Smith } 862533e041SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 872533e041SBarry Smith next = jac->head; 882533e041SBarry Smith while (next->next) { 892533e041SBarry Smith next = next->next; 909566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(mat, y, jac->work1)); 919566063dSJacob Faibussowitsch PetscCall(VecWAXPY(jac->work2, -1.0, jac->work1, x)); 929566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc, jac->work2, jac->work1)); 939566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); 942533e041SBarry Smith } 952533e041SBarry Smith } 962533e041SBarry Smith PetscFunctionReturn(0); 972533e041SBarry Smith } 982533e041SBarry Smith 994b9ad928SBarry Smith /* 1004b9ad928SBarry Smith This is very special for a matrix of the form alpha I + R + S 1014b9ad928SBarry Smith where first preconditioner is built from alpha I + S and second from 1024b9ad928SBarry Smith alpha I + R 1034b9ad928SBarry Smith */ 104d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_Composite_Special(PC pc, Vec x, Vec y) 105d71ae5a4SJacob Faibussowitsch { 1064b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1074b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1084b9ad928SBarry Smith 1094b9ad928SBarry Smith PetscFunctionBegin; 11028b400f6SJacob Faibussowitsch PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 1117827d75bSBarry Smith PetscCheck(next->next && !next->next->next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Special composite preconditioners requires exactly two PCs"); 1124b9ad928SBarry Smith 113450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 1149566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->pc, pc->reusepreconditioner)); 1159566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->next->pc, pc->reusepreconditioner)); 116450d59ebSPatrick Farrell 1179566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, x, jac->work1)); 1189566063dSJacob Faibussowitsch PetscCall(PCApply(next->next->pc, jac->work1, y)); 1194b9ad928SBarry Smith PetscFunctionReturn(0); 1204b9ad928SBarry Smith } 1214b9ad928SBarry Smith 122d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_Composite_Additive(PC pc, Vec x, Vec y) 123d71ae5a4SJacob Faibussowitsch { 1244b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1254b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1264b9ad928SBarry Smith 1274b9ad928SBarry Smith PetscFunctionBegin; 12828b400f6SJacob Faibussowitsch PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 129450d59ebSPatrick Farrell 130450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 131450d59ebSPatrick Farrell while (next) { 1329566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->pc, pc->reusepreconditioner)); 133450d59ebSPatrick Farrell next = next->next; 134450d59ebSPatrick Farrell } 135450d59ebSPatrick Farrell next = jac->head; 136450d59ebSPatrick Farrell 1379566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, x, y)); 1384b9ad928SBarry Smith while (next->next) { 1394b9ad928SBarry Smith next = next->next; 1409566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, x, jac->work1)); 1419566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); 1424b9ad928SBarry Smith } 1434b9ad928SBarry Smith PetscFunctionReturn(0); 1444b9ad928SBarry Smith } 1454b9ad928SBarry Smith 146d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_Composite_Additive(PC pc, Vec x, Vec y) 147d71ae5a4SJacob Faibussowitsch { 1482533e041SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1492533e041SBarry Smith PC_CompositeLink next = jac->head; 1502533e041SBarry Smith 1512533e041SBarry Smith PetscFunctionBegin; 15228b400f6SJacob Faibussowitsch PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 1539566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc, x, y)); 1542533e041SBarry Smith while (next->next) { 1552533e041SBarry Smith next = next->next; 1569566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc, x, jac->work1)); 1579566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); 1582533e041SBarry Smith } 1592533e041SBarry Smith PetscFunctionReturn(0); 1602533e041SBarry Smith } 1612533e041SBarry Smith 162d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_Composite(PC pc) 163d71ae5a4SJacob Faibussowitsch { 1644b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1654b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1665a78d018SMatthew G. Knepley DM dm; 1674b9ad928SBarry Smith 1684b9ad928SBarry Smith PetscFunctionBegin; 16948a46eb9SPierre Jolivet if (!jac->work1) PetscCall(MatCreateVecs(pc->pmat, &jac->work1, NULL)); 1709566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 1714b9ad928SBarry Smith while (next) { 17248a46eb9SPierre Jolivet if (!next->pc->dm) PetscCall(PCSetDM(next->pc, dm)); 17348a46eb9SPierre Jolivet if (!next->pc->mat) PetscCall(PCSetOperators(next->pc, pc->mat, pc->pmat)); 1744b9ad928SBarry Smith next = next->next; 1754b9ad928SBarry Smith } 1764b9ad928SBarry Smith PetscFunctionReturn(0); 1774b9ad928SBarry Smith } 1784b9ad928SBarry Smith 179d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_Composite(PC pc) 180d71ae5a4SJacob Faibussowitsch { 18169d2c0f9SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1825f48b12bSBarry Smith PC_CompositeLink next = jac->head; 18369d2c0f9SBarry Smith 18469d2c0f9SBarry Smith PetscFunctionBegin; 18569d2c0f9SBarry Smith while (next) { 1869566063dSJacob Faibussowitsch PetscCall(PCReset(next->pc)); 18769d2c0f9SBarry Smith next = next->next; 18869d2c0f9SBarry Smith } 1899566063dSJacob Faibussowitsch PetscCall(VecDestroy(&jac->work1)); 1909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&jac->work2)); 19169d2c0f9SBarry Smith PetscFunctionReturn(0); 19269d2c0f9SBarry Smith } 19369d2c0f9SBarry Smith 194d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_Composite(PC pc) 195d71ae5a4SJacob Faibussowitsch { 1964b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 197724c2c99SHong Zhang PC_CompositeLink next = jac->head, next_tmp; 1984b9ad928SBarry Smith 1994b9ad928SBarry Smith PetscFunctionBegin; 2009566063dSJacob Faibussowitsch PetscCall(PCReset_Composite(pc)); 2014b9ad928SBarry Smith while (next) { 2029566063dSJacob Faibussowitsch PetscCall(PCDestroy(&next->pc)); 203724c2c99SHong Zhang next_tmp = next; 2044b9ad928SBarry Smith next = next->next; 2059566063dSJacob Faibussowitsch PetscCall(PetscFree(next_tmp)); 2064b9ad928SBarry Smith } 2072e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSetType_C", NULL)); 2082e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetType_C", NULL)); 2092e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPCType_C", NULL)); 2102e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPC_C", NULL)); 2112e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetNumberPC_C", NULL)); 2122e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetPC_C", NULL)); 2132e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSpecialSetAlpha_C", NULL)); 2149566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 2154b9ad928SBarry Smith PetscFunctionReturn(0); 2164b9ad928SBarry Smith } 2174b9ad928SBarry Smith 218d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_Composite(PC pc, PetscOptionItems *PetscOptionsObject) 219d71ae5a4SJacob Faibussowitsch { 2204b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 2219dcbbd2bSBarry Smith PetscInt nmax = 8, i; 2224b9ad928SBarry Smith PC_CompositeLink next; 223e5999256SBarry Smith char *pcs[8]; 224ace3abfcSBarry Smith PetscBool flg; 2254b9ad928SBarry Smith 2264b9ad928SBarry Smith PetscFunctionBegin; 227d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Composite preconditioner options"); 2289566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-pc_composite_type", "Type of composition", "PCCompositeSetType", PCCompositeTypes, (PetscEnum)jac->type, (PetscEnum *)&jac->type, &flg)); 2291baa6e33SBarry Smith if (flg) PetscCall(PCCompositeSetType(pc, jac->type)); 2309566063dSJacob Faibussowitsch PetscCall(PetscOptionsStringArray("-pc_composite_pcs", "List of composite solvers", "PCCompositeAddPCType", pcs, &nmax, &flg)); 2314b9ad928SBarry Smith if (flg) { 2324b9ad928SBarry Smith for (i = 0; i < nmax; i++) { 2339566063dSJacob Faibussowitsch PetscCall(PCCompositeAddPCType(pc, pcs[i])); 2349566063dSJacob Faibussowitsch PetscCall(PetscFree(pcs[i])); /* deallocate string pcs[i], which is allocated in PetscOptionsStringArray() */ 2354b9ad928SBarry Smith } 2364b9ad928SBarry Smith } 237d0609cedSBarry Smith PetscOptionsHeadEnd(); 2384b9ad928SBarry Smith 2394b9ad928SBarry Smith next = jac->head; 2404b9ad928SBarry Smith while (next) { 2419566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(next->pc)); 2424b9ad928SBarry Smith next = next->next; 2434b9ad928SBarry Smith } 2444b9ad928SBarry Smith PetscFunctionReturn(0); 2454b9ad928SBarry Smith } 2464b9ad928SBarry Smith 247d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_Composite(PC pc, PetscViewer viewer) 248d71ae5a4SJacob Faibussowitsch { 2494b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 2504b9ad928SBarry Smith PC_CompositeLink next = jac->head; 251ace3abfcSBarry Smith PetscBool iascii; 2524b9ad928SBarry Smith 2534b9ad928SBarry Smith PetscFunctionBegin; 2549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 25532077d6dSBarry Smith if (iascii) { 2569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Composite PC type - %s\n", PCCompositeTypes[jac->type])); 2579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "PCs on composite preconditioner follow\n")); 2589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "---------------------------------\n")); 2594b9ad928SBarry Smith } 2601baa6e33SBarry Smith if (iascii) PetscCall(PetscViewerASCIIPushTab(viewer)); 2614b9ad928SBarry Smith while (next) { 2629566063dSJacob Faibussowitsch PetscCall(PCView(next->pc, viewer)); 2634b9ad928SBarry Smith next = next->next; 2644b9ad928SBarry Smith } 26532077d6dSBarry Smith if (iascii) { 2669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 2679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "---------------------------------\n")); 2684b9ad928SBarry Smith } 2694b9ad928SBarry Smith PetscFunctionReturn(0); 2704b9ad928SBarry Smith } 2714b9ad928SBarry Smith 272d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeSpecialSetAlpha_Composite(PC pc, PetscScalar alpha) 273d71ae5a4SJacob Faibussowitsch { 2744b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 2755fd66863SKarl Rupp 2764b9ad928SBarry Smith PetscFunctionBegin; 2774b9ad928SBarry Smith jac->alpha = alpha; 2784b9ad928SBarry Smith PetscFunctionReturn(0); 2794b9ad928SBarry Smith } 2804b9ad928SBarry Smith 281d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeSetType_Composite(PC pc, PCCompositeType type) 282d71ae5a4SJacob Faibussowitsch { 283fad69fbaSJed Brown PC_Composite *jac = (PC_Composite *)pc->data; 284fad69fbaSJed Brown 2854b9ad928SBarry Smith PetscFunctionBegin; 2864b9ad928SBarry Smith if (type == PC_COMPOSITE_ADDITIVE) { 2874b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 2882533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 289421e10b8SBarry Smith } else if (type == PC_COMPOSITE_MULTIPLICATIVE || type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 2904b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Multiplicative; 2912533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Multiplicative; 2924b9ad928SBarry Smith } else if (type == PC_COMPOSITE_SPECIAL) { 2934b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Special; 2940298fd71SBarry Smith pc->ops->applytranspose = NULL; 295a7261c6bSprj- } else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown composite preconditioner type"); 296fad69fbaSJed Brown jac->type = type; 2974b9ad928SBarry Smith PetscFunctionReturn(0); 2984b9ad928SBarry Smith } 2994b9ad928SBarry Smith 300d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeGetType_Composite(PC pc, PCCompositeType *type) 301d71ae5a4SJacob Faibussowitsch { 302c60c7ad4SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 303c60c7ad4SBarry Smith 304c60c7ad4SBarry Smith PetscFunctionBegin; 305c60c7ad4SBarry Smith *type = jac->type; 306c60c7ad4SBarry Smith PetscFunctionReturn(0); 307c60c7ad4SBarry Smith } 308c60c7ad4SBarry Smith 309d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeAddPC_Composite(PC pc, PC subpc) 310d71ae5a4SJacob Faibussowitsch { 3114b9ad928SBarry Smith PC_Composite *jac; 3125a9f2f41SSatish Balay PC_CompositeLink next, ilink; 31379416396SBarry Smith PetscInt cnt = 0; 3142dcb1b2aSMatthew Knepley const char *prefix; 315d726e3a5SJed Brown char newprefix[20]; 3164b9ad928SBarry Smith 3174b9ad928SBarry Smith PetscFunctionBegin; 3184dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&ilink)); 3190a545947SLisandro Dalcin ilink->next = NULL; 3208aa07aa6SMatthew G. Knepley ilink->pc = subpc; 3214b9ad928SBarry Smith 3224b9ad928SBarry Smith jac = (PC_Composite *)pc->data; 3234b9ad928SBarry Smith next = jac->head; 3244b9ad928SBarry Smith if (!next) { 3255a9f2f41SSatish Balay jac->head = ilink; 3260298fd71SBarry Smith ilink->previous = NULL; 3274b9ad928SBarry Smith } else { 3284b9ad928SBarry Smith cnt++; 3294b9ad928SBarry Smith while (next->next) { 3304b9ad928SBarry Smith next = next->next; 3314b9ad928SBarry Smith cnt++; 3324b9ad928SBarry Smith } 3335a9f2f41SSatish Balay next->next = ilink; 334421e10b8SBarry Smith ilink->previous = next; 3354b9ad928SBarry Smith } 3369566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix)); 3379566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(subpc, prefix)); 3389566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(newprefix, 20, "sub_%d_", (int)cnt)); 3399566063dSJacob Faibussowitsch PetscCall(PCAppendOptionsPrefix(subpc, newprefix)); 3409566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)subpc)); 3418aa07aa6SMatthew G. Knepley PetscFunctionReturn(0); 3428aa07aa6SMatthew G. Knepley } 3438aa07aa6SMatthew G. Knepley 344d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeAddPCType_Composite(PC pc, PCType type) 345d71ae5a4SJacob Faibussowitsch { 3468aa07aa6SMatthew G. Knepley PC subpc; 3478aa07aa6SMatthew G. Knepley 3488aa07aa6SMatthew G. Knepley PetscFunctionBegin; 3499566063dSJacob Faibussowitsch PetscCall(PCCreate(PetscObjectComm((PetscObject)pc), &subpc)); 3509566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)subpc, (PetscObject)pc, 1)); 3519566063dSJacob Faibussowitsch PetscCall(PCCompositeAddPC_Composite(pc, subpc)); 3524b9ad928SBarry Smith /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */ 3539566063dSJacob Faibussowitsch PetscCall(PCSetType(subpc, type)); 3549566063dSJacob Faibussowitsch PetscCall(PCDestroy(&subpc)); 3554b9ad928SBarry Smith PetscFunctionReturn(0); 3564b9ad928SBarry Smith } 3574b9ad928SBarry Smith 358d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeGetNumberPC_Composite(PC pc, PetscInt *n) 359d71ae5a4SJacob Faibussowitsch { 3608e6eba06SBarry Smith PC_Composite *jac; 3618e6eba06SBarry Smith PC_CompositeLink next; 3628e6eba06SBarry Smith 3638e6eba06SBarry Smith PetscFunctionBegin; 3648e6eba06SBarry Smith jac = (PC_Composite *)pc->data; 3658e6eba06SBarry Smith next = jac->head; 3668e6eba06SBarry Smith *n = 0; 3678e6eba06SBarry Smith while (next) { 3688e6eba06SBarry Smith next = next->next; 3698e6eba06SBarry Smith (*n)++; 3708e6eba06SBarry Smith } 3718e6eba06SBarry Smith PetscFunctionReturn(0); 3728e6eba06SBarry Smith } 3738e6eba06SBarry Smith 374d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeGetPC_Composite(PC pc, PetscInt n, PC *subpc) 375d71ae5a4SJacob Faibussowitsch { 3764b9ad928SBarry Smith PC_Composite *jac; 3774b9ad928SBarry Smith PC_CompositeLink next; 37879416396SBarry Smith PetscInt i; 3794b9ad928SBarry Smith 3804b9ad928SBarry Smith PetscFunctionBegin; 3814b9ad928SBarry Smith jac = (PC_Composite *)pc->data; 3824b9ad928SBarry Smith next = jac->head; 3834b9ad928SBarry Smith for (i = 0; i < n; i++) { 38428b400f6SJacob Faibussowitsch PetscCheck(next->next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Not enough PCs in composite preconditioner"); 3854b9ad928SBarry Smith next = next->next; 3864b9ad928SBarry Smith } 3874b9ad928SBarry Smith *subpc = next->pc; 3884b9ad928SBarry Smith PetscFunctionReturn(0); 3894b9ad928SBarry Smith } 3904b9ad928SBarry Smith 391f39d8e23SSatish Balay /*@ 3924b9ad928SBarry Smith PCCompositeSetType - Sets the type of composite preconditioner. 3934b9ad928SBarry Smith 394*c3339decSBarry Smith Logically Collective 3954b9ad928SBarry Smith 396c60c7ad4SBarry Smith Input Parameters: 3972a6744ebSBarry Smith + pc - the preconditioner context 398f1580f4eSBarry Smith - type - `PC_COMPOSITE_ADDITIVE` (default), `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL` 3994b9ad928SBarry Smith 4004b9ad928SBarry Smith Options Database Key: 4014b9ad928SBarry Smith . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 4024b9ad928SBarry Smith 403f1580f4eSBarry Smith Level: advanced 4044b9ad928SBarry Smith 405f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL`, `PCCompositeType`, 406f1580f4eSBarry Smith `PCCompositeGetType()` 4074b9ad928SBarry Smith @*/ 408d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeSetType(PC pc, PCCompositeType type) 409d71ae5a4SJacob Faibussowitsch { 4104b9ad928SBarry Smith PetscFunctionBegin; 4110700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 412c5eb9154SBarry Smith PetscValidLogicalCollectiveEnum(pc, type, 2); 413cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeSetType_C", (PC, PCCompositeType), (pc, type)); 4144b9ad928SBarry Smith PetscFunctionReturn(0); 4154b9ad928SBarry Smith } 4164b9ad928SBarry Smith 417c60c7ad4SBarry Smith /*@ 418721f67b5SBarry Smith PCCompositeGetType - Gets the type of composite preconditioner. 419c60c7ad4SBarry Smith 420*c3339decSBarry Smith Logically Collective 421c60c7ad4SBarry Smith 422c60c7ad4SBarry Smith Input Parameter: 423c60c7ad4SBarry Smith . pc - the preconditioner context 424c60c7ad4SBarry Smith 425c60c7ad4SBarry Smith Output Parameter: 426f1580f4eSBarry Smith . type - `PC_COMPOSITE_ADDITIVE` (default), `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL` 427c60c7ad4SBarry Smith 428f1580f4eSBarry Smith Level: advanced 429c60c7ad4SBarry Smith 430f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL`, `PCCompositeType`, 431f1580f4eSBarry Smith `PCCompositeSetType()` 432c60c7ad4SBarry Smith @*/ 433d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeGetType(PC pc, PCCompositeType *type) 434d71ae5a4SJacob Faibussowitsch { 435c60c7ad4SBarry Smith PetscFunctionBegin; 436c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 437cac4c232SBarry Smith PetscUseMethod(pc, "PCCompositeGetType_C", (PC, PCCompositeType *), (pc, type)); 438c60c7ad4SBarry Smith PetscFunctionReturn(0); 439c60c7ad4SBarry Smith } 440c60c7ad4SBarry Smith 441f39d8e23SSatish Balay /*@ 442f1580f4eSBarry Smith PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner, `PC_COMPOSITE_SPECIAL`, 4434b9ad928SBarry Smith for alphaI + R + S 4444b9ad928SBarry Smith 445*c3339decSBarry Smith Logically Collective 4464b9ad928SBarry Smith 447d8d19677SJose E. Roman Input Parameters: 4484b9ad928SBarry Smith + pc - the preconditioner context 4494b9ad928SBarry Smith - alpha - scale on identity 4504b9ad928SBarry Smith 4514b9ad928SBarry Smith Level: Developer 4524b9ad928SBarry Smith 453f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL`, `PCCompositeType`, 454f1580f4eSBarry Smith `PCCompositeSetType()`, `PCCompositeGetType()` 4554b9ad928SBarry Smith @*/ 456d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeSpecialSetAlpha(PC pc, PetscScalar alpha) 457d71ae5a4SJacob Faibussowitsch { 4584b9ad928SBarry Smith PetscFunctionBegin; 4590700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 460c5eb9154SBarry Smith PetscValidLogicalCollectiveScalar(pc, alpha, 2); 461cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeSpecialSetAlpha_C", (PC, PetscScalar), (pc, alpha)); 4624b9ad928SBarry Smith PetscFunctionReturn(0); 4634b9ad928SBarry Smith } 4644b9ad928SBarry Smith 4654b9ad928SBarry Smith /*@C 466f1580f4eSBarry Smith PCCompositeAddPCType - Adds another `PC` of the given type to the composite `PC`. 4674b9ad928SBarry Smith 468*c3339decSBarry Smith Collective 4694b9ad928SBarry Smith 4704b9ad928SBarry Smith Input Parameters: 4712a6744ebSBarry Smith + pc - the preconditioner context 4722a6744ebSBarry Smith - type - the type of the new preconditioner 4734b9ad928SBarry Smith 474f1580f4eSBarry Smith Level: intermediate 4754b9ad928SBarry Smith 476f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PCCompositeAddPC()`, `PCCompositeGetNumberPC()` 4774b9ad928SBarry Smith @*/ 478d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeAddPCType(PC pc, PCType type) 479d71ae5a4SJacob Faibussowitsch { 4804b9ad928SBarry Smith PetscFunctionBegin; 4810700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 482cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeAddPCType_C", (PC, PCType), (pc, type)); 4838aa07aa6SMatthew G. Knepley PetscFunctionReturn(0); 4848aa07aa6SMatthew G. Knepley } 4858aa07aa6SMatthew G. Knepley 4868aa07aa6SMatthew G. Knepley /*@ 487f1580f4eSBarry Smith PCCompositeAddPC - Adds another `PC` to the composite `PC`. 4888aa07aa6SMatthew G. Knepley 489*c3339decSBarry Smith Collective 4908aa07aa6SMatthew G. Knepley 4918aa07aa6SMatthew G. Knepley Input Parameters: 4928aa07aa6SMatthew G. Knepley + pc - the preconditioner context 4938aa07aa6SMatthew G. Knepley - subpc - the new preconditioner 4948aa07aa6SMatthew G. Knepley 495f1580f4eSBarry Smith Level: intermediate 4968aa07aa6SMatthew G. Knepley 497f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PCCompositeAddPCType()`, `PCCompositeGetNumberPC()` 4988aa07aa6SMatthew G. Knepley @*/ 499d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeAddPC(PC pc, PC subpc) 500d71ae5a4SJacob Faibussowitsch { 5018aa07aa6SMatthew G. Knepley PetscFunctionBegin; 5028aa07aa6SMatthew G. Knepley PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5038aa07aa6SMatthew G. Knepley PetscValidHeaderSpecific(subpc, PC_CLASSID, 2); 504cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeAddPC_C", (PC, PC), (pc, subpc)); 5054b9ad928SBarry Smith PetscFunctionReturn(0); 5064b9ad928SBarry Smith } 5074b9ad928SBarry Smith 5088e6eba06SBarry Smith /*@ 509f1580f4eSBarry Smith PCCompositeGetNumberPC - Gets the number of `PC` objects in the composite `PC`. 5108e6eba06SBarry Smith 5118e6eba06SBarry Smith Not Collective 5128e6eba06SBarry Smith 5138e6eba06SBarry Smith Input Parameter: 5148e6eba06SBarry Smith . pc - the preconditioner context 5158e6eba06SBarry Smith 5168e6eba06SBarry Smith Output Parameter: 5178e6eba06SBarry Smith . num - the number of sub pcs 5188e6eba06SBarry Smith 5198e6eba06SBarry Smith Level: Developer 5208e6eba06SBarry Smith 521f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PCCompositeGetPC()`, `PCCompositeAddPC()`, `PCCompositeAddPCType()` 5228e6eba06SBarry Smith @*/ 523d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeGetNumberPC(PC pc, PetscInt *num) 524d71ae5a4SJacob Faibussowitsch { 5258e6eba06SBarry Smith PetscFunctionBegin; 5268e6eba06SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5278e6eba06SBarry Smith PetscValidIntPointer(num, 2); 528cac4c232SBarry Smith PetscUseMethod(pc, "PCCompositeGetNumberPC_C", (PC, PetscInt *), (pc, num)); 5298e6eba06SBarry Smith PetscFunctionReturn(0); 5308e6eba06SBarry Smith } 5318e6eba06SBarry Smith 532f39d8e23SSatish Balay /*@ 533f1580f4eSBarry Smith PCCompositeGetPC - Gets one of the `PC` objects in the composite `PC`. 5344b9ad928SBarry Smith 5354b9ad928SBarry Smith Not Collective 5364b9ad928SBarry Smith 537d8d19677SJose E. Roman Input Parameters: 5382a6744ebSBarry Smith + pc - the preconditioner context 5392a6744ebSBarry Smith - n - the number of the pc requested 5404b9ad928SBarry Smith 541f1580f4eSBarry Smith Output Parameter: 5424b9ad928SBarry Smith . subpc - the PC requested 5434b9ad928SBarry Smith 544f1580f4eSBarry Smith Level: intermediate 5454b9ad928SBarry Smith 546f1580f4eSBarry Smith Note: 547f1580f4eSBarry Smith To use a different operator to construct one of the inner preconditioners first call `PCCompositeGetPC()`, then 548f1580f4eSBarry Smith call `PCSetOperators()` on that `PC`. 5492b1d202aSBarry Smith 550f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PCCompositeAddPCType()`, `PCCompositeGetNumberPC()`, `PCSetOperators()` 5514b9ad928SBarry Smith @*/ 552d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeGetPC(PC pc, PetscInt n, PC *subpc) 553d71ae5a4SJacob Faibussowitsch { 5544b9ad928SBarry Smith PetscFunctionBegin; 5550700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5564482741eSBarry Smith PetscValidPointer(subpc, 3); 557cac4c232SBarry Smith PetscUseMethod(pc, "PCCompositeGetPC_C", (PC, PetscInt, PC *), (pc, n, subpc)); 5584b9ad928SBarry Smith PetscFunctionReturn(0); 5594b9ad928SBarry Smith } 5604b9ad928SBarry Smith 5614b9ad928SBarry Smith /*MC 5624b9ad928SBarry Smith PCCOMPOSITE - Build a preconditioner by composing together several preconditioners 5634b9ad928SBarry Smith 5644b9ad928SBarry Smith Options Database Keys: 5652eab2d5bSJungho Lee + -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type 566f1580f4eSBarry Smith . -pc_use_amat - activates `PCSetUseAmat()` 56751f519a2SBarry Smith - -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose 5684b9ad928SBarry Smith 5694b9ad928SBarry Smith Level: intermediate 5704b9ad928SBarry Smith 57195452b02SPatrick Sanan Notes: 572f1580f4eSBarry Smith To use a Krylov method inside the composite preconditioner, set the `PCType` of one or more 573f1580f4eSBarry Smith inner `PC`s to be `PCKSP`. Using a Krylov method inside another Krylov method can be dangerous (you get divergence or 574f1580f4eSBarry Smith the incorrect answer) unless you use `KSPFGMRES` as the outer Krylov method 575f1580f4eSBarry Smith 576f1580f4eSBarry Smith To use a different operator to construct one of the inner preconditioners first call `PCCompositeGetPC()`, then 577f1580f4eSBarry Smith call `PCSetOperators()` on that `PC`. 5784b9ad928SBarry Smith 579db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, 580db781477SPatrick Sanan `PCSHELL`, `PCKSP`, `PCCompositeSetType()`, `PCCompositeSpecialSetAlpha()`, `PCCompositeAddPCType()`, 581f1580f4eSBarry Smith `PCCompositeGetPC()`, `PCSetUseAmat()`, `PCCompositeAddPC()`, `PCCompositeGetNumberPC()` 5824b9ad928SBarry Smith M*/ 5834b9ad928SBarry Smith 584d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc) 585d71ae5a4SJacob Faibussowitsch { 5864b9ad928SBarry Smith PC_Composite *jac; 5874b9ad928SBarry Smith 5884b9ad928SBarry Smith PetscFunctionBegin; 5894dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&jac)); 5902fa5cd67SKarl Rupp 5914b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 5922533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 5934b9ad928SBarry Smith pc->ops->setup = PCSetUp_Composite; 59469d2c0f9SBarry Smith pc->ops->reset = PCReset_Composite; 5954b9ad928SBarry Smith pc->ops->destroy = PCDestroy_Composite; 5964b9ad928SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Composite; 5974b9ad928SBarry Smith pc->ops->view = PCView_Composite; 5980a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 5994b9ad928SBarry Smith 6004b9ad928SBarry Smith pc->data = (void *)jac; 6014b9ad928SBarry Smith jac->type = PC_COMPOSITE_ADDITIVE; 6020a545947SLisandro Dalcin jac->work1 = NULL; 6030a545947SLisandro Dalcin jac->work2 = NULL; 6040a545947SLisandro Dalcin jac->head = NULL; 6054b9ad928SBarry Smith 6069566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSetType_C", PCCompositeSetType_Composite)); 6079566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetType_C", PCCompositeGetType_Composite)); 6089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPCType_C", PCCompositeAddPCType_Composite)); 6099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPC_C", PCCompositeAddPC_Composite)); 6109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetNumberPC_C", PCCompositeGetNumberPC_Composite)); 6119566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetPC_C", PCCompositeGetPC_Composite)); 6129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSpecialSetAlpha_C", PCCompositeSpecialSetAlpha_Composite)); 6134b9ad928SBarry Smith PetscFunctionReturn(0); 6144b9ad928SBarry Smith } 615