12a6744ebSBarry Smith 22a6744ebSBarry Smith /* 32a6744ebSBarry Smith Defines a preconditioner defined by R^T S R 42a6744ebSBarry Smith */ 5af0996ceSBarry Smith #include <petsc/private/pcimpl.h> 6c6db04a5SJed Brown #include <petscksp.h> /*I "petscksp.h" I*/ 72a6744ebSBarry Smith 82a6744ebSBarry Smith typedef struct { 92a6744ebSBarry Smith KSP ksp; 102a6744ebSBarry Smith Mat R, P; 112a6744ebSBarry Smith Vec b, x; 12b3402f20SBarry Smith PetscErrorCode (*computeasub)(PC, Mat, Mat, Mat *, void *); 13b3402f20SBarry Smith void *computeasub_ctx; 142a6744ebSBarry Smith } PC_Galerkin; 152a6744ebSBarry Smith 169371c9d4SSatish Balay static PetscErrorCode PCApply_Galerkin(PC pc, Vec x, Vec y) { 172a6744ebSBarry Smith PC_Galerkin *jac = (PC_Galerkin *)pc->data; 182a6744ebSBarry Smith 192a6744ebSBarry Smith PetscFunctionBegin; 202fa5cd67SKarl Rupp if (jac->R) { 219566063dSJacob Faibussowitsch PetscCall(MatRestrict(jac->R, x, jac->b)); 222fa5cd67SKarl Rupp } else { 239566063dSJacob Faibussowitsch PetscCall(MatRestrict(jac->P, x, jac->b)); 242fa5cd67SKarl Rupp } 259566063dSJacob Faibussowitsch PetscCall(KSPSolve(jac->ksp, jac->b, jac->x)); 269566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(jac->ksp, pc, jac->x)); 272fa5cd67SKarl Rupp if (jac->P) { 289566063dSJacob Faibussowitsch PetscCall(MatInterpolate(jac->P, jac->x, y)); 292fa5cd67SKarl Rupp } else { 309566063dSJacob Faibussowitsch PetscCall(MatInterpolate(jac->R, jac->x, y)); 312fa5cd67SKarl Rupp } 322a6744ebSBarry Smith PetscFunctionReturn(0); 332a6744ebSBarry Smith } 342a6744ebSBarry Smith 359371c9d4SSatish Balay static PetscErrorCode PCSetUp_Galerkin(PC pc) { 362a6744ebSBarry Smith PC_Galerkin *jac = (PC_Galerkin *)pc->data; 37ace3abfcSBarry Smith PetscBool a; 38906ed7ccSBarry Smith Vec *xx, *yy; 392a6744ebSBarry Smith 402a6744ebSBarry Smith PetscFunctionBegin; 41b3402f20SBarry Smith if (jac->computeasub) { 42b3402f20SBarry Smith Mat Ap; 43b3402f20SBarry Smith if (!pc->setupcalled) { 449566063dSJacob Faibussowitsch PetscCall((*jac->computeasub)(pc, pc->pmat, NULL, &Ap, jac->computeasub_ctx)); 459566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(jac->ksp, Ap, Ap)); 469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ap)); 47b3402f20SBarry Smith } else { 489566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(jac->ksp, NULL, &Ap)); 499566063dSJacob Faibussowitsch PetscCall((*jac->computeasub)(pc, pc->pmat, Ap, NULL, jac->computeasub_ctx)); 50b3402f20SBarry Smith } 51b3402f20SBarry Smith } 52b3402f20SBarry Smith 532a6744ebSBarry Smith if (!jac->x) { 549566063dSJacob Faibussowitsch PetscCall(KSPGetOperatorsSet(jac->ksp, &a, NULL)); 5528b400f6SJacob Faibussowitsch PetscCheck(a, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set operator of PCGALERKIN KSP with PCGalerkinGetKSP()/KSPSetOperators()"); 569566063dSJacob Faibussowitsch PetscCall(KSPCreateVecs(jac->ksp, 1, &xx, 1, &yy)); 57906ed7ccSBarry Smith jac->x = *xx; 58906ed7ccSBarry Smith jac->b = *yy; 599566063dSJacob Faibussowitsch PetscCall(PetscFree(xx)); 609566063dSJacob Faibussowitsch PetscCall(PetscFree(yy)); 612a6744ebSBarry Smith } 627827d75bSBarry Smith PetscCheck(jac->R || jac->P, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set restriction or interpolation of PCGALERKIN with PCGalerkinSetRestriction()/Interpolation()"); 632a6744ebSBarry Smith /* should check here that sizes of R/P match size of a */ 64b3402f20SBarry Smith 652a6744ebSBarry Smith PetscFunctionReturn(0); 662a6744ebSBarry Smith } 672a6744ebSBarry Smith 689371c9d4SSatish Balay static PetscErrorCode PCReset_Galerkin(PC pc) { 692a6744ebSBarry Smith PC_Galerkin *jac = (PC_Galerkin *)pc->data; 702a6744ebSBarry Smith 712a6744ebSBarry Smith PetscFunctionBegin; 729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&jac->R)); 739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&jac->P)); 749566063dSJacob Faibussowitsch PetscCall(VecDestroy(&jac->x)); 759566063dSJacob Faibussowitsch PetscCall(VecDestroy(&jac->b)); 769566063dSJacob Faibussowitsch PetscCall(KSPReset(jac->ksp)); 77a06653b4SBarry Smith PetscFunctionReturn(0); 78a06653b4SBarry Smith } 79a06653b4SBarry Smith 809371c9d4SSatish Balay static PetscErrorCode PCDestroy_Galerkin(PC pc) { 81a06653b4SBarry Smith PC_Galerkin *jac = (PC_Galerkin *)pc->data; 82a06653b4SBarry Smith 83a06653b4SBarry Smith PetscFunctionBegin; 849566063dSJacob Faibussowitsch PetscCall(PCReset_Galerkin(pc)); 859566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&jac->ksp)); 869566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 872a6744ebSBarry Smith PetscFunctionReturn(0); 882a6744ebSBarry Smith } 892a6744ebSBarry Smith 909371c9d4SSatish Balay static PetscErrorCode PCView_Galerkin(PC pc, PetscViewer viewer) { 912a6744ebSBarry Smith PC_Galerkin *jac = (PC_Galerkin *)pc->data; 92ace3abfcSBarry Smith PetscBool iascii; 932a6744ebSBarry Smith 942a6744ebSBarry Smith PetscFunctionBegin; 959566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 962a6744ebSBarry Smith if (iascii) { 979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " KSP on Galerkin follow\n")); 989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " ---------------------------------\n")); 992a6744ebSBarry Smith } 1009566063dSJacob Faibussowitsch PetscCall(KSPView(jac->ksp, viewer)); 1012a6744ebSBarry Smith PetscFunctionReturn(0); 1022a6744ebSBarry Smith } 1032a6744ebSBarry Smith 1049371c9d4SSatish Balay static PetscErrorCode PCGalerkinGetKSP_Galerkin(PC pc, KSP *ksp) { 1052a6744ebSBarry Smith PC_Galerkin *jac = (PC_Galerkin *)pc->data; 1062a6744ebSBarry Smith 1072a6744ebSBarry Smith PetscFunctionBegin; 1082a6744ebSBarry Smith *ksp = jac->ksp; 1092a6744ebSBarry Smith PetscFunctionReturn(0); 1102a6744ebSBarry Smith } 1112a6744ebSBarry Smith 1129371c9d4SSatish Balay static PetscErrorCode PCGalerkinSetRestriction_Galerkin(PC pc, Mat R) { 1132a6744ebSBarry Smith PC_Galerkin *jac = (PC_Galerkin *)pc->data; 1142a6744ebSBarry Smith 1152a6744ebSBarry Smith PetscFunctionBegin; 1169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)R)); 1179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&jac->R)); 1182a6744ebSBarry Smith jac->R = R; 1192a6744ebSBarry Smith PetscFunctionReturn(0); 1202a6744ebSBarry Smith } 1212a6744ebSBarry Smith 1229371c9d4SSatish Balay static PetscErrorCode PCGalerkinSetInterpolation_Galerkin(PC pc, Mat P) { 1232a6744ebSBarry Smith PC_Galerkin *jac = (PC_Galerkin *)pc->data; 1242a6744ebSBarry Smith 1252a6744ebSBarry Smith PetscFunctionBegin; 1269566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)P)); 1279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&jac->P)); 1282a6744ebSBarry Smith jac->P = P; 1292a6744ebSBarry Smith PetscFunctionReturn(0); 1302a6744ebSBarry Smith } 1312a6744ebSBarry Smith 1329371c9d4SSatish Balay static PetscErrorCode PCGalerkinSetComputeSubmatrix_Galerkin(PC pc, PetscErrorCode (*computeAsub)(PC, Mat, Mat, Mat *, void *), void *ctx) { 133b3402f20SBarry Smith PC_Galerkin *jac = (PC_Galerkin *)pc->data; 134b3402f20SBarry Smith 135b3402f20SBarry Smith PetscFunctionBegin; 136b3402f20SBarry Smith jac->computeasub = computeAsub; 137b3402f20SBarry Smith jac->computeasub_ctx = ctx; 138b3402f20SBarry Smith PetscFunctionReturn(0); 139b3402f20SBarry Smith } 140b3402f20SBarry Smith 1412a6744ebSBarry Smith /*@ 142*f1580f4eSBarry Smith PCGalerkinSetRestriction - Sets the restriction operator for the `PCGALERKIN` preconditioner 1432a6744ebSBarry Smith 144*f1580f4eSBarry Smith Logically Collective on pc 1452a6744ebSBarry Smith 146d8d19677SJose E. Roman Input Parameters: 1472a6744ebSBarry Smith + pc - the preconditioner context 1482a6744ebSBarry Smith - R - the restriction operator 1492a6744ebSBarry Smith 150*f1580f4eSBarry Smith Note: 151*f1580f4eSBarry Smith Either this or `PCGalerkinSetInterpolation()` or both must be called 1522a6744ebSBarry Smith 1532a6744ebSBarry Smith Level: Intermediate 1542a6744ebSBarry Smith 155db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`, 156db781477SPatrick Sanan `PCGalerkinSetInterpolation()`, `PCGalerkinGetKSP()` 1572a6744ebSBarry Smith @*/ 1589371c9d4SSatish Balay PetscErrorCode PCGalerkinSetRestriction(PC pc, Mat R) { 1592a6744ebSBarry Smith PetscFunctionBegin; 1600700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 161cac4c232SBarry Smith PetscTryMethod(pc, "PCGalerkinSetRestriction_C", (PC, Mat), (pc, R)); 1622a6744ebSBarry Smith PetscFunctionReturn(0); 1632a6744ebSBarry Smith } 1642a6744ebSBarry Smith 1652a6744ebSBarry Smith /*@ 166*f1580f4eSBarry Smith PCGalerkinSetInterpolation - Sets the interpolation operator for the `PCGALERKIN` preconditioner 1672a6744ebSBarry Smith 168*f1580f4eSBarry Smith Logically Collective on pc 1692a6744ebSBarry Smith 170d8d19677SJose E. Roman Input Parameters: 1712a6744ebSBarry Smith + pc - the preconditioner context 1722a6744ebSBarry Smith - R - the interpolation operator 1732a6744ebSBarry Smith 174*f1580f4eSBarry Smith Note: 175*f1580f4eSBarry Smith Either this or `PCGalerkinSetRestriction()` or both must be called 1762a6744ebSBarry Smith 1772a6744ebSBarry Smith Level: Intermediate 1782a6744ebSBarry Smith 179db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`, 180db781477SPatrick Sanan `PCGalerkinSetRestriction()`, `PCGalerkinGetKSP()` 1812a6744ebSBarry Smith @*/ 1829371c9d4SSatish Balay PetscErrorCode PCGalerkinSetInterpolation(PC pc, Mat P) { 1832a6744ebSBarry Smith PetscFunctionBegin; 1840700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 185cac4c232SBarry Smith PetscTryMethod(pc, "PCGalerkinSetInterpolation_C", (PC, Mat), (pc, P)); 1862a6744ebSBarry Smith PetscFunctionReturn(0); 1872a6744ebSBarry Smith } 1882a6744ebSBarry Smith 1892a6744ebSBarry Smith /*@ 190b3402f20SBarry Smith PCGalerkinSetComputeSubmatrix - Provide a routine that will be called to compute the Galerkin submatrix 191b3402f20SBarry Smith 192b3402f20SBarry Smith Logically Collective 193b3402f20SBarry Smith 194d8d19677SJose E. Roman Input Parameters: 195b3402f20SBarry Smith + pc - the preconditioner context 196b3402f20SBarry Smith . computeAsub - routine that computes the submatrix from the global matrix 197b3402f20SBarry Smith - ctx - context used by the routine, or NULL 198b3402f20SBarry Smith 199b3402f20SBarry Smith Calling sequence of computeAsub: 200b3402f20SBarry Smith $ computeAsub(PC pc,Mat A, Mat Ap, Mat *cAP,void *ctx); 201b3402f20SBarry Smith 202*f1580f4eSBarry Smith + PC - the `PCGALERKIN` 203*f1580f4eSBarry Smith . A - the matrix in the `PCGALERKIN` 204b3402f20SBarry Smith . Ap - the computed submatrix from any previous computation, if NULL it has not previously been computed 205b3402f20SBarry Smith . cAp - the submatrix computed by this routine 206b3402f20SBarry Smith - ctx - optional user-defined function context 207b3402f20SBarry Smith 208b3402f20SBarry Smith Level: Intermediate 209b3402f20SBarry Smith 21095452b02SPatrick Sanan Notes: 211*f1580f4eSBarry Smith Instead of providing this routine you can call `PCGalerkinGetKSP()` and then `KSPSetOperators()` to provide the submatrix, 212*f1580f4eSBarry Smith but that will not work for multiple `KSPSolve()`s with different matrices unless you call it for each solve. 213b3402f20SBarry Smith 214910cf402Sprj- This routine is called each time the outer matrix is changed. In the first call the Ap argument is NULL and the routine should create the 215b3402f20SBarry Smith matrix and computes its values in cAp. On each subsequent call the routine should up the Ap matrix. 216b3402f20SBarry Smith 217*f1580f4eSBarry Smith Developer Note: 218*f1580f4eSBarry Smith If the user does not call this routine nor call `PCGalerkinGetKSP()` and `KSPSetOperators()` then `PCGALERKIN` 219*f1580f4eSBarry Smith could automatically compute the submatrix via calls to `MatGalerkin()` or `MatRARt()` 220b3402f20SBarry Smith 221db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`, 222db781477SPatrick Sanan `PCGalerkinSetRestriction()`, `PCGalerkinSetInterpolation()`, `PCGalerkinGetKSP()` 223b3402f20SBarry Smith @*/ 2249371c9d4SSatish Balay PetscErrorCode PCGalerkinSetComputeSubmatrix(PC pc, PetscErrorCode (*computeAsub)(PC, Mat, Mat, Mat *, void *), void *ctx) { 225b3402f20SBarry Smith PetscFunctionBegin; 226b3402f20SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 227cac4c232SBarry Smith PetscTryMethod(pc, "PCGalerkinSetComputeSubmatrix_C", (PC, PetscErrorCode(*)(PC, Mat, Mat, Mat *, void *), void *), (pc, computeAsub, ctx)); 228b3402f20SBarry Smith PetscFunctionReturn(0); 229b3402f20SBarry Smith } 230b3402f20SBarry Smith 231b3402f20SBarry Smith /*@ 232*f1580f4eSBarry Smith PCGalerkinGetKSP - Gets the `KSP` object in the `PCGALERKIN` 2332a6744ebSBarry Smith 2342a6744ebSBarry Smith Not Collective 2352a6744ebSBarry Smith 2362a6744ebSBarry Smith Input Parameter: 2372a6744ebSBarry Smith . pc - the preconditioner context 2382a6744ebSBarry Smith 239*f1580f4eSBarry Smith Output Parameter: 240*f1580f4eSBarry Smith . ksp - the `KSP` object 2412a6744ebSBarry Smith 2422a6744ebSBarry Smith Level: Intermediate 2432a6744ebSBarry Smith 244*f1580f4eSBarry Smith Note: 245*f1580f4eSBarry Smith Once you have called this routine you can call `KSPSetOperators()` on the resulting ksp to provide the operator for the Galerkin problem, 246*f1580f4eSBarry Smith an alternative is to use `PCGalerkinSetComputeSubmatrix()` to provide a routine that computes the submatrix as needed. 247b3402f20SBarry Smith 248db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`, 249db781477SPatrick Sanan `PCGalerkinSetRestriction()`, `PCGalerkinSetInterpolation()`, `PCGalerkinSetComputeSubmatrix()` 2502a6744ebSBarry Smith @*/ 2519371c9d4SSatish Balay PetscErrorCode PCGalerkinGetKSP(PC pc, KSP *ksp) { 2522a6744ebSBarry Smith PetscFunctionBegin; 2530700a824SBarry Smith PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 2542a6744ebSBarry Smith PetscValidPointer(ksp, 2); 255cac4c232SBarry Smith PetscUseMethod(pc, "PCGalerkinGetKSP_C", (PC, KSP *), (pc, ksp)); 2562a6744ebSBarry Smith PetscFunctionReturn(0); 2572a6744ebSBarry Smith } 2582a6744ebSBarry Smith 2599371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_Galerkin(PC pc, PetscOptionItems *PetscOptionsObject) { 2604ac220ccSBarry Smith PC_Galerkin *jac = (PC_Galerkin *)pc->data; 2614ac220ccSBarry Smith const char *prefix; 2624ac220ccSBarry Smith PetscBool flg; 2634ac220ccSBarry Smith 2644ac220ccSBarry Smith PetscFunctionBegin; 2659566063dSJacob Faibussowitsch PetscCall(KSPGetOptionsPrefix(jac->ksp, &prefix)); 2669566063dSJacob Faibussowitsch PetscCall(PetscStrendswith(prefix, "galerkin_", &flg)); 2674ac220ccSBarry Smith if (!flg) { 2689566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix)); 2699566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(jac->ksp, prefix)); 2709566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(jac->ksp, "galerkin_")); 2714ac220ccSBarry Smith } 2724ac220ccSBarry Smith 273d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Galerkin options"); 2741baa6e33SBarry Smith if (jac->ksp) PetscCall(KSPSetFromOptions(jac->ksp)); 275d0609cedSBarry Smith PetscOptionsHeadEnd(); 2764ac220ccSBarry Smith PetscFunctionReturn(0); 2774ac220ccSBarry Smith } 2782a6744ebSBarry Smith 2792a6744ebSBarry Smith /*MC 2802a6744ebSBarry Smith PCGALERKIN - Build (part of) a preconditioner by P S R (where P is often R^T) 2812a6744ebSBarry Smith 282*f1580f4eSBarry Smith Use `PCGalerkinSetRestriction`(pc,R) and/or `PCGalerkinSetInterpolation`(pc,P) followed by `PCGalerkinGetKSP`(pc,&ksp); `KSPSetOperators`(ksp,A,....) 2832a6744ebSBarry Smith 2842a6744ebSBarry Smith Level: intermediate 2852a6744ebSBarry Smith 286*f1580f4eSBarry Smith Developer Notes: 287*f1580f4eSBarry Smith If `KSPSetOperators()` has not been called on the inner `KSP` then `PCGALERKIN` could use `MatRARt()` or `MatPtAP()` to compute 2887817a140SBarry Smith the operators automatically. 289*f1580f4eSBarry Smith 290*f1580f4eSBarry Smith Should there be a prefix for the inner `KSP`? 291*f1580f4eSBarry Smith 292*f1580f4eSBarry Smith There is no `KSPSetFromOptions_Galerkin()` that calls `KSPSetFromOptions()` on the inner `KSP` 2937817a140SBarry Smith 294db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, 295db781477SPatrick Sanan `PCSHELL`, `PCKSP`, `PCGalerkinSetRestriction()`, `PCGalerkinSetInterpolation()`, `PCGalerkinGetKSP()` 2962a6744ebSBarry Smith M*/ 2972a6744ebSBarry Smith 2989371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_Galerkin(PC pc) { 2992a6744ebSBarry Smith PC_Galerkin *jac; 3002a6744ebSBarry Smith 3012a6744ebSBarry Smith PetscFunctionBegin; 3029566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc, &jac)); 3032fa5cd67SKarl Rupp 3042a6744ebSBarry Smith pc->ops->apply = PCApply_Galerkin; 3052a6744ebSBarry Smith pc->ops->setup = PCSetUp_Galerkin; 306a06653b4SBarry Smith pc->ops->reset = PCReset_Galerkin; 3072a6744ebSBarry Smith pc->ops->destroy = PCDestroy_Galerkin; 3082a6744ebSBarry Smith pc->ops->view = PCView_Galerkin; 3094ac220ccSBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Galerkin; 3104ac220ccSBarry Smith pc->ops->applyrichardson = NULL; 3112a6744ebSBarry Smith 3129566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)pc), &jac->ksp)); 3139566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(jac->ksp, pc->erroriffailure)); 3149566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)jac->ksp, (PetscObject)pc, 1)); 3152a6744ebSBarry Smith 3162a6744ebSBarry Smith pc->data = (void *)jac; 3172a6744ebSBarry Smith 3189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinSetRestriction_C", PCGalerkinSetRestriction_Galerkin)); 3199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinSetInterpolation_C", PCGalerkinSetInterpolation_Galerkin)); 3209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinGetKSP_C", PCGalerkinGetKSP_Galerkin)); 3219566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinSetComputeSubmatrix_C", PCGalerkinSetComputeSubmatrix_Galerkin)); 3222a6744ebSBarry Smith PetscFunctionReturn(0); 3232a6744ebSBarry Smith } 324