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 */ 759371c9d4SSatish Balay 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; 163*48a46eb9SPierre Jolivet if (!jac->work1) PetscCall(MatCreateVecs(pc->pmat, &jac->work1, NULL)); 1649566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 1654b9ad928SBarry Smith while (next) { 166*48a46eb9SPierre Jolivet if (!next->pc->dm) PetscCall(PCSetDM(next->pc, dm)); 167*48a46eb9SPierre 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 2624b9ad928SBarry Smith /* ------------------------------------------------------------------------------*/ 2634b9ad928SBarry Smith 2649371c9d4SSatish Balay static PetscErrorCode PCCompositeSpecialSetAlpha_Composite(PC pc, PetscScalar alpha) { 2654b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 2665fd66863SKarl Rupp 2674b9ad928SBarry Smith PetscFunctionBegin; 2684b9ad928SBarry Smith jac->alpha = alpha; 2694b9ad928SBarry Smith PetscFunctionReturn(0); 2704b9ad928SBarry Smith } 2714b9ad928SBarry Smith 2729371c9d4SSatish Balay static PetscErrorCode PCCompositeSetType_Composite(PC pc, PCCompositeType type) { 273fad69fbaSJed Brown PC_Composite *jac = (PC_Composite *)pc->data; 274fad69fbaSJed Brown 2754b9ad928SBarry Smith PetscFunctionBegin; 2764b9ad928SBarry Smith if (type == PC_COMPOSITE_ADDITIVE) { 2774b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 2782533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 279421e10b8SBarry Smith } else if (type == PC_COMPOSITE_MULTIPLICATIVE || type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 2804b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Multiplicative; 2812533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Multiplicative; 2824b9ad928SBarry Smith } else if (type == PC_COMPOSITE_SPECIAL) { 2834b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Special; 2840298fd71SBarry Smith pc->ops->applytranspose = NULL; 285a7261c6bSprj- } else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown composite preconditioner type"); 286fad69fbaSJed Brown jac->type = type; 2874b9ad928SBarry Smith PetscFunctionReturn(0); 2884b9ad928SBarry Smith } 2894b9ad928SBarry Smith 2909371c9d4SSatish Balay static PetscErrorCode PCCompositeGetType_Composite(PC pc, PCCompositeType *type) { 291c60c7ad4SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 292c60c7ad4SBarry Smith 293c60c7ad4SBarry Smith PetscFunctionBegin; 294c60c7ad4SBarry Smith *type = jac->type; 295c60c7ad4SBarry Smith PetscFunctionReturn(0); 296c60c7ad4SBarry Smith } 297c60c7ad4SBarry Smith 2989371c9d4SSatish Balay static PetscErrorCode PCCompositeAddPC_Composite(PC pc, PC subpc) { 2994b9ad928SBarry Smith PC_Composite *jac; 3005a9f2f41SSatish Balay PC_CompositeLink next, ilink; 30179416396SBarry Smith PetscInt cnt = 0; 3022dcb1b2aSMatthew Knepley const char *prefix; 303d726e3a5SJed Brown char newprefix[20]; 3044b9ad928SBarry Smith 3054b9ad928SBarry Smith PetscFunctionBegin; 3069566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc, &ilink)); 3070a545947SLisandro Dalcin ilink->next = NULL; 3088aa07aa6SMatthew G. Knepley ilink->pc = subpc; 3094b9ad928SBarry Smith 3104b9ad928SBarry Smith jac = (PC_Composite *)pc->data; 3114b9ad928SBarry Smith next = jac->head; 3124b9ad928SBarry Smith if (!next) { 3135a9f2f41SSatish Balay jac->head = ilink; 3140298fd71SBarry Smith ilink->previous = NULL; 3154b9ad928SBarry Smith } else { 3164b9ad928SBarry Smith cnt++; 3174b9ad928SBarry Smith while (next->next) { 3184b9ad928SBarry Smith next = next->next; 3194b9ad928SBarry Smith cnt++; 3204b9ad928SBarry Smith } 3215a9f2f41SSatish Balay next->next = ilink; 322421e10b8SBarry Smith ilink->previous = next; 3234b9ad928SBarry Smith } 3249566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix)); 3259566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(subpc, prefix)); 3269566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(newprefix, 20, "sub_%d_", (int)cnt)); 3279566063dSJacob Faibussowitsch PetscCall(PCAppendOptionsPrefix(subpc, newprefix)); 3289566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)subpc)); 3298aa07aa6SMatthew G. Knepley PetscFunctionReturn(0); 3308aa07aa6SMatthew G. Knepley } 3318aa07aa6SMatthew G. Knepley 3329371c9d4SSatish Balay static PetscErrorCode PCCompositeAddPCType_Composite(PC pc, PCType type) { 3338aa07aa6SMatthew G. Knepley PC subpc; 3348aa07aa6SMatthew G. Knepley 3358aa07aa6SMatthew G. Knepley PetscFunctionBegin; 3369566063dSJacob Faibussowitsch PetscCall(PCCreate(PetscObjectComm((PetscObject)pc), &subpc)); 3379566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)subpc, (PetscObject)pc, 1)); 3389566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)subpc)); 3399566063dSJacob Faibussowitsch PetscCall(PCCompositeAddPC_Composite(pc, subpc)); 3404b9ad928SBarry Smith /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */ 3419566063dSJacob Faibussowitsch PetscCall(PCSetType(subpc, type)); 3429566063dSJacob Faibussowitsch PetscCall(PCDestroy(&subpc)); 3434b9ad928SBarry Smith PetscFunctionReturn(0); 3444b9ad928SBarry Smith } 3454b9ad928SBarry Smith 3469371c9d4SSatish Balay static PetscErrorCode PCCompositeGetNumberPC_Composite(PC pc, PetscInt *n) { 3478e6eba06SBarry Smith PC_Composite *jac; 3488e6eba06SBarry Smith PC_CompositeLink next; 3498e6eba06SBarry Smith 3508e6eba06SBarry Smith PetscFunctionBegin; 3518e6eba06SBarry Smith jac = (PC_Composite *)pc->data; 3528e6eba06SBarry Smith next = jac->head; 3538e6eba06SBarry Smith *n = 0; 3548e6eba06SBarry Smith while (next) { 3558e6eba06SBarry Smith next = next->next; 3568e6eba06SBarry Smith (*n)++; 3578e6eba06SBarry Smith } 3588e6eba06SBarry Smith PetscFunctionReturn(0); 3598e6eba06SBarry Smith } 3608e6eba06SBarry Smith 3619371c9d4SSatish Balay static PetscErrorCode PCCompositeGetPC_Composite(PC pc, PetscInt n, PC *subpc) { 3624b9ad928SBarry Smith PC_Composite *jac; 3634b9ad928SBarry Smith PC_CompositeLink next; 36479416396SBarry Smith PetscInt i; 3654b9ad928SBarry Smith 3664b9ad928SBarry Smith PetscFunctionBegin; 3674b9ad928SBarry Smith jac = (PC_Composite *)pc->data; 3684b9ad928SBarry Smith next = jac->head; 3694b9ad928SBarry Smith for (i = 0; i < n; i++) { 37028b400f6SJacob Faibussowitsch PetscCheck(next->next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Not enough PCs in composite preconditioner"); 3714b9ad928SBarry Smith next = next->next; 3724b9ad928SBarry Smith } 3734b9ad928SBarry Smith *subpc = next->pc; 3744b9ad928SBarry Smith PetscFunctionReturn(0); 3754b9ad928SBarry Smith } 3764b9ad928SBarry Smith 3774b9ad928SBarry Smith /* -------------------------------------------------------------------------------- */ 378f39d8e23SSatish Balay /*@ 3794b9ad928SBarry Smith PCCompositeSetType - Sets the type of composite preconditioner. 3804b9ad928SBarry Smith 381ad4df100SBarry Smith Logically Collective on PC 3824b9ad928SBarry Smith 383c60c7ad4SBarry Smith Input Parameters: 3842a6744ebSBarry Smith + pc - the preconditioner context 3852a6744ebSBarry Smith - type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL 3864b9ad928SBarry Smith 3874b9ad928SBarry Smith Options Database Key: 3884b9ad928SBarry Smith . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 3894b9ad928SBarry Smith 3904b9ad928SBarry Smith Level: Developer 3914b9ad928SBarry Smith 3924b9ad928SBarry Smith @*/ 3939371c9d4SSatish Balay PetscErrorCode PCCompositeSetType(PC pc, PCCompositeType type) { 3944b9ad928SBarry Smith PetscFunctionBegin; 3950700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 396c5eb9154SBarry Smith PetscValidLogicalCollectiveEnum(pc, type, 2); 397cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeSetType_C", (PC, PCCompositeType), (pc, type)); 3984b9ad928SBarry Smith PetscFunctionReturn(0); 3994b9ad928SBarry Smith } 4004b9ad928SBarry Smith 401c60c7ad4SBarry Smith /*@ 402721f67b5SBarry Smith PCCompositeGetType - Gets the type of composite preconditioner. 403c60c7ad4SBarry Smith 404c60c7ad4SBarry Smith Logically Collective on PC 405c60c7ad4SBarry Smith 406c60c7ad4SBarry Smith Input Parameter: 407c60c7ad4SBarry Smith . pc - the preconditioner context 408c60c7ad4SBarry Smith 409c60c7ad4SBarry Smith Output Parameter: 410c60c7ad4SBarry Smith . type - PC_COMPOSITE_ADDITIVE (default), PC_COMPOSITE_MULTIPLICATIVE, PC_COMPOSITE_SPECIAL 411c60c7ad4SBarry Smith 412c60c7ad4SBarry Smith Options Database Key: 413c60c7ad4SBarry Smith . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 414c60c7ad4SBarry Smith 415c60c7ad4SBarry Smith Level: Developer 416c60c7ad4SBarry Smith 417c60c7ad4SBarry Smith @*/ 4189371c9d4SSatish Balay PetscErrorCode PCCompositeGetType(PC pc, PCCompositeType *type) { 419c60c7ad4SBarry Smith PetscFunctionBegin; 420c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 421cac4c232SBarry Smith PetscUseMethod(pc, "PCCompositeGetType_C", (PC, PCCompositeType *), (pc, type)); 422c60c7ad4SBarry Smith PetscFunctionReturn(0); 423c60c7ad4SBarry Smith } 424c60c7ad4SBarry Smith 425f39d8e23SSatish Balay /*@ 4264b9ad928SBarry Smith PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner 4274b9ad928SBarry Smith for alphaI + R + S 4284b9ad928SBarry Smith 429ad4df100SBarry Smith Logically Collective on PC 4304b9ad928SBarry Smith 431d8d19677SJose E. Roman Input Parameters: 4324b9ad928SBarry Smith + pc - the preconditioner context 4334b9ad928SBarry Smith - alpha - scale on identity 4344b9ad928SBarry Smith 4354b9ad928SBarry Smith Level: Developer 4364b9ad928SBarry Smith 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 4478aa07aa6SMatthew G. Knepley PCCompositeAddPCType - Adds another PC of the given type to the composite PC. 4484b9ad928SBarry Smith 4494b9ad928SBarry 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 4554b9ad928SBarry Smith Level: Developer 4564b9ad928SBarry Smith 457db781477SPatrick Sanan .seealso: `PCCompositeAddPC()` 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 /*@ 4678aa07aa6SMatthew G. Knepley PCCompositeAddPC - Adds another PC to the composite PC. 4688aa07aa6SMatthew G. Knepley 4698aa07aa6SMatthew G. Knepley 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 4758aa07aa6SMatthew G. Knepley Level: Developer 4768aa07aa6SMatthew G. Knepley 477db781477SPatrick Sanan .seealso: `PCCompositeAddPCType()` 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 /*@ 4888e6eba06SBarry 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 500db781477SPatrick Sanan .seealso: `PCCompositeGetPC()` 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 /*@ 5114b9ad928SBarry 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 5194b9ad928SBarry Smith Output Parameters: 5204b9ad928SBarry Smith . subpc - the PC requested 5214b9ad928SBarry Smith 5224b9ad928SBarry Smith Level: Developer 5234b9ad928SBarry Smith 52495452b02SPatrick Sanan Notes: 52595452b02SPatrick Sanan To use a different operator to construct one of the inner preconditioners first call PCCompositeGetPC(), then 5262b1d202aSBarry Smith call PCSetOperators() on that PC. 5272b1d202aSBarry Smith 528db781477SPatrick Sanan .seealso: `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 /* -------------------------------------------------------------------------------------------*/ 5394b9ad928SBarry Smith 5404b9ad928SBarry Smith /*MC 5414b9ad928SBarry Smith PCCOMPOSITE - Build a preconditioner by composing together several preconditioners 5424b9ad928SBarry Smith 5434b9ad928SBarry Smith Options Database Keys: 5442eab2d5bSJungho Lee + -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type 5452b1d202aSBarry Smith . -pc_use_amat - activates PCSetUseAmat() 54651f519a2SBarry Smith - -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose 5474b9ad928SBarry Smith 5484b9ad928SBarry Smith Level: intermediate 5494b9ad928SBarry Smith 55095452b02SPatrick Sanan Notes: 55195452b02SPatrick Sanan To use a Krylov method inside the composite preconditioner, set the PCType of one or more 5524b9ad928SBarry Smith inner PCs to be PCKSP. 5534b9ad928SBarry Smith Using a Krylov method inside another Krylov method can be dangerous (you get divergence or 554b3ef52cdSBarry Smith the incorrect answer) unless you use KSPFGMRES as the outer Krylov method 5552b1d202aSBarry Smith To use a different operator to construct one of the inner preconditioners first call PCCompositeGetPC(), then 5562b1d202aSBarry Smith call PCSetOperators() on that PC. 5574b9ad928SBarry Smith 558db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, 559db781477SPatrick Sanan `PCSHELL`, `PCKSP`, `PCCompositeSetType()`, `PCCompositeSpecialSetAlpha()`, `PCCompositeAddPCType()`, 560db781477SPatrick Sanan `PCCompositeGetPC()`, `PCSetUseAmat()` 5614b9ad928SBarry Smith 5624b9ad928SBarry Smith M*/ 5634b9ad928SBarry Smith 5649371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc) { 5654b9ad928SBarry Smith PC_Composite *jac; 5664b9ad928SBarry Smith 5674b9ad928SBarry Smith PetscFunctionBegin; 5689566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc, &jac)); 5692fa5cd67SKarl Rupp 5704b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 5712533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 5724b9ad928SBarry Smith pc->ops->setup = PCSetUp_Composite; 57369d2c0f9SBarry Smith pc->ops->reset = PCReset_Composite; 5744b9ad928SBarry Smith pc->ops->destroy = PCDestroy_Composite; 5754b9ad928SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Composite; 5764b9ad928SBarry Smith pc->ops->view = PCView_Composite; 5770a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 5784b9ad928SBarry Smith 5794b9ad928SBarry Smith pc->data = (void *)jac; 5804b9ad928SBarry Smith jac->type = PC_COMPOSITE_ADDITIVE; 5810a545947SLisandro Dalcin jac->work1 = NULL; 5820a545947SLisandro Dalcin jac->work2 = NULL; 5830a545947SLisandro Dalcin jac->head = NULL; 5844b9ad928SBarry Smith 5859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSetType_C", PCCompositeSetType_Composite)); 5869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetType_C", PCCompositeGetType_Composite)); 5879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPCType_C", PCCompositeAddPCType_Composite)); 5889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPC_C", PCCompositeAddPC_Composite)); 5899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetNumberPC_C", PCCompositeGetNumberPC_Composite)); 5909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetPC_C", PCCompositeGetPC_Composite)); 5919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSpecialSetAlpha_C", PCCompositeSpecialSetAlpha_Composite)); 5924b9ad928SBarry Smith PetscFunctionReturn(0); 5934b9ad928SBarry Smith } 594