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 239371c9d4SSatish Balay static PetscErrorCode PCApply_Composite_Multiplicative(PC pc, Vec x, Vec y) { 244b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 254b9ad928SBarry Smith PC_CompositeLink next = jac->head; 264b9ad928SBarry Smith Mat mat = pc->pmat; 274b9ad928SBarry Smith 284b9ad928SBarry Smith PetscFunctionBegin; 29450d59ebSPatrick Farrell 3028b400f6SJacob Faibussowitsch PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 31450d59ebSPatrick Farrell 32450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 33450d59ebSPatrick Farrell while (next) { 349566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->pc, pc->reusepreconditioner)); 35450d59ebSPatrick Farrell next = next->next; 36450d59ebSPatrick Farrell } 37450d59ebSPatrick Farrell next = jac->head; 38450d59ebSPatrick Farrell 394b9ad928SBarry Smith if (next->next && !jac->work2) { /* allocate second work vector */ 409566063dSJacob Faibussowitsch PetscCall(VecDuplicate(jac->work1, &jac->work2)); 414b9ad928SBarry Smith } 4249517cdeSBarry Smith if (pc->useAmat) mat = pc->mat; 439566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, x, y)); /* y <- B x */ 444b9ad928SBarry Smith while (next->next) { 454b9ad928SBarry Smith next = next->next; 469566063dSJacob Faibussowitsch PetscCall(MatMult(mat, y, jac->work1)); /* work1 <- A y */ 479566063dSJacob Faibussowitsch PetscCall(VecWAXPY(jac->work2, -1.0, jac->work1, x)); /* work2 <- x - work1 */ 489566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, jac->work2, jac->work1)); /* work1 <- C work2 */ 499566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); /* y <- y + work1 = B x + C (x - A B x) = (B + C (1 - A B)) x */ 504b9ad928SBarry Smith } 51421e10b8SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 52421e10b8SBarry Smith while (next->previous) { 53421e10b8SBarry Smith next = next->previous; 549566063dSJacob Faibussowitsch PetscCall(MatMult(mat, y, jac->work1)); 559566063dSJacob Faibussowitsch PetscCall(VecWAXPY(jac->work2, -1.0, jac->work1, x)); 569566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, jac->work2, jac->work1)); 579566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); 58421e10b8SBarry Smith } 59421e10b8SBarry Smith } 604b9ad928SBarry Smith PetscFunctionReturn(0); 614b9ad928SBarry Smith } 624b9ad928SBarry Smith 639371c9d4SSatish Balay static PetscErrorCode PCApplyTranspose_Composite_Multiplicative(PC pc, Vec x, Vec y) { 642533e041SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 652533e041SBarry Smith PC_CompositeLink next = jac->head; 662533e041SBarry Smith Mat mat = pc->pmat; 672533e041SBarry Smith 682533e041SBarry Smith PetscFunctionBegin; 6928b400f6SJacob Faibussowitsch PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 702533e041SBarry Smith if (next->next && !jac->work2) { /* allocate second work vector */ 719566063dSJacob Faibussowitsch PetscCall(VecDuplicate(jac->work1, &jac->work2)); 722533e041SBarry Smith } 7349517cdeSBarry Smith if (pc->useAmat) mat = pc->mat; 742533e041SBarry Smith /* locate last PC */ 75ad540459SPierre Jolivet while (next->next) next = next->next; 769566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc, x, y)); 772533e041SBarry Smith while (next->previous) { 782533e041SBarry Smith next = next->previous; 799566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(mat, y, jac->work1)); 809566063dSJacob Faibussowitsch PetscCall(VecWAXPY(jac->work2, -1.0, jac->work1, x)); 819566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc, jac->work2, jac->work1)); 829566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); 832533e041SBarry Smith } 842533e041SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 852533e041SBarry Smith next = jac->head; 862533e041SBarry Smith while (next->next) { 872533e041SBarry Smith next = next->next; 889566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(mat, y, jac->work1)); 899566063dSJacob Faibussowitsch PetscCall(VecWAXPY(jac->work2, -1.0, jac->work1, x)); 909566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc, jac->work2, jac->work1)); 919566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); 922533e041SBarry Smith } 932533e041SBarry Smith } 942533e041SBarry Smith PetscFunctionReturn(0); 952533e041SBarry Smith } 962533e041SBarry Smith 974b9ad928SBarry Smith /* 984b9ad928SBarry Smith This is very special for a matrix of the form alpha I + R + S 994b9ad928SBarry Smith where first preconditioner is built from alpha I + S and second from 1004b9ad928SBarry Smith alpha I + R 1014b9ad928SBarry Smith */ 1029371c9d4SSatish Balay static PetscErrorCode PCApply_Composite_Special(PC pc, Vec x, Vec y) { 1034b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1044b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1054b9ad928SBarry Smith 1064b9ad928SBarry Smith PetscFunctionBegin; 10728b400f6SJacob Faibussowitsch PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 1087827d75bSBarry Smith PetscCheck(next->next && !next->next->next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Special composite preconditioners requires exactly two PCs"); 1094b9ad928SBarry Smith 110450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 1119566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->pc, pc->reusepreconditioner)); 1129566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->next->pc, pc->reusepreconditioner)); 113450d59ebSPatrick Farrell 1149566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, x, jac->work1)); 1159566063dSJacob Faibussowitsch PetscCall(PCApply(next->next->pc, jac->work1, y)); 1164b9ad928SBarry Smith PetscFunctionReturn(0); 1174b9ad928SBarry Smith } 1184b9ad928SBarry Smith 1199371c9d4SSatish Balay static PetscErrorCode PCApply_Composite_Additive(PC pc, Vec x, Vec y) { 1204b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1214b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1224b9ad928SBarry Smith 1234b9ad928SBarry Smith PetscFunctionBegin; 12428b400f6SJacob Faibussowitsch PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 125450d59ebSPatrick Farrell 126450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 127450d59ebSPatrick Farrell while (next) { 1289566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->pc, pc->reusepreconditioner)); 129450d59ebSPatrick Farrell next = next->next; 130450d59ebSPatrick Farrell } 131450d59ebSPatrick Farrell next = jac->head; 132450d59ebSPatrick Farrell 1339566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, x, y)); 1344b9ad928SBarry Smith while (next->next) { 1354b9ad928SBarry Smith next = next->next; 1369566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, x, jac->work1)); 1379566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); 1384b9ad928SBarry Smith } 1394b9ad928SBarry Smith PetscFunctionReturn(0); 1404b9ad928SBarry Smith } 1414b9ad928SBarry Smith 1429371c9d4SSatish Balay static PetscErrorCode PCApplyTranspose_Composite_Additive(PC pc, Vec x, Vec y) { 1432533e041SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1442533e041SBarry Smith PC_CompositeLink next = jac->head; 1452533e041SBarry Smith 1462533e041SBarry Smith PetscFunctionBegin; 14728b400f6SJacob Faibussowitsch PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 1489566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc, x, y)); 1492533e041SBarry Smith while (next->next) { 1502533e041SBarry Smith next = next->next; 1519566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc, x, jac->work1)); 1529566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); 1532533e041SBarry Smith } 1542533e041SBarry Smith PetscFunctionReturn(0); 1552533e041SBarry Smith } 1562533e041SBarry Smith 1579371c9d4SSatish Balay static PetscErrorCode PCSetUp_Composite(PC pc) { 1584b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1594b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1605a78d018SMatthew G. Knepley DM dm; 1614b9ad928SBarry Smith 1624b9ad928SBarry Smith PetscFunctionBegin; 16348a46eb9SPierre Jolivet if (!jac->work1) PetscCall(MatCreateVecs(pc->pmat, &jac->work1, NULL)); 1649566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 1654b9ad928SBarry Smith while (next) { 16648a46eb9SPierre Jolivet if (!next->pc->dm) PetscCall(PCSetDM(next->pc, dm)); 16748a46eb9SPierre Jolivet if (!next->pc->mat) PetscCall(PCSetOperators(next->pc, pc->mat, pc->pmat)); 1684b9ad928SBarry Smith next = next->next; 1694b9ad928SBarry Smith } 1704b9ad928SBarry Smith PetscFunctionReturn(0); 1714b9ad928SBarry Smith } 1724b9ad928SBarry Smith 1739371c9d4SSatish Balay static PetscErrorCode PCReset_Composite(PC pc) { 17469d2c0f9SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1755f48b12bSBarry Smith PC_CompositeLink next = jac->head; 17669d2c0f9SBarry Smith 17769d2c0f9SBarry Smith PetscFunctionBegin; 17869d2c0f9SBarry Smith while (next) { 1799566063dSJacob Faibussowitsch PetscCall(PCReset(next->pc)); 18069d2c0f9SBarry Smith next = next->next; 18169d2c0f9SBarry Smith } 1829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&jac->work1)); 1839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&jac->work2)); 18469d2c0f9SBarry Smith PetscFunctionReturn(0); 18569d2c0f9SBarry Smith } 18669d2c0f9SBarry Smith 1879371c9d4SSatish Balay static PetscErrorCode PCDestroy_Composite(PC pc) { 1884b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 189724c2c99SHong Zhang PC_CompositeLink next = jac->head, next_tmp; 1904b9ad928SBarry Smith 1914b9ad928SBarry Smith PetscFunctionBegin; 1929566063dSJacob Faibussowitsch PetscCall(PCReset_Composite(pc)); 1934b9ad928SBarry Smith while (next) { 1949566063dSJacob Faibussowitsch PetscCall(PCDestroy(&next->pc)); 195724c2c99SHong Zhang next_tmp = next; 1964b9ad928SBarry Smith next = next->next; 1979566063dSJacob Faibussowitsch PetscCall(PetscFree(next_tmp)); 1984b9ad928SBarry Smith } 1992e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSetType_C", NULL)); 2002e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetType_C", NULL)); 2012e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPCType_C", NULL)); 2022e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPC_C", NULL)); 2032e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetNumberPC_C", NULL)); 2042e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetPC_C", NULL)); 2052e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSpecialSetAlpha_C", NULL)); 2069566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 2074b9ad928SBarry Smith PetscFunctionReturn(0); 2084b9ad928SBarry Smith } 2094b9ad928SBarry Smith 2109371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_Composite(PC pc, PetscOptionItems *PetscOptionsObject) { 2114b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 2129dcbbd2bSBarry Smith PetscInt nmax = 8, i; 2134b9ad928SBarry Smith PC_CompositeLink next; 214e5999256SBarry Smith char *pcs[8]; 215ace3abfcSBarry Smith PetscBool flg; 2164b9ad928SBarry Smith 2174b9ad928SBarry Smith PetscFunctionBegin; 218d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Composite preconditioner options"); 2199566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-pc_composite_type", "Type of composition", "PCCompositeSetType", PCCompositeTypes, (PetscEnum)jac->type, (PetscEnum *)&jac->type, &flg)); 2201baa6e33SBarry Smith if (flg) PetscCall(PCCompositeSetType(pc, jac->type)); 2219566063dSJacob Faibussowitsch PetscCall(PetscOptionsStringArray("-pc_composite_pcs", "List of composite solvers", "PCCompositeAddPCType", pcs, &nmax, &flg)); 2224b9ad928SBarry Smith if (flg) { 2234b9ad928SBarry Smith for (i = 0; i < nmax; i++) { 2249566063dSJacob Faibussowitsch PetscCall(PCCompositeAddPCType(pc, pcs[i])); 2259566063dSJacob Faibussowitsch PetscCall(PetscFree(pcs[i])); /* deallocate string pcs[i], which is allocated in PetscOptionsStringArray() */ 2264b9ad928SBarry Smith } 2274b9ad928SBarry Smith } 228d0609cedSBarry Smith PetscOptionsHeadEnd(); 2294b9ad928SBarry Smith 2304b9ad928SBarry Smith next = jac->head; 2314b9ad928SBarry Smith while (next) { 2329566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(next->pc)); 2334b9ad928SBarry Smith next = next->next; 2344b9ad928SBarry Smith } 2354b9ad928SBarry Smith PetscFunctionReturn(0); 2364b9ad928SBarry Smith } 2374b9ad928SBarry Smith 2389371c9d4SSatish Balay static PetscErrorCode PCView_Composite(PC pc, PetscViewer viewer) { 2394b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 2404b9ad928SBarry Smith PC_CompositeLink next = jac->head; 241ace3abfcSBarry Smith PetscBool iascii; 2424b9ad928SBarry Smith 2434b9ad928SBarry Smith PetscFunctionBegin; 2449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 24532077d6dSBarry Smith if (iascii) { 2469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Composite PC type - %s\n", PCCompositeTypes[jac->type])); 2479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "PCs on composite preconditioner follow\n")); 2489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "---------------------------------\n")); 2494b9ad928SBarry Smith } 2501baa6e33SBarry Smith if (iascii) PetscCall(PetscViewerASCIIPushTab(viewer)); 2514b9ad928SBarry Smith while (next) { 2529566063dSJacob Faibussowitsch PetscCall(PCView(next->pc, viewer)); 2534b9ad928SBarry Smith next = next->next; 2544b9ad928SBarry Smith } 25532077d6dSBarry Smith if (iascii) { 2569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 2579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "---------------------------------\n")); 2584b9ad928SBarry Smith } 2594b9ad928SBarry Smith PetscFunctionReturn(0); 2604b9ad928SBarry Smith } 2614b9ad928SBarry Smith 2629371c9d4SSatish Balay static PetscErrorCode PCCompositeSpecialSetAlpha_Composite(PC pc, PetscScalar alpha) { 2634b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 2645fd66863SKarl Rupp 2654b9ad928SBarry Smith PetscFunctionBegin; 2664b9ad928SBarry Smith jac->alpha = alpha; 2674b9ad928SBarry Smith PetscFunctionReturn(0); 2684b9ad928SBarry Smith } 2694b9ad928SBarry Smith 2709371c9d4SSatish Balay static PetscErrorCode PCCompositeSetType_Composite(PC pc, PCCompositeType type) { 271fad69fbaSJed Brown PC_Composite *jac = (PC_Composite *)pc->data; 272fad69fbaSJed Brown 2734b9ad928SBarry Smith PetscFunctionBegin; 2744b9ad928SBarry Smith if (type == PC_COMPOSITE_ADDITIVE) { 2754b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 2762533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 277421e10b8SBarry Smith } else if (type == PC_COMPOSITE_MULTIPLICATIVE || type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 2784b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Multiplicative; 2792533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Multiplicative; 2804b9ad928SBarry Smith } else if (type == PC_COMPOSITE_SPECIAL) { 2814b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Special; 2820298fd71SBarry Smith pc->ops->applytranspose = NULL; 283a7261c6bSprj- } else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown composite preconditioner type"); 284fad69fbaSJed Brown jac->type = type; 2854b9ad928SBarry Smith PetscFunctionReturn(0); 2864b9ad928SBarry Smith } 2874b9ad928SBarry Smith 2889371c9d4SSatish Balay static PetscErrorCode PCCompositeGetType_Composite(PC pc, PCCompositeType *type) { 289c60c7ad4SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 290c60c7ad4SBarry Smith 291c60c7ad4SBarry Smith PetscFunctionBegin; 292c60c7ad4SBarry Smith *type = jac->type; 293c60c7ad4SBarry Smith PetscFunctionReturn(0); 294c60c7ad4SBarry Smith } 295c60c7ad4SBarry Smith 2969371c9d4SSatish Balay static PetscErrorCode PCCompositeAddPC_Composite(PC pc, PC subpc) { 2974b9ad928SBarry Smith PC_Composite *jac; 2985a9f2f41SSatish Balay PC_CompositeLink next, ilink; 29979416396SBarry Smith PetscInt cnt = 0; 3002dcb1b2aSMatthew Knepley const char *prefix; 301d726e3a5SJed Brown char newprefix[20]; 3024b9ad928SBarry Smith 3034b9ad928SBarry Smith PetscFunctionBegin; 3049566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc, &ilink)); 3050a545947SLisandro Dalcin ilink->next = NULL; 3068aa07aa6SMatthew G. Knepley ilink->pc = subpc; 3074b9ad928SBarry Smith 3084b9ad928SBarry Smith jac = (PC_Composite *)pc->data; 3094b9ad928SBarry Smith next = jac->head; 3104b9ad928SBarry Smith if (!next) { 3115a9f2f41SSatish Balay jac->head = ilink; 3120298fd71SBarry Smith ilink->previous = NULL; 3134b9ad928SBarry Smith } else { 3144b9ad928SBarry Smith cnt++; 3154b9ad928SBarry Smith while (next->next) { 3164b9ad928SBarry Smith next = next->next; 3174b9ad928SBarry Smith cnt++; 3184b9ad928SBarry Smith } 3195a9f2f41SSatish Balay next->next = ilink; 320421e10b8SBarry Smith ilink->previous = next; 3214b9ad928SBarry Smith } 3229566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix)); 3239566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(subpc, prefix)); 3249566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(newprefix, 20, "sub_%d_", (int)cnt)); 3259566063dSJacob Faibussowitsch PetscCall(PCAppendOptionsPrefix(subpc, newprefix)); 3269566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)subpc)); 3278aa07aa6SMatthew G. Knepley PetscFunctionReturn(0); 3288aa07aa6SMatthew G. Knepley } 3298aa07aa6SMatthew G. Knepley 3309371c9d4SSatish Balay static PetscErrorCode PCCompositeAddPCType_Composite(PC pc, PCType type) { 3318aa07aa6SMatthew G. Knepley PC subpc; 3328aa07aa6SMatthew G. Knepley 3338aa07aa6SMatthew G. Knepley PetscFunctionBegin; 3349566063dSJacob Faibussowitsch PetscCall(PCCreate(PetscObjectComm((PetscObject)pc), &subpc)); 3359566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)subpc, (PetscObject)pc, 1)); 3369566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)subpc)); 3379566063dSJacob Faibussowitsch PetscCall(PCCompositeAddPC_Composite(pc, subpc)); 3384b9ad928SBarry Smith /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */ 3399566063dSJacob Faibussowitsch PetscCall(PCSetType(subpc, type)); 3409566063dSJacob Faibussowitsch PetscCall(PCDestroy(&subpc)); 3414b9ad928SBarry Smith PetscFunctionReturn(0); 3424b9ad928SBarry Smith } 3434b9ad928SBarry Smith 3449371c9d4SSatish Balay static PetscErrorCode PCCompositeGetNumberPC_Composite(PC pc, PetscInt *n) { 3458e6eba06SBarry Smith PC_Composite *jac; 3468e6eba06SBarry Smith PC_CompositeLink next; 3478e6eba06SBarry Smith 3488e6eba06SBarry Smith PetscFunctionBegin; 3498e6eba06SBarry Smith jac = (PC_Composite *)pc->data; 3508e6eba06SBarry Smith next = jac->head; 3518e6eba06SBarry Smith *n = 0; 3528e6eba06SBarry Smith while (next) { 3538e6eba06SBarry Smith next = next->next; 3548e6eba06SBarry Smith (*n)++; 3558e6eba06SBarry Smith } 3568e6eba06SBarry Smith PetscFunctionReturn(0); 3578e6eba06SBarry Smith } 3588e6eba06SBarry Smith 3599371c9d4SSatish Balay static PetscErrorCode PCCompositeGetPC_Composite(PC pc, PetscInt n, PC *subpc) { 3604b9ad928SBarry Smith PC_Composite *jac; 3614b9ad928SBarry Smith PC_CompositeLink next; 36279416396SBarry Smith PetscInt i; 3634b9ad928SBarry Smith 3644b9ad928SBarry Smith PetscFunctionBegin; 3654b9ad928SBarry Smith jac = (PC_Composite *)pc->data; 3664b9ad928SBarry Smith next = jac->head; 3674b9ad928SBarry Smith for (i = 0; i < n; i++) { 36828b400f6SJacob Faibussowitsch PetscCheck(next->next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Not enough PCs in composite preconditioner"); 3694b9ad928SBarry Smith next = next->next; 3704b9ad928SBarry Smith } 3714b9ad928SBarry Smith *subpc = next->pc; 3724b9ad928SBarry Smith PetscFunctionReturn(0); 3734b9ad928SBarry Smith } 3744b9ad928SBarry Smith 375f39d8e23SSatish Balay /*@ 3764b9ad928SBarry Smith PCCompositeSetType - Sets the type of composite preconditioner. 3774b9ad928SBarry Smith 378*f1580f4eSBarry Smith Logically Collective on pc 3794b9ad928SBarry Smith 380c60c7ad4SBarry Smith Input Parameters: 3812a6744ebSBarry Smith + pc - the preconditioner context 382*f1580f4eSBarry Smith - type - `PC_COMPOSITE_ADDITIVE` (default), `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL` 3834b9ad928SBarry Smith 3844b9ad928SBarry Smith Options Database Key: 3854b9ad928SBarry Smith . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 3864b9ad928SBarry Smith 387*f1580f4eSBarry Smith Level: advanced 3884b9ad928SBarry Smith 389*f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL`, `PCCompositeType`, 390*f1580f4eSBarry Smith `PCCompositeGetType()` 3914b9ad928SBarry Smith @*/ 3929371c9d4SSatish Balay PetscErrorCode PCCompositeSetType(PC pc, PCCompositeType type) { 3934b9ad928SBarry Smith PetscFunctionBegin; 3940700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 395c5eb9154SBarry Smith PetscValidLogicalCollectiveEnum(pc, type, 2); 396cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeSetType_C", (PC, PCCompositeType), (pc, type)); 3974b9ad928SBarry Smith PetscFunctionReturn(0); 3984b9ad928SBarry Smith } 3994b9ad928SBarry Smith 400c60c7ad4SBarry Smith /*@ 401721f67b5SBarry Smith PCCompositeGetType - Gets the type of composite preconditioner. 402c60c7ad4SBarry Smith 403*f1580f4eSBarry Smith Logically Collective on pc 404c60c7ad4SBarry Smith 405c60c7ad4SBarry Smith Input Parameter: 406c60c7ad4SBarry Smith . pc - the preconditioner context 407c60c7ad4SBarry Smith 408c60c7ad4SBarry Smith Output Parameter: 409*f1580f4eSBarry Smith . type - `PC_COMPOSITE_ADDITIVE` (default), `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL` 410c60c7ad4SBarry Smith 411*f1580f4eSBarry Smith Level: advanced 412c60c7ad4SBarry Smith 413*f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL`, `PCCompositeType`, 414*f1580f4eSBarry Smith `PCCompositeSetType()` 415c60c7ad4SBarry Smith @*/ 4169371c9d4SSatish Balay PetscErrorCode PCCompositeGetType(PC pc, PCCompositeType *type) { 417c60c7ad4SBarry Smith PetscFunctionBegin; 418c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 419cac4c232SBarry Smith PetscUseMethod(pc, "PCCompositeGetType_C", (PC, PCCompositeType *), (pc, type)); 420c60c7ad4SBarry Smith PetscFunctionReturn(0); 421c60c7ad4SBarry Smith } 422c60c7ad4SBarry Smith 423f39d8e23SSatish Balay /*@ 424*f1580f4eSBarry Smith PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner, `PC_COMPOSITE_SPECIAL`, 4254b9ad928SBarry Smith for alphaI + R + S 4264b9ad928SBarry Smith 427*f1580f4eSBarry Smith Logically Collective on pc 4284b9ad928SBarry Smith 429d8d19677SJose E. Roman Input Parameters: 4304b9ad928SBarry Smith + pc - the preconditioner context 4314b9ad928SBarry Smith - alpha - scale on identity 4324b9ad928SBarry Smith 4334b9ad928SBarry Smith Level: Developer 4344b9ad928SBarry Smith 435*f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL`, `PCCompositeType`, 436*f1580f4eSBarry Smith `PCCompositeSetType()`, `PCCompositeGetType()` 4374b9ad928SBarry Smith @*/ 4389371c9d4SSatish Balay PetscErrorCode PCCompositeSpecialSetAlpha(PC pc, PetscScalar alpha) { 4394b9ad928SBarry Smith PetscFunctionBegin; 4400700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 441c5eb9154SBarry Smith PetscValidLogicalCollectiveScalar(pc, alpha, 2); 442cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeSpecialSetAlpha_C", (PC, PetscScalar), (pc, alpha)); 4434b9ad928SBarry Smith PetscFunctionReturn(0); 4444b9ad928SBarry Smith } 4454b9ad928SBarry Smith 4464b9ad928SBarry Smith /*@C 447*f1580f4eSBarry Smith PCCompositeAddPCType - Adds another `PC` of the given type to the composite `PC`. 4484b9ad928SBarry Smith 449*f1580f4eSBarry Smith Collective on pc 4504b9ad928SBarry Smith 4514b9ad928SBarry Smith Input Parameters: 4522a6744ebSBarry Smith + pc - the preconditioner context 4532a6744ebSBarry Smith - type - the type of the new preconditioner 4544b9ad928SBarry Smith 455*f1580f4eSBarry Smith Level: intermediate 4564b9ad928SBarry Smith 457*f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PCCompositeAddPC()`, `PCCompositeGetNumberPC()` 4584b9ad928SBarry Smith @*/ 4599371c9d4SSatish Balay PetscErrorCode PCCompositeAddPCType(PC pc, PCType type) { 4604b9ad928SBarry Smith PetscFunctionBegin; 4610700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 462cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeAddPCType_C", (PC, PCType), (pc, type)); 4638aa07aa6SMatthew G. Knepley PetscFunctionReturn(0); 4648aa07aa6SMatthew G. Knepley } 4658aa07aa6SMatthew G. Knepley 4668aa07aa6SMatthew G. Knepley /*@ 467*f1580f4eSBarry Smith PCCompositeAddPC - Adds another `PC` to the composite `PC`. 4688aa07aa6SMatthew G. Knepley 469*f1580f4eSBarry Smith Collective on pc 4708aa07aa6SMatthew G. Knepley 4718aa07aa6SMatthew G. Knepley Input Parameters: 4728aa07aa6SMatthew G. Knepley + pc - the preconditioner context 4738aa07aa6SMatthew G. Knepley - subpc - the new preconditioner 4748aa07aa6SMatthew G. Knepley 475*f1580f4eSBarry Smith Level: intermediate 4768aa07aa6SMatthew G. Knepley 477*f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PCCompositeAddPCType()`, `PCCompositeGetNumberPC()` 4788aa07aa6SMatthew G. Knepley @*/ 4799371c9d4SSatish Balay PetscErrorCode PCCompositeAddPC(PC pc, PC subpc) { 4808aa07aa6SMatthew G. Knepley PetscFunctionBegin; 4818aa07aa6SMatthew G. Knepley PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 4828aa07aa6SMatthew G. Knepley PetscValidHeaderSpecific(subpc, PC_CLASSID, 2); 483cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeAddPC_C", (PC, PC), (pc, subpc)); 4844b9ad928SBarry Smith PetscFunctionReturn(0); 4854b9ad928SBarry Smith } 4864b9ad928SBarry Smith 4878e6eba06SBarry Smith /*@ 488*f1580f4eSBarry Smith PCCompositeGetNumberPC - Gets the number of `PC` objects in the composite `PC`. 4898e6eba06SBarry Smith 4908e6eba06SBarry Smith Not Collective 4918e6eba06SBarry Smith 4928e6eba06SBarry Smith Input Parameter: 4938e6eba06SBarry Smith . pc - the preconditioner context 4948e6eba06SBarry Smith 4958e6eba06SBarry Smith Output Parameter: 4968e6eba06SBarry Smith . num - the number of sub pcs 4978e6eba06SBarry Smith 4988e6eba06SBarry Smith Level: Developer 4998e6eba06SBarry Smith 500*f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PCCompositeGetPC()`, `PCCompositeAddPC()`, `PCCompositeAddPCType()` 5018e6eba06SBarry Smith @*/ 5029371c9d4SSatish Balay PetscErrorCode PCCompositeGetNumberPC(PC pc, PetscInt *num) { 5038e6eba06SBarry Smith PetscFunctionBegin; 5048e6eba06SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5058e6eba06SBarry Smith PetscValidIntPointer(num, 2); 506cac4c232SBarry Smith PetscUseMethod(pc, "PCCompositeGetNumberPC_C", (PC, PetscInt *), (pc, num)); 5078e6eba06SBarry Smith PetscFunctionReturn(0); 5088e6eba06SBarry Smith } 5098e6eba06SBarry Smith 510f39d8e23SSatish Balay /*@ 511*f1580f4eSBarry Smith PCCompositeGetPC - Gets one of the `PC` objects in the composite `PC`. 5124b9ad928SBarry Smith 5134b9ad928SBarry Smith Not Collective 5144b9ad928SBarry Smith 515d8d19677SJose E. Roman Input Parameters: 5162a6744ebSBarry Smith + pc - the preconditioner context 5172a6744ebSBarry Smith - n - the number of the pc requested 5184b9ad928SBarry Smith 519*f1580f4eSBarry Smith Output Parameter: 5204b9ad928SBarry Smith . subpc - the PC requested 5214b9ad928SBarry Smith 522*f1580f4eSBarry Smith Level: intermediate 5234b9ad928SBarry Smith 524*f1580f4eSBarry Smith Note: 525*f1580f4eSBarry Smith To use a different operator to construct one of the inner preconditioners first call `PCCompositeGetPC()`, then 526*f1580f4eSBarry Smith call `PCSetOperators()` on that `PC`. 5272b1d202aSBarry Smith 528*f1580f4eSBarry Smith .seealso: `PCCOMPOSITE`, `PCCompositeAddPCType()`, `PCCompositeGetNumberPC()`, `PCSetOperators()` 5294b9ad928SBarry Smith @*/ 5309371c9d4SSatish Balay PetscErrorCode PCCompositeGetPC(PC pc, PetscInt n, PC *subpc) { 5314b9ad928SBarry Smith PetscFunctionBegin; 5320700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5334482741eSBarry Smith PetscValidPointer(subpc, 3); 534cac4c232SBarry Smith PetscUseMethod(pc, "PCCompositeGetPC_C", (PC, PetscInt, PC *), (pc, n, subpc)); 5354b9ad928SBarry Smith PetscFunctionReturn(0); 5364b9ad928SBarry Smith } 5374b9ad928SBarry Smith 5384b9ad928SBarry Smith /*MC 5394b9ad928SBarry Smith PCCOMPOSITE - Build a preconditioner by composing together several preconditioners 5404b9ad928SBarry Smith 5414b9ad928SBarry Smith Options Database Keys: 5422eab2d5bSJungho Lee + -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type 543*f1580f4eSBarry Smith . -pc_use_amat - activates `PCSetUseAmat()` 54451f519a2SBarry Smith - -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose 5454b9ad928SBarry Smith 5464b9ad928SBarry Smith Level: intermediate 5474b9ad928SBarry Smith 54895452b02SPatrick Sanan Notes: 549*f1580f4eSBarry Smith To use a Krylov method inside the composite preconditioner, set the `PCType` of one or more 550*f1580f4eSBarry Smith inner `PC`s to be `PCKSP`. Using a Krylov method inside another Krylov method can be dangerous (you get divergence or 551*f1580f4eSBarry Smith the incorrect answer) unless you use `KSPFGMRES` as the outer Krylov method 552*f1580f4eSBarry Smith 553*f1580f4eSBarry Smith To use a different operator to construct one of the inner preconditioners first call `PCCompositeGetPC()`, then 554*f1580f4eSBarry Smith call `PCSetOperators()` on that `PC`. 5554b9ad928SBarry Smith 556db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, 557db781477SPatrick Sanan `PCSHELL`, `PCKSP`, `PCCompositeSetType()`, `PCCompositeSpecialSetAlpha()`, `PCCompositeAddPCType()`, 558*f1580f4eSBarry Smith `PCCompositeGetPC()`, `PCSetUseAmat()`, `PCCompositeAddPC()`, `PCCompositeGetNumberPC()` 5594b9ad928SBarry Smith M*/ 5604b9ad928SBarry Smith 5619371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc) { 5624b9ad928SBarry Smith PC_Composite *jac; 5634b9ad928SBarry Smith 5644b9ad928SBarry Smith PetscFunctionBegin; 5659566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc, &jac)); 5662fa5cd67SKarl Rupp 5674b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 5682533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 5694b9ad928SBarry Smith pc->ops->setup = PCSetUp_Composite; 57069d2c0f9SBarry Smith pc->ops->reset = PCReset_Composite; 5714b9ad928SBarry Smith pc->ops->destroy = PCDestroy_Composite; 5724b9ad928SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Composite; 5734b9ad928SBarry Smith pc->ops->view = PCView_Composite; 5740a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 5754b9ad928SBarry Smith 5764b9ad928SBarry Smith pc->data = (void *)jac; 5774b9ad928SBarry Smith jac->type = PC_COMPOSITE_ADDITIVE; 5780a545947SLisandro Dalcin jac->work1 = NULL; 5790a545947SLisandro Dalcin jac->work2 = NULL; 5800a545947SLisandro Dalcin jac->head = NULL; 5814b9ad928SBarry Smith 5829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSetType_C", PCCompositeSetType_Composite)); 5839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetType_C", PCCompositeGetType_Composite)); 5849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPCType_C", PCCompositeAddPCType_Composite)); 5859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPC_C", PCCompositeAddPC_Composite)); 5869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetNumberPC_C", PCCompositeGetNumberPC_Composite)); 5879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetPC_C", PCCompositeGetPC_Composite)); 5889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSpecialSetAlpha_C", PCCompositeSpecialSetAlpha_Composite)); 5894b9ad928SBarry Smith PetscFunctionReturn(0); 5904b9ad928SBarry Smith } 591