xref: /petsc/src/ksp/pc/impls/galerkin/galerkin.c (revision f1580f4e3ce5d5b2393648fd039d0d41b440385d)
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