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 } 613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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 } 963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 1193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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 } 1433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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 } 1593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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 } 1763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1774b9ad928SBarry Smith } 1784b9ad928SBarry Smith 1794f853519SStefano Zampini static PetscErrorCode PCSetUpOnBlocks_Composite(PC pc) 1804f853519SStefano Zampini { 1814f853519SStefano Zampini PC_Composite *jac = (PC_Composite *)pc->data; 1824f853519SStefano Zampini PC_CompositeLink next = jac->head; 1834f853519SStefano Zampini PCFailedReason reason; 1844f853519SStefano Zampini 1854f853519SStefano Zampini PetscFunctionBegin; 1864f853519SStefano Zampini while (next) { 1874f853519SStefano Zampini PetscCall(PCSetUp(next->pc)); 1884f853519SStefano Zampini PetscCall(PCGetFailedReasonRank(next->pc, &reason)); 1894f853519SStefano Zampini if (reason) pc->failedreason = reason; 1904f853519SStefano Zampini next = next->next; 1914f853519SStefano Zampini } 1924f853519SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1934f853519SStefano Zampini } 1944f853519SStefano Zampini 195d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_Composite(PC pc) 196d71ae5a4SJacob Faibussowitsch { 19769d2c0f9SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1985f48b12bSBarry Smith PC_CompositeLink next = jac->head; 19969d2c0f9SBarry Smith 20069d2c0f9SBarry Smith PetscFunctionBegin; 20169d2c0f9SBarry Smith while (next) { 2029566063dSJacob Faibussowitsch PetscCall(PCReset(next->pc)); 20369d2c0f9SBarry Smith next = next->next; 20469d2c0f9SBarry Smith } 2059566063dSJacob Faibussowitsch PetscCall(VecDestroy(&jac->work1)); 2069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&jac->work2)); 2073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20869d2c0f9SBarry Smith } 20969d2c0f9SBarry Smith 210d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_Composite(PC pc) 211d71ae5a4SJacob Faibussowitsch { 2124b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 213724c2c99SHong Zhang PC_CompositeLink next = jac->head, next_tmp; 2144b9ad928SBarry Smith 2154b9ad928SBarry Smith PetscFunctionBegin; 2169566063dSJacob Faibussowitsch PetscCall(PCReset_Composite(pc)); 2174b9ad928SBarry Smith while (next) { 2189566063dSJacob Faibussowitsch PetscCall(PCDestroy(&next->pc)); 219724c2c99SHong Zhang next_tmp = next; 2204b9ad928SBarry Smith next = next->next; 2219566063dSJacob Faibussowitsch PetscCall(PetscFree(next_tmp)); 2224b9ad928SBarry Smith } 2232e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSetType_C", NULL)); 2242e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetType_C", NULL)); 2252e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPCType_C", NULL)); 2262e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPC_C", NULL)); 2272e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetNumberPC_C", NULL)); 2282e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetPC_C", NULL)); 2292e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSpecialSetAlpha_C", NULL)); 2309566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 2313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2324b9ad928SBarry Smith } 2334b9ad928SBarry Smith 234d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_Composite(PC pc, PetscOptionItems *PetscOptionsObject) 235d71ae5a4SJacob Faibussowitsch { 2364b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 2379dcbbd2bSBarry Smith PetscInt nmax = 8, i; 2384b9ad928SBarry Smith PC_CompositeLink next; 239e5999256SBarry Smith char *pcs[8]; 240ace3abfcSBarry Smith PetscBool flg; 2414b9ad928SBarry Smith 2424b9ad928SBarry Smith PetscFunctionBegin; 243d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Composite preconditioner options"); 2449566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-pc_composite_type", "Type of composition", "PCCompositeSetType", PCCompositeTypes, (PetscEnum)jac->type, (PetscEnum *)&jac->type, &flg)); 2451baa6e33SBarry Smith if (flg) PetscCall(PCCompositeSetType(pc, jac->type)); 2469566063dSJacob Faibussowitsch PetscCall(PetscOptionsStringArray("-pc_composite_pcs", "List of composite solvers", "PCCompositeAddPCType", pcs, &nmax, &flg)); 2474b9ad928SBarry Smith if (flg) { 2484b9ad928SBarry Smith for (i = 0; i < nmax; i++) { 2499566063dSJacob Faibussowitsch PetscCall(PCCompositeAddPCType(pc, pcs[i])); 2509566063dSJacob Faibussowitsch PetscCall(PetscFree(pcs[i])); /* deallocate string pcs[i], which is allocated in PetscOptionsStringArray() */ 2514b9ad928SBarry Smith } 2524b9ad928SBarry Smith } 253d0609cedSBarry Smith PetscOptionsHeadEnd(); 2544b9ad928SBarry Smith 2554b9ad928SBarry Smith next = jac->head; 2564b9ad928SBarry Smith while (next) { 2579566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(next->pc)); 2584b9ad928SBarry Smith next = next->next; 2594b9ad928SBarry Smith } 2603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2614b9ad928SBarry Smith } 2624b9ad928SBarry Smith 263d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_Composite(PC pc, PetscViewer viewer) 264d71ae5a4SJacob Faibussowitsch { 2654b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 2664b9ad928SBarry Smith PC_CompositeLink next = jac->head; 267ace3abfcSBarry Smith PetscBool iascii; 2684b9ad928SBarry Smith 2694b9ad928SBarry Smith PetscFunctionBegin; 2709566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 27132077d6dSBarry Smith if (iascii) { 2729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Composite PC type - %s\n", PCCompositeTypes[jac->type])); 2739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "PCs on composite preconditioner follow\n")); 2749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "---------------------------------\n")); 2754b9ad928SBarry Smith } 2761baa6e33SBarry Smith if (iascii) PetscCall(PetscViewerASCIIPushTab(viewer)); 2774b9ad928SBarry Smith while (next) { 2789566063dSJacob Faibussowitsch PetscCall(PCView(next->pc, viewer)); 2794b9ad928SBarry Smith next = next->next; 2804b9ad928SBarry Smith } 28132077d6dSBarry Smith if (iascii) { 2829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 2839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "---------------------------------\n")); 2844b9ad928SBarry Smith } 2853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2864b9ad928SBarry Smith } 2874b9ad928SBarry Smith 288d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeSpecialSetAlpha_Composite(PC pc, PetscScalar alpha) 289d71ae5a4SJacob Faibussowitsch { 2904b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 2915fd66863SKarl Rupp 2924b9ad928SBarry Smith PetscFunctionBegin; 2934b9ad928SBarry Smith jac->alpha = alpha; 2943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2954b9ad928SBarry Smith } 2964b9ad928SBarry Smith 297d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeSetType_Composite(PC pc, PCCompositeType type) 298d71ae5a4SJacob Faibussowitsch { 299fad69fbaSJed Brown PC_Composite *jac = (PC_Composite *)pc->data; 300fad69fbaSJed Brown 3014b9ad928SBarry Smith PetscFunctionBegin; 3024b9ad928SBarry Smith if (type == PC_COMPOSITE_ADDITIVE) { 3034b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 3042533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 305421e10b8SBarry Smith } else if (type == PC_COMPOSITE_MULTIPLICATIVE || type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 3064b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Multiplicative; 3072533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Multiplicative; 3084b9ad928SBarry Smith } else if (type == PC_COMPOSITE_SPECIAL) { 3094b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Special; 3100298fd71SBarry Smith pc->ops->applytranspose = NULL; 311a7261c6bSprj- } else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown composite preconditioner type"); 312fad69fbaSJed Brown jac->type = type; 3133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3144b9ad928SBarry Smith } 3154b9ad928SBarry Smith 316d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeGetType_Composite(PC pc, PCCompositeType *type) 317d71ae5a4SJacob Faibussowitsch { 318c60c7ad4SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 319c60c7ad4SBarry Smith 320c60c7ad4SBarry Smith PetscFunctionBegin; 321c60c7ad4SBarry Smith *type = jac->type; 3223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 323c60c7ad4SBarry Smith } 324c60c7ad4SBarry Smith 325d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeAddPC_Composite(PC pc, PC subpc) 326d71ae5a4SJacob Faibussowitsch { 3274b9ad928SBarry Smith PC_Composite *jac; 3285a9f2f41SSatish Balay PC_CompositeLink next, ilink; 32979416396SBarry Smith PetscInt cnt = 0; 3302dcb1b2aSMatthew Knepley const char *prefix; 331d726e3a5SJed Brown char newprefix[20]; 3324b9ad928SBarry Smith 3334b9ad928SBarry Smith PetscFunctionBegin; 3344dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&ilink)); 3350a545947SLisandro Dalcin ilink->next = NULL; 3368aa07aa6SMatthew G. Knepley ilink->pc = subpc; 3374b9ad928SBarry Smith 3384b9ad928SBarry Smith jac = (PC_Composite *)pc->data; 3394b9ad928SBarry Smith next = jac->head; 3404b9ad928SBarry Smith if (!next) { 3415a9f2f41SSatish Balay jac->head = ilink; 3420298fd71SBarry Smith ilink->previous = NULL; 3434b9ad928SBarry Smith } else { 3444b9ad928SBarry Smith cnt++; 3454b9ad928SBarry Smith while (next->next) { 3464b9ad928SBarry Smith next = next->next; 3474b9ad928SBarry Smith cnt++; 3484b9ad928SBarry Smith } 3495a9f2f41SSatish Balay next->next = ilink; 350421e10b8SBarry Smith ilink->previous = next; 3514b9ad928SBarry Smith } 3529566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix)); 3539566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(subpc, prefix)); 3549566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(newprefix, 20, "sub_%d_", (int)cnt)); 3559566063dSJacob Faibussowitsch PetscCall(PCAppendOptionsPrefix(subpc, newprefix)); 3569566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)subpc)); 3573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3588aa07aa6SMatthew G. Knepley } 3598aa07aa6SMatthew G. Knepley 360d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeAddPCType_Composite(PC pc, PCType type) 361d71ae5a4SJacob Faibussowitsch { 3628aa07aa6SMatthew G. Knepley PC subpc; 3638aa07aa6SMatthew G. Knepley 3648aa07aa6SMatthew G. Knepley PetscFunctionBegin; 3659566063dSJacob Faibussowitsch PetscCall(PCCreate(PetscObjectComm((PetscObject)pc), &subpc)); 3669566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)subpc, (PetscObject)pc, 1)); 3679566063dSJacob Faibussowitsch PetscCall(PCCompositeAddPC_Composite(pc, subpc)); 3684b9ad928SBarry Smith /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */ 3699566063dSJacob Faibussowitsch PetscCall(PCSetType(subpc, type)); 3709566063dSJacob Faibussowitsch PetscCall(PCDestroy(&subpc)); 3713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3724b9ad928SBarry Smith } 3734b9ad928SBarry Smith 374d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeGetNumberPC_Composite(PC pc, PetscInt *n) 375d71ae5a4SJacob Faibussowitsch { 3768e6eba06SBarry Smith PC_Composite *jac; 3778e6eba06SBarry Smith PC_CompositeLink next; 3788e6eba06SBarry Smith 3798e6eba06SBarry Smith PetscFunctionBegin; 3808e6eba06SBarry Smith jac = (PC_Composite *)pc->data; 3818e6eba06SBarry Smith next = jac->head; 3828e6eba06SBarry Smith *n = 0; 3838e6eba06SBarry Smith while (next) { 3848e6eba06SBarry Smith next = next->next; 3858e6eba06SBarry Smith (*n)++; 3868e6eba06SBarry Smith } 3873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3888e6eba06SBarry Smith } 3898e6eba06SBarry Smith 390d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeGetPC_Composite(PC pc, PetscInt n, PC *subpc) 391d71ae5a4SJacob Faibussowitsch { 3924b9ad928SBarry Smith PC_Composite *jac; 3934b9ad928SBarry Smith PC_CompositeLink next; 39479416396SBarry Smith PetscInt i; 3954b9ad928SBarry Smith 3964b9ad928SBarry Smith PetscFunctionBegin; 3974b9ad928SBarry Smith jac = (PC_Composite *)pc->data; 3984b9ad928SBarry Smith next = jac->head; 3994b9ad928SBarry Smith for (i = 0; i < n; i++) { 40028b400f6SJacob Faibussowitsch PetscCheck(next->next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Not enough PCs in composite preconditioner"); 4014b9ad928SBarry Smith next = next->next; 4024b9ad928SBarry Smith } 4034b9ad928SBarry Smith *subpc = next->pc; 4043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4054b9ad928SBarry Smith } 4064b9ad928SBarry Smith 407f39d8e23SSatish Balay /*@ 4084b9ad928SBarry Smith PCCompositeSetType - Sets the type of composite preconditioner. 4094b9ad928SBarry Smith 410c3339decSBarry Smith Logically Collective 4114b9ad928SBarry Smith 412c60c7ad4SBarry Smith Input Parameters: 4132a6744ebSBarry Smith + pc - the preconditioner context 414f1580f4eSBarry 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 419f1580f4eSBarry Smith Level: advanced 4204b9ad928SBarry Smith 421f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL`, `PCCompositeType`, 422f1580f4eSBarry Smith `PCCompositeGetType()` 4234b9ad928SBarry Smith @*/ 424d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeSetType(PC pc, PCCompositeType type) 425d71ae5a4SJacob Faibussowitsch { 4264b9ad928SBarry Smith PetscFunctionBegin; 4270700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 428c5eb9154SBarry Smith PetscValidLogicalCollectiveEnum(pc, type, 2); 429cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeSetType_C", (PC, PCCompositeType), (pc, type)); 4303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4314b9ad928SBarry Smith } 4324b9ad928SBarry Smith 433c60c7ad4SBarry Smith /*@ 434721f67b5SBarry Smith PCCompositeGetType - Gets the type of composite preconditioner. 435c60c7ad4SBarry Smith 436c3339decSBarry Smith Logically Collective 437c60c7ad4SBarry Smith 438c60c7ad4SBarry Smith Input Parameter: 439c60c7ad4SBarry Smith . pc - the preconditioner context 440c60c7ad4SBarry Smith 441c60c7ad4SBarry Smith Output Parameter: 442f1580f4eSBarry Smith . type - `PC_COMPOSITE_ADDITIVE` (default), `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL` 443c60c7ad4SBarry Smith 444f1580f4eSBarry Smith Level: advanced 445c60c7ad4SBarry Smith 446f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL`, `PCCompositeType`, 447f1580f4eSBarry Smith `PCCompositeSetType()` 448c60c7ad4SBarry Smith @*/ 449d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeGetType(PC pc, PCCompositeType *type) 450d71ae5a4SJacob Faibussowitsch { 451c60c7ad4SBarry Smith PetscFunctionBegin; 452c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 453cac4c232SBarry Smith PetscUseMethod(pc, "PCCompositeGetType_C", (PC, PCCompositeType *), (pc, type)); 4543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 455c60c7ad4SBarry Smith } 456c60c7ad4SBarry Smith 457f39d8e23SSatish Balay /*@ 458f1580f4eSBarry Smith PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner, `PC_COMPOSITE_SPECIAL`, 4594b9ad928SBarry Smith for alphaI + R + S 4604b9ad928SBarry Smith 461c3339decSBarry Smith Logically Collective 4624b9ad928SBarry Smith 463d8d19677SJose E. Roman Input Parameters: 4644b9ad928SBarry Smith + pc - the preconditioner context 4654b9ad928SBarry Smith - alpha - scale on identity 4664b9ad928SBarry Smith 467*feefa0e1SJacob Faibussowitsch Level: developer 4684b9ad928SBarry Smith 469f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL`, `PCCompositeType`, 470f1580f4eSBarry Smith `PCCompositeSetType()`, `PCCompositeGetType()` 4714b9ad928SBarry Smith @*/ 472d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeSpecialSetAlpha(PC pc, PetscScalar alpha) 473d71ae5a4SJacob Faibussowitsch { 4744b9ad928SBarry Smith PetscFunctionBegin; 4750700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 476c5eb9154SBarry Smith PetscValidLogicalCollectiveScalar(pc, alpha, 2); 477cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeSpecialSetAlpha_C", (PC, PetscScalar), (pc, alpha)); 4783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4794b9ad928SBarry Smith } 4804b9ad928SBarry Smith 4814b9ad928SBarry Smith /*@C 482f1580f4eSBarry Smith PCCompositeAddPCType - Adds another `PC` of the given type to the composite `PC`. 4834b9ad928SBarry Smith 484c3339decSBarry Smith Collective 4854b9ad928SBarry Smith 4864b9ad928SBarry Smith Input Parameters: 4872a6744ebSBarry Smith + pc - the preconditioner context 4882a6744ebSBarry Smith - type - the type of the new preconditioner 4894b9ad928SBarry Smith 490f1580f4eSBarry Smith Level: intermediate 4914b9ad928SBarry Smith 492f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PCCompositeAddPC()`, `PCCompositeGetNumberPC()` 4934b9ad928SBarry Smith @*/ 494d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeAddPCType(PC pc, PCType type) 495d71ae5a4SJacob Faibussowitsch { 4964b9ad928SBarry Smith PetscFunctionBegin; 4970700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 498cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeAddPCType_C", (PC, PCType), (pc, type)); 4993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5008aa07aa6SMatthew G. Knepley } 5018aa07aa6SMatthew G. Knepley 5028aa07aa6SMatthew G. Knepley /*@ 503f1580f4eSBarry Smith PCCompositeAddPC - Adds another `PC` to the composite `PC`. 5048aa07aa6SMatthew G. Knepley 505c3339decSBarry Smith Collective 5068aa07aa6SMatthew G. Knepley 5078aa07aa6SMatthew G. Knepley Input Parameters: 5088aa07aa6SMatthew G. Knepley + pc - the preconditioner context 5098aa07aa6SMatthew G. Knepley - subpc - the new preconditioner 5108aa07aa6SMatthew G. Knepley 511f1580f4eSBarry Smith Level: intermediate 5128aa07aa6SMatthew G. Knepley 513f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PCCompositeAddPCType()`, `PCCompositeGetNumberPC()` 5148aa07aa6SMatthew G. Knepley @*/ 515d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeAddPC(PC pc, PC subpc) 516d71ae5a4SJacob Faibussowitsch { 5178aa07aa6SMatthew G. Knepley PetscFunctionBegin; 5188aa07aa6SMatthew G. Knepley PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5198aa07aa6SMatthew G. Knepley PetscValidHeaderSpecific(subpc, PC_CLASSID, 2); 520cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeAddPC_C", (PC, PC), (pc, subpc)); 5213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5224b9ad928SBarry Smith } 5234b9ad928SBarry Smith 5248e6eba06SBarry Smith /*@ 525f1580f4eSBarry Smith PCCompositeGetNumberPC - Gets the number of `PC` objects in the composite `PC`. 5268e6eba06SBarry Smith 5278e6eba06SBarry Smith Not Collective 5288e6eba06SBarry Smith 5298e6eba06SBarry Smith Input Parameter: 5308e6eba06SBarry Smith . pc - the preconditioner context 5318e6eba06SBarry Smith 5328e6eba06SBarry Smith Output Parameter: 5338e6eba06SBarry Smith . num - the number of sub pcs 5348e6eba06SBarry Smith 535*feefa0e1SJacob Faibussowitsch Level: developer 5368e6eba06SBarry Smith 537f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PCCompositeGetPC()`, `PCCompositeAddPC()`, `PCCompositeAddPCType()` 5388e6eba06SBarry Smith @*/ 539d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeGetNumberPC(PC pc, PetscInt *num) 540d71ae5a4SJacob Faibussowitsch { 5418e6eba06SBarry Smith PetscFunctionBegin; 5428e6eba06SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5438e6eba06SBarry Smith PetscValidIntPointer(num, 2); 544cac4c232SBarry Smith PetscUseMethod(pc, "PCCompositeGetNumberPC_C", (PC, PetscInt *), (pc, num)); 5453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5468e6eba06SBarry Smith } 5478e6eba06SBarry Smith 548f39d8e23SSatish Balay /*@ 549f1580f4eSBarry Smith PCCompositeGetPC - Gets one of the `PC` objects in the composite `PC`. 5504b9ad928SBarry Smith 5514b9ad928SBarry Smith Not Collective 5524b9ad928SBarry Smith 553d8d19677SJose E. Roman Input Parameters: 5542a6744ebSBarry Smith + pc - the preconditioner context 5552a6744ebSBarry Smith - n - the number of the pc requested 5564b9ad928SBarry Smith 557f1580f4eSBarry Smith Output Parameter: 5584b9ad928SBarry Smith . subpc - the PC requested 5594b9ad928SBarry Smith 560f1580f4eSBarry Smith Level: intermediate 5614b9ad928SBarry Smith 562f1580f4eSBarry Smith Note: 563f1580f4eSBarry Smith To use a different operator to construct one of the inner preconditioners first call `PCCompositeGetPC()`, then 564f1580f4eSBarry Smith call `PCSetOperators()` on that `PC`. 5652b1d202aSBarry Smith 566f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PCCompositeAddPCType()`, `PCCompositeGetNumberPC()`, `PCSetOperators()` 5674b9ad928SBarry Smith @*/ 568d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeGetPC(PC pc, PetscInt n, PC *subpc) 569d71ae5a4SJacob Faibussowitsch { 5704b9ad928SBarry Smith PetscFunctionBegin; 5710700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5724482741eSBarry Smith PetscValidPointer(subpc, 3); 573cac4c232SBarry Smith PetscUseMethod(pc, "PCCompositeGetPC_C", (PC, PetscInt, PC *), (pc, n, subpc)); 5743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5754b9ad928SBarry Smith } 5764b9ad928SBarry Smith 5774b9ad928SBarry Smith /*MC 5784b9ad928SBarry Smith PCCOMPOSITE - Build a preconditioner by composing together several preconditioners 5794b9ad928SBarry Smith 5804b9ad928SBarry Smith Options Database Keys: 5812eab2d5bSJungho Lee + -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type 582f1580f4eSBarry Smith . -pc_use_amat - activates `PCSetUseAmat()` 58351f519a2SBarry Smith - -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose 5844b9ad928SBarry Smith 5854b9ad928SBarry Smith Level: intermediate 5864b9ad928SBarry Smith 58795452b02SPatrick Sanan Notes: 588f1580f4eSBarry Smith To use a Krylov method inside the composite preconditioner, set the `PCType` of one or more 589f1580f4eSBarry Smith inner `PC`s to be `PCKSP`. Using a Krylov method inside another Krylov method can be dangerous (you get divergence or 590f1580f4eSBarry Smith the incorrect answer) unless you use `KSPFGMRES` as the outer Krylov method 591f1580f4eSBarry Smith 592f1580f4eSBarry Smith To use a different operator to construct one of the inner preconditioners first call `PCCompositeGetPC()`, then 593f1580f4eSBarry Smith call `PCSetOperators()` on that `PC`. 5944b9ad928SBarry Smith 595db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, 596db781477SPatrick Sanan `PCSHELL`, `PCKSP`, `PCCompositeSetType()`, `PCCompositeSpecialSetAlpha()`, `PCCompositeAddPCType()`, 597f1580f4eSBarry Smith `PCCompositeGetPC()`, `PCSetUseAmat()`, `PCCompositeAddPC()`, `PCCompositeGetNumberPC()` 5984b9ad928SBarry Smith M*/ 5994b9ad928SBarry Smith 600d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc) 601d71ae5a4SJacob Faibussowitsch { 6024b9ad928SBarry Smith PC_Composite *jac; 6034b9ad928SBarry Smith 6044b9ad928SBarry Smith PetscFunctionBegin; 6054dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&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; 6104f853519SStefano Zampini pc->ops->setuponblocks = PCSetUpOnBlocks_Composite; 61169d2c0f9SBarry Smith pc->ops->reset = PCReset_Composite; 6124b9ad928SBarry Smith pc->ops->destroy = PCDestroy_Composite; 6134b9ad928SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Composite; 6144b9ad928SBarry Smith pc->ops->view = PCView_Composite; 6150a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 6164b9ad928SBarry Smith 6174b9ad928SBarry Smith pc->data = (void *)jac; 6184b9ad928SBarry Smith jac->type = PC_COMPOSITE_ADDITIVE; 6190a545947SLisandro Dalcin jac->work1 = NULL; 6200a545947SLisandro Dalcin jac->work2 = NULL; 6210a545947SLisandro Dalcin jac->head = NULL; 6224b9ad928SBarry Smith 6239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSetType_C", PCCompositeSetType_Composite)); 6249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetType_C", PCCompositeGetType_Composite)); 6259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPCType_C", PCCompositeAddPCType_Composite)); 6269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPC_C", PCCompositeAddPC_Composite)); 6279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetNumberPC_C", PCCompositeGetNumberPC_Composite)); 6289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetPC_C", PCCompositeGetPC_Composite)); 6299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSpecialSetAlpha_C", PCCompositeSpecialSetAlpha_Composite)); 6303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6314b9ad928SBarry Smith } 632