xref: /petsc/src/ksp/pc/impls/galerkin/galerkin.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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 
16*9371c9d4SSatish 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 
35*9371c9d4SSatish 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 
68*9371c9d4SSatish 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 
80*9371c9d4SSatish 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 
90*9371c9d4SSatish 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 
104*9371c9d4SSatish 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 
112*9371c9d4SSatish 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 
122*9371c9d4SSatish 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 
132*9371c9d4SSatish 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 /* -------------------------------------------------------------------------------- */
1422a6744ebSBarry Smith /*@
1432a6744ebSBarry Smith    PCGalerkinSetRestriction - Sets the restriction operator for the "Galerkin-type" preconditioner
1442a6744ebSBarry Smith 
145ad4df100SBarry Smith    Logically Collective on PC
1462a6744ebSBarry Smith 
147d8d19677SJose E. Roman    Input Parameters:
1482a6744ebSBarry Smith +  pc - the preconditioner context
1492a6744ebSBarry Smith -  R - the restriction operator
1502a6744ebSBarry Smith 
15195452b02SPatrick Sanan    Notes:
15295452b02SPatrick Sanan     Either this or PCGalerkinSetInterpolation() or both must be called
1532a6744ebSBarry Smith 
1542a6744ebSBarry Smith    Level: Intermediate
1552a6744ebSBarry Smith 
156db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`,
157db781477SPatrick Sanan           `PCGalerkinSetInterpolation()`, `PCGalerkinGetKSP()`
1582a6744ebSBarry Smith 
1592a6744ebSBarry Smith @*/
160*9371c9d4SSatish Balay PetscErrorCode PCGalerkinSetRestriction(PC pc, Mat R) {
1612a6744ebSBarry Smith   PetscFunctionBegin;
1620700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
163cac4c232SBarry Smith   PetscTryMethod(pc, "PCGalerkinSetRestriction_C", (PC, Mat), (pc, R));
1642a6744ebSBarry Smith   PetscFunctionReturn(0);
1652a6744ebSBarry Smith }
1662a6744ebSBarry Smith 
1672a6744ebSBarry Smith /*@
1682a6744ebSBarry Smith    PCGalerkinSetInterpolation - Sets the interpolation operator for the "Galerkin-type" preconditioner
1692a6744ebSBarry Smith 
170ad4df100SBarry Smith    Logically Collective on PC
1712a6744ebSBarry Smith 
172d8d19677SJose E. Roman    Input Parameters:
1732a6744ebSBarry Smith +  pc - the preconditioner context
1742a6744ebSBarry Smith -  R - the interpolation operator
1752a6744ebSBarry Smith 
17695452b02SPatrick Sanan    Notes:
17795452b02SPatrick Sanan     Either this or PCGalerkinSetRestriction() or both must be called
1782a6744ebSBarry Smith 
1792a6744ebSBarry Smith    Level: Intermediate
1802a6744ebSBarry Smith 
181db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`,
182db781477SPatrick Sanan           `PCGalerkinSetRestriction()`, `PCGalerkinGetKSP()`
1832a6744ebSBarry Smith 
1842a6744ebSBarry Smith @*/
185*9371c9d4SSatish Balay PetscErrorCode PCGalerkinSetInterpolation(PC pc, Mat P) {
1862a6744ebSBarry Smith   PetscFunctionBegin;
1870700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
188cac4c232SBarry Smith   PetscTryMethod(pc, "PCGalerkinSetInterpolation_C", (PC, Mat), (pc, P));
1892a6744ebSBarry Smith   PetscFunctionReturn(0);
1902a6744ebSBarry Smith }
1912a6744ebSBarry Smith 
1922a6744ebSBarry Smith /*@
193b3402f20SBarry Smith    PCGalerkinSetComputeSubmatrix - Provide a routine that will be called to compute the Galerkin submatrix
194b3402f20SBarry Smith 
195b3402f20SBarry Smith    Logically Collective
196b3402f20SBarry Smith 
197d8d19677SJose E. Roman    Input Parameters:
198b3402f20SBarry Smith +  pc - the preconditioner context
199b3402f20SBarry Smith .  computeAsub - routine that computes the submatrix from the global matrix
200b3402f20SBarry Smith -  ctx - context used by the routine, or NULL
201b3402f20SBarry Smith 
202b3402f20SBarry Smith    Calling sequence of computeAsub:
203b3402f20SBarry Smith $    computeAsub(PC pc,Mat A, Mat Ap, Mat *cAP,void *ctx);
204b3402f20SBarry Smith 
205b3402f20SBarry Smith +  PC - the Galerkin PC
206b3402f20SBarry Smith .  A - the matrix in the Galerkin PC
207b3402f20SBarry Smith .  Ap - the computed submatrix from any previous computation, if NULL it has not previously been computed
208b3402f20SBarry Smith .  cAp - the submatrix computed by this routine
209b3402f20SBarry Smith -  ctx - optional user-defined function context
210b3402f20SBarry Smith 
211b3402f20SBarry Smith    Level: Intermediate
212b3402f20SBarry Smith 
21395452b02SPatrick Sanan    Notes:
21495452b02SPatrick Sanan     Instead of providing this routine you can call PCGalerkinGetKSP() and then KSPSetOperators() to provide the submatrix,
215b3402f20SBarry Smith           but that will not work for multiple KSPSolves with different matrices unless you call it for each solve.
216b3402f20SBarry Smith 
217910cf402Sprj-           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
218b3402f20SBarry Smith           matrix and computes its values in cAp. On each subsequent call the routine should up the Ap matrix.
219b3402f20SBarry Smith 
22095452b02SPatrick Sanan    Developer Notes:
22195452b02SPatrick Sanan     If the user does not call this routine nor call PCGalerkinGetKSP() and KSPSetOperators() then PCGalerkin could
222b3402f20SBarry Smith                     could automatically compute the submatrix via calls to MatGalerkin() or MatRARt()
223b3402f20SBarry Smith 
224db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`,
225db781477SPatrick Sanan           `PCGalerkinSetRestriction()`, `PCGalerkinSetInterpolation()`, `PCGalerkinGetKSP()`
226b3402f20SBarry Smith 
227b3402f20SBarry Smith @*/
228*9371c9d4SSatish Balay PetscErrorCode PCGalerkinSetComputeSubmatrix(PC pc, PetscErrorCode (*computeAsub)(PC, Mat, Mat, Mat *, void *), void *ctx) {
229b3402f20SBarry Smith   PetscFunctionBegin;
230b3402f20SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
231cac4c232SBarry Smith   PetscTryMethod(pc, "PCGalerkinSetComputeSubmatrix_C", (PC, PetscErrorCode(*)(PC, Mat, Mat, Mat *, void *), void *), (pc, computeAsub, ctx));
232b3402f20SBarry Smith   PetscFunctionReturn(0);
233b3402f20SBarry Smith }
234b3402f20SBarry Smith 
235b3402f20SBarry Smith /*@
2362a6744ebSBarry Smith    PCGalerkinGetKSP - Gets the KSP object in the Galerkin PC.
2372a6744ebSBarry Smith 
2382a6744ebSBarry Smith    Not Collective
2392a6744ebSBarry Smith 
2402a6744ebSBarry Smith    Input Parameter:
2412a6744ebSBarry Smith .  pc - the preconditioner context
2422a6744ebSBarry Smith 
2432a6744ebSBarry Smith    Output Parameters:
2442a6744ebSBarry Smith .  ksp - the KSP object
2452a6744ebSBarry Smith 
2462a6744ebSBarry Smith    Level: Intermediate
2472a6744ebSBarry Smith 
24895452b02SPatrick Sanan    Notes:
24995452b02SPatrick Sanan     Once you have called this routine you can call KSPSetOperators() on the resulting ksp to provide the operator for the Galerkin problem,
250b3402f20SBarry Smith           an alternative is to use PCGalerkinSetComputeSubmatrix() to provide a routine that computes the submatrix as needed.
251b3402f20SBarry Smith 
252db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`,
253db781477SPatrick Sanan           `PCGalerkinSetRestriction()`, `PCGalerkinSetInterpolation()`, `PCGalerkinSetComputeSubmatrix()`
2542a6744ebSBarry Smith 
2552a6744ebSBarry Smith @*/
256*9371c9d4SSatish Balay PetscErrorCode PCGalerkinGetKSP(PC pc, KSP *ksp) {
2572a6744ebSBarry Smith   PetscFunctionBegin;
2580700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2592a6744ebSBarry Smith   PetscValidPointer(ksp, 2);
260cac4c232SBarry Smith   PetscUseMethod(pc, "PCGalerkinGetKSP_C", (PC, KSP *), (pc, ksp));
2612a6744ebSBarry Smith   PetscFunctionReturn(0);
2622a6744ebSBarry Smith }
2632a6744ebSBarry Smith 
264*9371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_Galerkin(PC pc, PetscOptionItems *PetscOptionsObject) {
2654ac220ccSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
2664ac220ccSBarry Smith   const char  *prefix;
2674ac220ccSBarry Smith   PetscBool    flg;
2684ac220ccSBarry Smith 
2694ac220ccSBarry Smith   PetscFunctionBegin;
2709566063dSJacob Faibussowitsch   PetscCall(KSPGetOptionsPrefix(jac->ksp, &prefix));
2719566063dSJacob Faibussowitsch   PetscCall(PetscStrendswith(prefix, "galerkin_", &flg));
2724ac220ccSBarry Smith   if (!flg) {
2739566063dSJacob Faibussowitsch     PetscCall(PCGetOptionsPrefix(pc, &prefix));
2749566063dSJacob Faibussowitsch     PetscCall(KSPSetOptionsPrefix(jac->ksp, prefix));
2759566063dSJacob Faibussowitsch     PetscCall(KSPAppendOptionsPrefix(jac->ksp, "galerkin_"));
2764ac220ccSBarry Smith   }
2774ac220ccSBarry Smith 
278d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "Galerkin options");
2791baa6e33SBarry Smith   if (jac->ksp) PetscCall(KSPSetFromOptions(jac->ksp));
280d0609cedSBarry Smith   PetscOptionsHeadEnd();
2814ac220ccSBarry Smith   PetscFunctionReturn(0);
2824ac220ccSBarry Smith }
2832a6744ebSBarry Smith 
2842a6744ebSBarry Smith /* -------------------------------------------------------------------------------------------*/
2852a6744ebSBarry Smith 
2862a6744ebSBarry Smith /*MC
2872a6744ebSBarry Smith      PCGALERKIN - Build (part of) a preconditioner by P S R (where P is often R^T)
2882a6744ebSBarry Smith 
2892a6744ebSBarry Smith $   Use PCGalerkinSetRestriction(pc,R) and/or PCGalerkinSetInterpolation(pc,P) followed by
2907817a140SBarry Smith $   PCGalerkinGetKSP(pc,&ksp); KSPSetOperators(ksp,A,....)
2912a6744ebSBarry Smith 
2922a6744ebSBarry Smith    Level: intermediate
2932a6744ebSBarry Smith 
294b59c8b46SBarry Smith    Developer Note: If KSPSetOperators() has not been called on the inner KSP then PCGALERKIN could use MatRARt() or MatPtAP() to compute
2957817a140SBarry Smith                    the operators automatically.
2967817a140SBarry Smith                    Should there be a prefix for the inner KSP.
2977817a140SBarry Smith                    There is no KSPSetFromOptions_Galerkin() that calls KSPSetFromOptions() on the inner KSP
2987817a140SBarry Smith 
299db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`,
300db781477SPatrick Sanan           `PCSHELL`, `PCKSP`, `PCGalerkinSetRestriction()`, `PCGalerkinSetInterpolation()`, `PCGalerkinGetKSP()`
3012a6744ebSBarry Smith 
3022a6744ebSBarry Smith M*/
3032a6744ebSBarry Smith 
304*9371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_Galerkin(PC pc) {
3052a6744ebSBarry Smith   PC_Galerkin *jac;
3062a6744ebSBarry Smith 
3072a6744ebSBarry Smith   PetscFunctionBegin;
3089566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc, &jac));
3092fa5cd67SKarl Rupp 
3102a6744ebSBarry Smith   pc->ops->apply           = PCApply_Galerkin;
3112a6744ebSBarry Smith   pc->ops->setup           = PCSetUp_Galerkin;
312a06653b4SBarry Smith   pc->ops->reset           = PCReset_Galerkin;
3132a6744ebSBarry Smith   pc->ops->destroy         = PCDestroy_Galerkin;
3142a6744ebSBarry Smith   pc->ops->view            = PCView_Galerkin;
3154ac220ccSBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_Galerkin;
3164ac220ccSBarry Smith   pc->ops->applyrichardson = NULL;
3172a6744ebSBarry Smith 
3189566063dSJacob Faibussowitsch   PetscCall(KSPCreate(PetscObjectComm((PetscObject)pc), &jac->ksp));
3199566063dSJacob Faibussowitsch   PetscCall(KSPSetErrorIfNotConverged(jac->ksp, pc->erroriffailure));
3209566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)jac->ksp, (PetscObject)pc, 1));
3212a6744ebSBarry Smith 
3222a6744ebSBarry Smith   pc->data = (void *)jac;
3232a6744ebSBarry Smith 
3249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinSetRestriction_C", PCGalerkinSetRestriction_Galerkin));
3259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinSetInterpolation_C", PCGalerkinSetInterpolation_Galerkin));
3269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinGetKSP_C", PCGalerkinGetKSP_Galerkin));
3279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinSetComputeSubmatrix_C", PCGalerkinSetComputeSubmatrix_Galerkin));
3282a6744ebSBarry Smith   PetscFunctionReturn(0);
3292a6744ebSBarry Smith }
330