14b9ad928SBarry Smith /* 24b9ad928SBarry Smith Defines a preconditioner that can consist of a collection of PCs 34b9ad928SBarry Smith */ 4af0996ceSBarry Smith #include <petsc/private/pcimpl.h> 5c6db04a5SJed Brown #include <petscksp.h> /*I "petscksp.h" I*/ 64b9ad928SBarry Smith 74b9ad928SBarry Smith typedef struct _PC_CompositeLink *PC_CompositeLink; 84b9ad928SBarry Smith struct _PC_CompositeLink { 94b9ad928SBarry Smith PC pc; 104b9ad928SBarry Smith PC_CompositeLink next; 11421e10b8SBarry Smith PC_CompositeLink previous; 124b9ad928SBarry Smith }; 134b9ad928SBarry Smith 144b9ad928SBarry Smith typedef struct { 154b9ad928SBarry Smith PC_CompositeLink head; 164b9ad928SBarry Smith PCCompositeType type; 174b9ad928SBarry Smith Vec work1; 184b9ad928SBarry Smith Vec work2; 194b9ad928SBarry Smith PetscScalar alpha; 204b9ad928SBarry Smith } PC_Composite; 214b9ad928SBarry Smith 22d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_Composite_Multiplicative(PC pc, Vec x, Vec y) 23d71ae5a4SJacob Faibussowitsch { 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; 2928b400f6SJacob Faibussowitsch PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 30450d59ebSPatrick Farrell 31450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 32450d59ebSPatrick Farrell while (next) { 339566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->pc, pc->reusepreconditioner)); 34450d59ebSPatrick Farrell next = next->next; 35450d59ebSPatrick Farrell } 36450d59ebSPatrick Farrell next = jac->head; 37450d59ebSPatrick Farrell 384b9ad928SBarry Smith if (next->next && !jac->work2) { /* allocate second work vector */ 399566063dSJacob Faibussowitsch PetscCall(VecDuplicate(jac->work1, &jac->work2)); 404b9ad928SBarry Smith } 4149517cdeSBarry Smith if (pc->useAmat) mat = pc->mat; 429566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, x, y)); /* y <- B x */ 434b9ad928SBarry Smith while (next->next) { 444b9ad928SBarry Smith next = next->next; 459566063dSJacob Faibussowitsch PetscCall(MatMult(mat, y, jac->work1)); /* work1 <- A y */ 469566063dSJacob Faibussowitsch PetscCall(VecWAXPY(jac->work2, -1.0, jac->work1, x)); /* work2 <- x - work1 */ 479566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, jac->work2, jac->work1)); /* work1 <- C work2 */ 489566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); /* y <- y + work1 = B x + C (x - A B x) = (B + C (1 - A B)) x */ 494b9ad928SBarry Smith } 50421e10b8SBarry Smith if (jac->type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 51421e10b8SBarry Smith while (next->previous) { 52421e10b8SBarry Smith next = next->previous; 539566063dSJacob Faibussowitsch PetscCall(MatMult(mat, y, jac->work1)); 549566063dSJacob Faibussowitsch PetscCall(VecWAXPY(jac->work2, -1.0, jac->work1, x)); 559566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, jac->work2, jac->work1)); 569566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); 57421e10b8SBarry Smith } 58421e10b8SBarry Smith } 593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 604b9ad928SBarry Smith } 614b9ad928SBarry Smith 62d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_Composite_Multiplicative(PC pc, Vec x, Vec y) 63d71ae5a4SJacob Faibussowitsch { 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 } 943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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 */ 102d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_Composite_Special(PC pc, Vec x, Vec y) 103d71ae5a4SJacob Faibussowitsch { 1044b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1054b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1064b9ad928SBarry Smith 1074b9ad928SBarry Smith PetscFunctionBegin; 10828b400f6SJacob Faibussowitsch PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 1097827d75bSBarry Smith PetscCheck(next->next && !next->next->next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Special composite preconditioners requires exactly two PCs"); 1104b9ad928SBarry Smith 111450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 1129566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->pc, pc->reusepreconditioner)); 1139566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->next->pc, pc->reusepreconditioner)); 114450d59ebSPatrick Farrell 1159566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, x, jac->work1)); 1169566063dSJacob Faibussowitsch PetscCall(PCApply(next->next->pc, jac->work1, y)); 1173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1184b9ad928SBarry Smith } 1194b9ad928SBarry Smith 120d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_Composite_Additive(PC pc, Vec x, Vec y) 121d71ae5a4SJacob Faibussowitsch { 1224b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1234b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1244b9ad928SBarry Smith 1254b9ad928SBarry Smith PetscFunctionBegin; 12628b400f6SJacob Faibussowitsch PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 127450d59ebSPatrick Farrell 128450d59ebSPatrick Farrell /* Set the reuse flag on children PCs */ 129450d59ebSPatrick Farrell while (next) { 1309566063dSJacob Faibussowitsch PetscCall(PCSetReusePreconditioner(next->pc, pc->reusepreconditioner)); 131450d59ebSPatrick Farrell next = next->next; 132450d59ebSPatrick Farrell } 133450d59ebSPatrick Farrell next = jac->head; 134450d59ebSPatrick Farrell 1359566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, x, y)); 1364b9ad928SBarry Smith while (next->next) { 1374b9ad928SBarry Smith next = next->next; 1389566063dSJacob Faibussowitsch PetscCall(PCApply(next->pc, x, jac->work1)); 1399566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); 1404b9ad928SBarry Smith } 1413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1424b9ad928SBarry Smith } 1434b9ad928SBarry Smith 144d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_Composite_Additive(PC pc, Vec x, Vec y) 145d71ae5a4SJacob Faibussowitsch { 1462533e041SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1472533e041SBarry Smith PC_CompositeLink next = jac->head; 1482533e041SBarry Smith 1492533e041SBarry Smith PetscFunctionBegin; 15028b400f6SJacob Faibussowitsch PetscCheck(next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "No composite preconditioners supplied via PCCompositeAddPCType() or -pc_composite_pcs"); 1519566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc, x, y)); 1522533e041SBarry Smith while (next->next) { 1532533e041SBarry Smith next = next->next; 1549566063dSJacob Faibussowitsch PetscCall(PCApplyTranspose(next->pc, x, jac->work1)); 1559566063dSJacob Faibussowitsch PetscCall(VecAXPY(y, 1.0, jac->work1)); 1562533e041SBarry Smith } 1573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1582533e041SBarry Smith } 1592533e041SBarry Smith 160d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_Composite(PC pc) 161d71ae5a4SJacob Faibussowitsch { 1624b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1634b9ad928SBarry Smith PC_CompositeLink next = jac->head; 1645a78d018SMatthew G. Knepley DM dm; 1654b9ad928SBarry Smith 1664b9ad928SBarry Smith PetscFunctionBegin; 16748a46eb9SPierre Jolivet if (!jac->work1) PetscCall(MatCreateVecs(pc->pmat, &jac->work1, NULL)); 1689566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 1694b9ad928SBarry Smith while (next) { 17048a46eb9SPierre Jolivet if (!next->pc->dm) PetscCall(PCSetDM(next->pc, dm)); 17148a46eb9SPierre Jolivet if (!next->pc->mat) PetscCall(PCSetOperators(next->pc, pc->mat, pc->pmat)); 1724b9ad928SBarry Smith next = next->next; 1734b9ad928SBarry Smith } 1743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1754b9ad928SBarry Smith } 1764b9ad928SBarry Smith 1774f853519SStefano Zampini static PetscErrorCode PCSetUpOnBlocks_Composite(PC pc) 1784f853519SStefano Zampini { 1794f853519SStefano Zampini PC_Composite *jac = (PC_Composite *)pc->data; 1804f853519SStefano Zampini PC_CompositeLink next = jac->head; 1814f853519SStefano Zampini PCFailedReason reason; 1824f853519SStefano Zampini 1834f853519SStefano Zampini PetscFunctionBegin; 1844f853519SStefano Zampini while (next) { 1854f853519SStefano Zampini PetscCall(PCSetUp(next->pc)); 1864f853519SStefano Zampini PetscCall(PCGetFailedReasonRank(next->pc, &reason)); 1874f853519SStefano Zampini if (reason) pc->failedreason = reason; 1884f853519SStefano Zampini next = next->next; 1894f853519SStefano Zampini } 1904f853519SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1914f853519SStefano Zampini } 1924f853519SStefano Zampini 193d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_Composite(PC pc) 194d71ae5a4SJacob Faibussowitsch { 19569d2c0f9SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 1965f48b12bSBarry Smith PC_CompositeLink next = jac->head; 19769d2c0f9SBarry Smith 19869d2c0f9SBarry Smith PetscFunctionBegin; 19969d2c0f9SBarry Smith while (next) { 2009566063dSJacob Faibussowitsch PetscCall(PCReset(next->pc)); 20169d2c0f9SBarry Smith next = next->next; 20269d2c0f9SBarry Smith } 2039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&jac->work1)); 2049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&jac->work2)); 2053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20669d2c0f9SBarry Smith } 20769d2c0f9SBarry Smith 208d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_Composite(PC pc) 209d71ae5a4SJacob Faibussowitsch { 2104b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 211724c2c99SHong Zhang PC_CompositeLink next = jac->head, next_tmp; 2124b9ad928SBarry Smith 2134b9ad928SBarry Smith PetscFunctionBegin; 2149566063dSJacob Faibussowitsch PetscCall(PCReset_Composite(pc)); 2154b9ad928SBarry Smith while (next) { 2169566063dSJacob Faibussowitsch PetscCall(PCDestroy(&next->pc)); 217724c2c99SHong Zhang next_tmp = next; 2184b9ad928SBarry Smith next = next->next; 2199566063dSJacob Faibussowitsch PetscCall(PetscFree(next_tmp)); 2204b9ad928SBarry Smith } 2212e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSetType_C", NULL)); 2222e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetType_C", NULL)); 2232e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPCType_C", NULL)); 2242e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPC_C", NULL)); 2252e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetNumberPC_C", NULL)); 2262e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetPC_C", NULL)); 2272e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSpecialSetAlpha_C", NULL)); 2289566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 2293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2304b9ad928SBarry Smith } 2314b9ad928SBarry Smith 232d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_Composite(PC pc, PetscOptionItems *PetscOptionsObject) 233d71ae5a4SJacob Faibussowitsch { 2344b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 235*fe972ab9SMatthew G. Knepley PetscInt nmax, i; 2364b9ad928SBarry Smith PC_CompositeLink next; 237*fe972ab9SMatthew G. Knepley char *pcs[1024]; 238ace3abfcSBarry Smith PetscBool flg; 2394b9ad928SBarry Smith 2404b9ad928SBarry Smith PetscFunctionBegin; 241d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Composite preconditioner options"); 2429566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-pc_composite_type", "Type of composition", "PCCompositeSetType", PCCompositeTypes, (PetscEnum)jac->type, (PetscEnum *)&jac->type, &flg)); 2431baa6e33SBarry Smith if (flg) PetscCall(PCCompositeSetType(pc, jac->type)); 244*fe972ab9SMatthew G. Knepley nmax = (PetscInt)PETSC_STATIC_ARRAY_LENGTH(pcs); 2459566063dSJacob Faibussowitsch PetscCall(PetscOptionsStringArray("-pc_composite_pcs", "List of composite solvers", "PCCompositeAddPCType", pcs, &nmax, &flg)); 2464b9ad928SBarry Smith if (flg) { 2474b9ad928SBarry Smith for (i = 0; i < nmax; i++) { 2489566063dSJacob Faibussowitsch PetscCall(PCCompositeAddPCType(pc, pcs[i])); 2499566063dSJacob Faibussowitsch PetscCall(PetscFree(pcs[i])); /* deallocate string pcs[i], which is allocated in PetscOptionsStringArray() */ 2504b9ad928SBarry Smith } 2514b9ad928SBarry Smith } 252d0609cedSBarry Smith PetscOptionsHeadEnd(); 2534b9ad928SBarry Smith 2544b9ad928SBarry Smith next = jac->head; 2554b9ad928SBarry Smith while (next) { 2569566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(next->pc)); 2574b9ad928SBarry Smith next = next->next; 2584b9ad928SBarry Smith } 2593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2604b9ad928SBarry Smith } 2614b9ad928SBarry Smith 262d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_Composite(PC pc, PetscViewer viewer) 263d71ae5a4SJacob Faibussowitsch { 2644b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 2654b9ad928SBarry Smith PC_CompositeLink next = jac->head; 266ace3abfcSBarry Smith PetscBool iascii; 2674b9ad928SBarry Smith 2684b9ad928SBarry Smith PetscFunctionBegin; 2699566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 27032077d6dSBarry Smith if (iascii) { 2719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Composite PC type - %s\n", PCCompositeTypes[jac->type])); 2729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "PCs on composite preconditioner follow\n")); 2739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "---------------------------------\n")); 2744b9ad928SBarry Smith } 2751baa6e33SBarry Smith if (iascii) PetscCall(PetscViewerASCIIPushTab(viewer)); 2764b9ad928SBarry Smith while (next) { 2779566063dSJacob Faibussowitsch PetscCall(PCView(next->pc, viewer)); 2784b9ad928SBarry Smith next = next->next; 2794b9ad928SBarry Smith } 28032077d6dSBarry Smith if (iascii) { 2819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 2829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "---------------------------------\n")); 2834b9ad928SBarry Smith } 2843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2854b9ad928SBarry Smith } 2864b9ad928SBarry Smith 287d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeSpecialSetAlpha_Composite(PC pc, PetscScalar alpha) 288d71ae5a4SJacob Faibussowitsch { 2894b9ad928SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 2905fd66863SKarl Rupp 2914b9ad928SBarry Smith PetscFunctionBegin; 2924b9ad928SBarry Smith jac->alpha = alpha; 2933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2944b9ad928SBarry Smith } 2954b9ad928SBarry Smith 296d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeSetType_Composite(PC pc, PCCompositeType type) 297d71ae5a4SJacob Faibussowitsch { 298fad69fbaSJed Brown PC_Composite *jac = (PC_Composite *)pc->data; 299fad69fbaSJed Brown 3004b9ad928SBarry Smith PetscFunctionBegin; 3014b9ad928SBarry Smith if (type == PC_COMPOSITE_ADDITIVE) { 3024b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 3032533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 304421e10b8SBarry Smith } else if (type == PC_COMPOSITE_MULTIPLICATIVE || type == PC_COMPOSITE_SYMMETRIC_MULTIPLICATIVE) { 3054b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Multiplicative; 3062533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Multiplicative; 3074b9ad928SBarry Smith } else if (type == PC_COMPOSITE_SPECIAL) { 3084b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Special; 3090298fd71SBarry Smith pc->ops->applytranspose = NULL; 310a7261c6bSprj- } else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Unknown composite preconditioner type"); 311fad69fbaSJed Brown jac->type = type; 3123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3134b9ad928SBarry Smith } 3144b9ad928SBarry Smith 315d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeGetType_Composite(PC pc, PCCompositeType *type) 316d71ae5a4SJacob Faibussowitsch { 317c60c7ad4SBarry Smith PC_Composite *jac = (PC_Composite *)pc->data; 318c60c7ad4SBarry Smith 319c60c7ad4SBarry Smith PetscFunctionBegin; 320c60c7ad4SBarry Smith *type = jac->type; 3213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 322c60c7ad4SBarry Smith } 323c60c7ad4SBarry Smith 324d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeAddPC_Composite(PC pc, PC subpc) 325d71ae5a4SJacob Faibussowitsch { 3264b9ad928SBarry Smith PC_Composite *jac; 3275a9f2f41SSatish Balay PC_CompositeLink next, ilink; 32879416396SBarry Smith PetscInt cnt = 0; 3292dcb1b2aSMatthew Knepley const char *prefix; 330d726e3a5SJed Brown char newprefix[20]; 3314b9ad928SBarry Smith 3324b9ad928SBarry Smith PetscFunctionBegin; 3334dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&ilink)); 3340a545947SLisandro Dalcin ilink->next = NULL; 3358aa07aa6SMatthew G. Knepley ilink->pc = subpc; 3364b9ad928SBarry Smith 3374b9ad928SBarry Smith jac = (PC_Composite *)pc->data; 3384b9ad928SBarry Smith next = jac->head; 3394b9ad928SBarry Smith if (!next) { 3405a9f2f41SSatish Balay jac->head = ilink; 3410298fd71SBarry Smith ilink->previous = NULL; 3424b9ad928SBarry Smith } else { 3434b9ad928SBarry Smith cnt++; 3444b9ad928SBarry Smith while (next->next) { 3454b9ad928SBarry Smith next = next->next; 3464b9ad928SBarry Smith cnt++; 3474b9ad928SBarry Smith } 3485a9f2f41SSatish Balay next->next = ilink; 349421e10b8SBarry Smith ilink->previous = next; 3504b9ad928SBarry Smith } 3519566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix)); 3529566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(subpc, prefix)); 3539566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(newprefix, 20, "sub_%d_", (int)cnt)); 3549566063dSJacob Faibussowitsch PetscCall(PCAppendOptionsPrefix(subpc, newprefix)); 3559566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)subpc)); 3563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3578aa07aa6SMatthew G. Knepley } 3588aa07aa6SMatthew G. Knepley 359d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeAddPCType_Composite(PC pc, PCType type) 360d71ae5a4SJacob Faibussowitsch { 3618aa07aa6SMatthew G. Knepley PC subpc; 3628aa07aa6SMatthew G. Knepley 3638aa07aa6SMatthew G. Knepley PetscFunctionBegin; 3649566063dSJacob Faibussowitsch PetscCall(PCCreate(PetscObjectComm((PetscObject)pc), &subpc)); 3659566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)subpc, (PetscObject)pc, 1)); 3669566063dSJacob Faibussowitsch PetscCall(PCCompositeAddPC_Composite(pc, subpc)); 3674b9ad928SBarry Smith /* type is set after prefix, because some methods may modify prefix, e.g. pcksp */ 3689566063dSJacob Faibussowitsch PetscCall(PCSetType(subpc, type)); 3699566063dSJacob Faibussowitsch PetscCall(PCDestroy(&subpc)); 3703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3714b9ad928SBarry Smith } 3724b9ad928SBarry Smith 373d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeGetNumberPC_Composite(PC pc, PetscInt *n) 374d71ae5a4SJacob Faibussowitsch { 3758e6eba06SBarry Smith PC_Composite *jac; 3768e6eba06SBarry Smith PC_CompositeLink next; 3778e6eba06SBarry Smith 3788e6eba06SBarry Smith PetscFunctionBegin; 3798e6eba06SBarry Smith jac = (PC_Composite *)pc->data; 3808e6eba06SBarry Smith next = jac->head; 3818e6eba06SBarry Smith *n = 0; 3828e6eba06SBarry Smith while (next) { 3838e6eba06SBarry Smith next = next->next; 3848e6eba06SBarry Smith (*n)++; 3858e6eba06SBarry Smith } 3863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3878e6eba06SBarry Smith } 3888e6eba06SBarry Smith 389d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCCompositeGetPC_Composite(PC pc, PetscInt n, PC *subpc) 390d71ae5a4SJacob Faibussowitsch { 3914b9ad928SBarry Smith PC_Composite *jac; 3924b9ad928SBarry Smith PC_CompositeLink next; 39379416396SBarry Smith PetscInt i; 3944b9ad928SBarry Smith 3954b9ad928SBarry Smith PetscFunctionBegin; 3964b9ad928SBarry Smith jac = (PC_Composite *)pc->data; 3974b9ad928SBarry Smith next = jac->head; 3984b9ad928SBarry Smith for (i = 0; i < n; i++) { 39928b400f6SJacob Faibussowitsch PetscCheck(next->next, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_INCOMP, "Not enough PCs in composite preconditioner"); 4004b9ad928SBarry Smith next = next->next; 4014b9ad928SBarry Smith } 4024b9ad928SBarry Smith *subpc = next->pc; 4033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4044b9ad928SBarry Smith } 4054b9ad928SBarry Smith 406f39d8e23SSatish Balay /*@ 4074b9ad928SBarry Smith PCCompositeSetType - Sets the type of composite preconditioner. 4084b9ad928SBarry Smith 409c3339decSBarry Smith Logically Collective 4104b9ad928SBarry Smith 411c60c7ad4SBarry Smith Input Parameters: 4122a6744ebSBarry Smith + pc - the preconditioner context 413f1580f4eSBarry Smith - type - `PC_COMPOSITE_ADDITIVE` (default), `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL` 4144b9ad928SBarry Smith 4154b9ad928SBarry Smith Options Database Key: 4164b9ad928SBarry Smith . -pc_composite_type <type: one of multiplicative, additive, special> - Sets composite preconditioner type 4174b9ad928SBarry Smith 418f1580f4eSBarry Smith Level: advanced 4194b9ad928SBarry Smith 420562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCOMPOSITE`, `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL`, `PCCompositeType`, 421f1580f4eSBarry Smith `PCCompositeGetType()` 4224b9ad928SBarry Smith @*/ 423d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeSetType(PC pc, PCCompositeType type) 424d71ae5a4SJacob Faibussowitsch { 4254b9ad928SBarry Smith PetscFunctionBegin; 4260700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 427c5eb9154SBarry Smith PetscValidLogicalCollectiveEnum(pc, type, 2); 428cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeSetType_C", (PC, PCCompositeType), (pc, type)); 4293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4304b9ad928SBarry Smith } 4314b9ad928SBarry Smith 432c60c7ad4SBarry Smith /*@ 433721f67b5SBarry Smith PCCompositeGetType - Gets the type of composite preconditioner. 434c60c7ad4SBarry Smith 435c3339decSBarry Smith Logically Collective 436c60c7ad4SBarry Smith 437c60c7ad4SBarry Smith Input Parameter: 438c60c7ad4SBarry Smith . pc - the preconditioner context 439c60c7ad4SBarry Smith 440c60c7ad4SBarry Smith Output Parameter: 441f1580f4eSBarry Smith . type - `PC_COMPOSITE_ADDITIVE` (default), `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL` 442c60c7ad4SBarry Smith 443f1580f4eSBarry Smith Level: advanced 444c60c7ad4SBarry Smith 445562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCOMPOSITE`, `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL`, `PCCompositeType`, 446f1580f4eSBarry Smith `PCCompositeSetType()` 447c60c7ad4SBarry Smith @*/ 448d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeGetType(PC pc, PCCompositeType *type) 449d71ae5a4SJacob Faibussowitsch { 450c60c7ad4SBarry Smith PetscFunctionBegin; 451c60c7ad4SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 452cac4c232SBarry Smith PetscUseMethod(pc, "PCCompositeGetType_C", (PC, PCCompositeType *), (pc, type)); 4533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 454c60c7ad4SBarry Smith } 455c60c7ad4SBarry Smith 456f39d8e23SSatish Balay /*@ 457f1580f4eSBarry Smith PCCompositeSpecialSetAlpha - Sets alpha for the special composite preconditioner, `PC_COMPOSITE_SPECIAL`, 458af27ebaaSBarry Smith for $\alpha I + R + S$ 4594b9ad928SBarry Smith 460c3339decSBarry Smith Logically Collective 4614b9ad928SBarry Smith 462d8d19677SJose E. Roman Input Parameters: 4634b9ad928SBarry Smith + pc - the preconditioner context 4644b9ad928SBarry Smith - alpha - scale on identity 4654b9ad928SBarry Smith 466feefa0e1SJacob Faibussowitsch Level: developer 4674b9ad928SBarry Smith 468562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCOMPOSITE`, `PC_COMPOSITE_ADDITIVE`, `PC_COMPOSITE_MULTIPLICATIVE`, `PC_COMPOSITE_SPECIAL`, `PCCompositeType`, 469f1580f4eSBarry Smith `PCCompositeSetType()`, `PCCompositeGetType()` 4704b9ad928SBarry Smith @*/ 471d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeSpecialSetAlpha(PC pc, PetscScalar alpha) 472d71ae5a4SJacob Faibussowitsch { 4734b9ad928SBarry Smith PetscFunctionBegin; 4740700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 475c5eb9154SBarry Smith PetscValidLogicalCollectiveScalar(pc, alpha, 2); 476cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeSpecialSetAlpha_C", (PC, PetscScalar), (pc, alpha)); 4773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4784b9ad928SBarry Smith } 4794b9ad928SBarry Smith 4804b9ad928SBarry Smith /*@C 481f1580f4eSBarry Smith PCCompositeAddPCType - Adds another `PC` of the given type to the composite `PC`. 4824b9ad928SBarry Smith 483c3339decSBarry Smith Collective 4844b9ad928SBarry Smith 4854b9ad928SBarry Smith Input Parameters: 4862a6744ebSBarry Smith + pc - the preconditioner context 4872a6744ebSBarry Smith - type - the type of the new preconditioner 4884b9ad928SBarry Smith 489f1580f4eSBarry Smith Level: intermediate 4904b9ad928SBarry Smith 491562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCOMPOSITE`, `PCCompositeAddPC()`, `PCCompositeGetNumberPC()` 4924b9ad928SBarry Smith @*/ 493d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeAddPCType(PC pc, PCType type) 494d71ae5a4SJacob Faibussowitsch { 4954b9ad928SBarry Smith PetscFunctionBegin; 4960700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 497cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeAddPCType_C", (PC, PCType), (pc, type)); 4983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4998aa07aa6SMatthew G. Knepley } 5008aa07aa6SMatthew G. Knepley 5018aa07aa6SMatthew G. Knepley /*@ 502f1580f4eSBarry Smith PCCompositeAddPC - Adds another `PC` to the composite `PC`. 5038aa07aa6SMatthew G. Knepley 504c3339decSBarry Smith Collective 5058aa07aa6SMatthew G. Knepley 5068aa07aa6SMatthew G. Knepley Input Parameters: 5078aa07aa6SMatthew G. Knepley + pc - the preconditioner context 5088aa07aa6SMatthew G. Knepley - subpc - the new preconditioner 5098aa07aa6SMatthew G. Knepley 510f1580f4eSBarry Smith Level: intermediate 5118aa07aa6SMatthew G. Knepley 512562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCOMPOSITE`, `PCCompositeAddPCType()`, `PCCompositeGetNumberPC()` 5138aa07aa6SMatthew G. Knepley @*/ 514d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeAddPC(PC pc, PC subpc) 515d71ae5a4SJacob Faibussowitsch { 5168aa07aa6SMatthew G. Knepley PetscFunctionBegin; 5178aa07aa6SMatthew G. Knepley PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5188aa07aa6SMatthew G. Knepley PetscValidHeaderSpecific(subpc, PC_CLASSID, 2); 519cac4c232SBarry Smith PetscTryMethod(pc, "PCCompositeAddPC_C", (PC, PC), (pc, subpc)); 5203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5214b9ad928SBarry Smith } 5224b9ad928SBarry Smith 5238e6eba06SBarry Smith /*@ 524f1580f4eSBarry Smith PCCompositeGetNumberPC - Gets the number of `PC` objects in the composite `PC`. 5258e6eba06SBarry Smith 5268e6eba06SBarry Smith Not Collective 5278e6eba06SBarry Smith 5288e6eba06SBarry Smith Input Parameter: 5298e6eba06SBarry Smith . pc - the preconditioner context 5308e6eba06SBarry Smith 5318e6eba06SBarry Smith Output Parameter: 5328e6eba06SBarry Smith . num - the number of sub pcs 5338e6eba06SBarry Smith 534feefa0e1SJacob Faibussowitsch Level: developer 5358e6eba06SBarry Smith 536562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCOMPOSITE`, `PCCompositeGetPC()`, `PCCompositeAddPC()`, `PCCompositeAddPCType()` 5378e6eba06SBarry Smith @*/ 538d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeGetNumberPC(PC pc, PetscInt *num) 539d71ae5a4SJacob Faibussowitsch { 5408e6eba06SBarry Smith PetscFunctionBegin; 5418e6eba06SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5424f572ea9SToby Isaac PetscAssertPointer(num, 2); 543cac4c232SBarry Smith PetscUseMethod(pc, "PCCompositeGetNumberPC_C", (PC, PetscInt *), (pc, num)); 5443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5458e6eba06SBarry Smith } 5468e6eba06SBarry Smith 547f39d8e23SSatish Balay /*@ 548f1580f4eSBarry Smith PCCompositeGetPC - Gets one of the `PC` objects in the composite `PC`. 5494b9ad928SBarry Smith 5504b9ad928SBarry Smith Not Collective 5514b9ad928SBarry Smith 552d8d19677SJose E. Roman Input Parameters: 5532a6744ebSBarry Smith + pc - the preconditioner context 5542a6744ebSBarry Smith - n - the number of the pc requested 5554b9ad928SBarry Smith 556f1580f4eSBarry Smith Output Parameter: 5574b9ad928SBarry Smith . subpc - the PC requested 5584b9ad928SBarry Smith 559f1580f4eSBarry Smith Level: intermediate 5604b9ad928SBarry Smith 561f1580f4eSBarry Smith Note: 562f1580f4eSBarry Smith To use a different operator to construct one of the inner preconditioners first call `PCCompositeGetPC()`, then 563f1580f4eSBarry Smith call `PCSetOperators()` on that `PC`. 5642b1d202aSBarry Smith 565562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCOMPOSITE`, `PCCompositeAddPCType()`, `PCCompositeGetNumberPC()`, `PCSetOperators()` 5664b9ad928SBarry Smith @*/ 567d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCompositeGetPC(PC pc, PetscInt n, PC *subpc) 568d71ae5a4SJacob Faibussowitsch { 5694b9ad928SBarry Smith PetscFunctionBegin; 5700700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5714f572ea9SToby Isaac PetscAssertPointer(subpc, 3); 572cac4c232SBarry Smith PetscUseMethod(pc, "PCCompositeGetPC_C", (PC, PetscInt, PC *), (pc, n, subpc)); 5733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5744b9ad928SBarry Smith } 5754b9ad928SBarry Smith 5764b9ad928SBarry Smith /*MC 5774b9ad928SBarry Smith PCCOMPOSITE - Build a preconditioner by composing together several preconditioners 5784b9ad928SBarry Smith 5794b9ad928SBarry Smith Options Database Keys: 5802eab2d5bSJungho Lee + -pc_composite_type <type: one of multiplicative, additive, symmetric_multiplicative, special> - Sets composite preconditioner type 581f1580f4eSBarry Smith . -pc_use_amat - activates `PCSetUseAmat()` 58251f519a2SBarry Smith - -pc_composite_pcs - <pc0,pc1,...> list of PCs to compose 5834b9ad928SBarry Smith 5844b9ad928SBarry Smith Level: intermediate 5854b9ad928SBarry Smith 58695452b02SPatrick Sanan Notes: 587f1580f4eSBarry Smith To use a Krylov method inside the composite preconditioner, set the `PCType` of one or more 588f1580f4eSBarry Smith inner `PC`s to be `PCKSP`. Using a Krylov method inside another Krylov method can be dangerous (you get divergence or 589f1580f4eSBarry Smith the incorrect answer) unless you use `KSPFGMRES` as the outer Krylov method 590f1580f4eSBarry Smith 591f1580f4eSBarry Smith To use a different operator to construct one of the inner preconditioners first call `PCCompositeGetPC()`, then 592f1580f4eSBarry Smith call `PCSetOperators()` on that `PC`. 5934b9ad928SBarry Smith 594562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, 595db781477SPatrick Sanan `PCSHELL`, `PCKSP`, `PCCompositeSetType()`, `PCCompositeSpecialSetAlpha()`, `PCCompositeAddPCType()`, 596f1580f4eSBarry Smith `PCCompositeGetPC()`, `PCSetUseAmat()`, `PCCompositeAddPC()`, `PCCompositeGetNumberPC()` 5974b9ad928SBarry Smith M*/ 5984b9ad928SBarry Smith 599d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_Composite(PC pc) 600d71ae5a4SJacob Faibussowitsch { 6014b9ad928SBarry Smith PC_Composite *jac; 6024b9ad928SBarry Smith 6034b9ad928SBarry Smith PetscFunctionBegin; 6044dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&jac)); 6052fa5cd67SKarl Rupp 6064b9ad928SBarry Smith pc->ops->apply = PCApply_Composite_Additive; 6072533e041SBarry Smith pc->ops->applytranspose = PCApplyTranspose_Composite_Additive; 6084b9ad928SBarry Smith pc->ops->setup = PCSetUp_Composite; 6094f853519SStefano Zampini pc->ops->setuponblocks = PCSetUpOnBlocks_Composite; 61069d2c0f9SBarry Smith pc->ops->reset = PCReset_Composite; 6114b9ad928SBarry Smith pc->ops->destroy = PCDestroy_Composite; 6124b9ad928SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Composite; 6134b9ad928SBarry Smith pc->ops->view = PCView_Composite; 6140a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 6154b9ad928SBarry Smith 6164b9ad928SBarry Smith pc->data = (void *)jac; 6174b9ad928SBarry Smith jac->type = PC_COMPOSITE_ADDITIVE; 6180a545947SLisandro Dalcin jac->work1 = NULL; 6190a545947SLisandro Dalcin jac->work2 = NULL; 6200a545947SLisandro Dalcin jac->head = NULL; 6214b9ad928SBarry Smith 6229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSetType_C", PCCompositeSetType_Composite)); 6239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetType_C", PCCompositeGetType_Composite)); 6249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPCType_C", PCCompositeAddPCType_Composite)); 6259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeAddPC_C", PCCompositeAddPC_Composite)); 6269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetNumberPC_C", PCCompositeGetNumberPC_Composite)); 6279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeGetPC_C", PCCompositeGetPC_Composite)); 6289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCCompositeSpecialSetAlpha_C", PCCompositeSpecialSetAlpha_Composite)); 6293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6304b9ad928SBarry Smith } 631