xref: /petsc/src/ksp/pc/impls/galerkin/galerkin.c (revision 562efe2ef922487c6beae96ba39e19afd4eefbe6)
12a6744ebSBarry Smith /*
22a6744ebSBarry Smith       Defines a preconditioner defined by R^T S R
32a6744ebSBarry Smith */
4af0996ceSBarry Smith #include <petsc/private/pcimpl.h>
5c6db04a5SJed Brown #include <petscksp.h> /*I "petscksp.h" I*/
62a6744ebSBarry Smith 
72a6744ebSBarry Smith typedef struct {
82a6744ebSBarry Smith   KSP ksp;
92a6744ebSBarry Smith   Mat R, P;
102a6744ebSBarry Smith   Vec b, x;
11b3402f20SBarry Smith   PetscErrorCode (*computeasub)(PC, Mat, Mat, Mat *, void *);
12b3402f20SBarry Smith   void *computeasub_ctx;
132a6744ebSBarry Smith } PC_Galerkin;
142a6744ebSBarry Smith 
15d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_Galerkin(PC pc, Vec x, Vec y)
16d71ae5a4SJacob Faibussowitsch {
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   }
323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
332a6744ebSBarry Smith }
342a6744ebSBarry Smith 
35d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_Galerkin(PC pc)
36d71ae5a4SJacob Faibussowitsch {
372a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
38ace3abfcSBarry Smith   PetscBool    a;
39906ed7ccSBarry Smith   Vec         *xx, *yy;
402a6744ebSBarry Smith 
412a6744ebSBarry Smith   PetscFunctionBegin;
42b3402f20SBarry Smith   if (jac->computeasub) {
43b3402f20SBarry Smith     Mat Ap;
44b3402f20SBarry Smith     if (!pc->setupcalled) {
459566063dSJacob Faibussowitsch       PetscCall((*jac->computeasub)(pc, pc->pmat, NULL, &Ap, jac->computeasub_ctx));
469566063dSJacob Faibussowitsch       PetscCall(KSPSetOperators(jac->ksp, Ap, Ap));
479566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Ap));
48b3402f20SBarry Smith     } else {
499566063dSJacob Faibussowitsch       PetscCall(KSPGetOperators(jac->ksp, NULL, &Ap));
509566063dSJacob Faibussowitsch       PetscCall((*jac->computeasub)(pc, pc->pmat, Ap, NULL, jac->computeasub_ctx));
51b3402f20SBarry Smith     }
52b3402f20SBarry Smith   }
53b3402f20SBarry Smith 
542a6744ebSBarry Smith   if (!jac->x) {
559566063dSJacob Faibussowitsch     PetscCall(KSPGetOperatorsSet(jac->ksp, &a, NULL));
5628b400f6SJacob Faibussowitsch     PetscCheck(a, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set operator of PCGALERKIN KSP with PCGalerkinGetKSP()/KSPSetOperators()");
579566063dSJacob Faibussowitsch     PetscCall(KSPCreateVecs(jac->ksp, 1, &xx, 1, &yy));
58906ed7ccSBarry Smith     jac->x = *xx;
59906ed7ccSBarry Smith     jac->b = *yy;
609566063dSJacob Faibussowitsch     PetscCall(PetscFree(xx));
619566063dSJacob Faibussowitsch     PetscCall(PetscFree(yy));
622a6744ebSBarry Smith   }
637827d75bSBarry Smith   PetscCheck(jac->R || jac->P, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set restriction or interpolation of PCGALERKIN with PCGalerkinSetRestriction()/Interpolation()");
642a6744ebSBarry Smith   /* should check here that sizes of R/P match size of a */
65b3402f20SBarry Smith 
663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
672a6744ebSBarry Smith }
682a6744ebSBarry Smith 
69d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_Galerkin(PC pc)
70d71ae5a4SJacob Faibussowitsch {
712a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
722a6744ebSBarry Smith 
732a6744ebSBarry Smith   PetscFunctionBegin;
749566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->R));
759566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->P));
769566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->x));
779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->b));
789566063dSJacob Faibussowitsch   PetscCall(KSPReset(jac->ksp));
793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80a06653b4SBarry Smith }
81a06653b4SBarry Smith 
82d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_Galerkin(PC pc)
83d71ae5a4SJacob Faibussowitsch {
84a06653b4SBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
85a06653b4SBarry Smith 
86a06653b4SBarry Smith   PetscFunctionBegin;
879566063dSJacob Faibussowitsch   PetscCall(PCReset_Galerkin(pc));
889566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&jac->ksp));
899566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
912a6744ebSBarry Smith }
922a6744ebSBarry Smith 
93d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_Galerkin(PC pc, PetscViewer viewer)
94d71ae5a4SJacob Faibussowitsch {
952a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
96ace3abfcSBarry Smith   PetscBool    iascii;
972a6744ebSBarry Smith 
982a6744ebSBarry Smith   PetscFunctionBegin;
999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1002a6744ebSBarry Smith   if (iascii) {
1019566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  KSP on Galerkin follow\n"));
1029566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------------------------------\n"));
1032a6744ebSBarry Smith   }
1049566063dSJacob Faibussowitsch   PetscCall(KSPView(jac->ksp, viewer));
1053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1062a6744ebSBarry Smith }
1072a6744ebSBarry Smith 
108d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGalerkinGetKSP_Galerkin(PC pc, KSP *ksp)
109d71ae5a4SJacob Faibussowitsch {
1102a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
1112a6744ebSBarry Smith 
1122a6744ebSBarry Smith   PetscFunctionBegin;
1132a6744ebSBarry Smith   *ksp = jac->ksp;
1143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1152a6744ebSBarry Smith }
1162a6744ebSBarry Smith 
117d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGalerkinSetRestriction_Galerkin(PC pc, Mat R)
118d71ae5a4SJacob Faibussowitsch {
1192a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
1202a6744ebSBarry Smith 
1212a6744ebSBarry Smith   PetscFunctionBegin;
1229566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)R));
1239566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->R));
1242a6744ebSBarry Smith   jac->R = R;
1253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1262a6744ebSBarry Smith }
1272a6744ebSBarry Smith 
128d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGalerkinSetInterpolation_Galerkin(PC pc, Mat P)
129d71ae5a4SJacob Faibussowitsch {
1302a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
1312a6744ebSBarry Smith 
1322a6744ebSBarry Smith   PetscFunctionBegin;
1339566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)P));
1349566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->P));
1352a6744ebSBarry Smith   jac->P = P;
1363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1372a6744ebSBarry Smith }
1382a6744ebSBarry Smith 
139d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGalerkinSetComputeSubmatrix_Galerkin(PC pc, PetscErrorCode (*computeAsub)(PC, Mat, Mat, Mat *, void *), void *ctx)
140d71ae5a4SJacob Faibussowitsch {
141b3402f20SBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
142b3402f20SBarry Smith 
143b3402f20SBarry Smith   PetscFunctionBegin;
144b3402f20SBarry Smith   jac->computeasub     = computeAsub;
145b3402f20SBarry Smith   jac->computeasub_ctx = ctx;
1463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
147b3402f20SBarry Smith }
148b3402f20SBarry Smith 
1492a6744ebSBarry Smith /*@
150f1580f4eSBarry Smith   PCGalerkinSetRestriction - Sets the restriction operator for the `PCGALERKIN` preconditioner
1512a6744ebSBarry Smith 
152c3339decSBarry Smith   Logically Collective
1532a6744ebSBarry Smith 
154d8d19677SJose E. Roman   Input Parameters:
1552a6744ebSBarry Smith + pc - the preconditioner context
1562a6744ebSBarry Smith - R  - the restriction operator
1572a6744ebSBarry Smith 
158feefa0e1SJacob Faibussowitsch   Level: intermediate
15920f4b53cSBarry Smith 
160f1580f4eSBarry Smith   Note:
161f1580f4eSBarry Smith   Either this or `PCGalerkinSetInterpolation()` or both must be called
1622a6744ebSBarry Smith 
163*562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`,
164db781477SPatrick Sanan           `PCGalerkinSetInterpolation()`, `PCGalerkinGetKSP()`
1652a6744ebSBarry Smith @*/
166d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGalerkinSetRestriction(PC pc, Mat R)
167d71ae5a4SJacob Faibussowitsch {
1682a6744ebSBarry Smith   PetscFunctionBegin;
1690700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
170cac4c232SBarry Smith   PetscTryMethod(pc, "PCGalerkinSetRestriction_C", (PC, Mat), (pc, R));
1713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1722a6744ebSBarry Smith }
1732a6744ebSBarry Smith 
1742a6744ebSBarry Smith /*@
175f1580f4eSBarry Smith   PCGalerkinSetInterpolation - Sets the interpolation operator for the `PCGALERKIN` preconditioner
1762a6744ebSBarry Smith 
177c3339decSBarry Smith   Logically Collective
1782a6744ebSBarry Smith 
179d8d19677SJose E. Roman   Input Parameters:
1802a6744ebSBarry Smith + pc - the preconditioner context
181feefa0e1SJacob Faibussowitsch - P  - the interpolation operator
1822a6744ebSBarry Smith 
183feefa0e1SJacob Faibussowitsch   Level: intermediate
18420f4b53cSBarry Smith 
185f1580f4eSBarry Smith   Note:
186f1580f4eSBarry Smith   Either this or `PCGalerkinSetRestriction()` or both must be called
1872a6744ebSBarry Smith 
188*562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`,
189db781477SPatrick Sanan           `PCGalerkinSetRestriction()`, `PCGalerkinGetKSP()`
1902a6744ebSBarry Smith @*/
191d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGalerkinSetInterpolation(PC pc, Mat P)
192d71ae5a4SJacob Faibussowitsch {
1932a6744ebSBarry Smith   PetscFunctionBegin;
1940700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
195cac4c232SBarry Smith   PetscTryMethod(pc, "PCGalerkinSetInterpolation_C", (PC, Mat), (pc, P));
1963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1972a6744ebSBarry Smith }
1982a6744ebSBarry Smith 
199feefa0e1SJacob Faibussowitsch /*@C
200b3402f20SBarry Smith   PCGalerkinSetComputeSubmatrix - Provide a routine that will be called to compute the Galerkin submatrix
201b3402f20SBarry Smith 
202b3402f20SBarry Smith   Logically Collective
203b3402f20SBarry Smith 
204d8d19677SJose E. Roman   Input Parameters:
205b3402f20SBarry Smith + pc          - the preconditioner context
206b3402f20SBarry Smith . computeAsub - routine that computes the submatrix from the global matrix
20720f4b53cSBarry Smith - ctx         - context used by the routine, or `NULL`
208b3402f20SBarry Smith 
20920f4b53cSBarry Smith   Calling sequence of `computeAsub`:
21004c3f3b8SBarry Smith + pc  - the `PCGALERKIN` preconditioner
211f1580f4eSBarry Smith . A   - the matrix in the `PCGALERKIN`
21220f4b53cSBarry Smith . Ap  - the computed submatrix from any previous computation, if `NULL` it has not previously been computed
213b3402f20SBarry Smith . cAp - the submatrix computed by this routine
214b3402f20SBarry Smith - ctx - optional user-defined function context
215b3402f20SBarry Smith 
216feefa0e1SJacob Faibussowitsch   Level: intermediate
217b3402f20SBarry Smith 
21895452b02SPatrick Sanan   Notes:
219f1580f4eSBarry Smith   Instead of providing this routine you can call `PCGalerkinGetKSP()` and then `KSPSetOperators()` to provide the submatrix,
220f1580f4eSBarry Smith   but that will not work for multiple `KSPSolve()`s with different matrices unless you call it for each solve.
221b3402f20SBarry Smith 
22220f4b53cSBarry Smith   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
223b3402f20SBarry Smith   matrix and computes its values in cAp. On each subsequent call the routine should up the Ap matrix.
224b3402f20SBarry Smith 
225feefa0e1SJacob Faibussowitsch   Developer Notes:
226f1580f4eSBarry Smith   If the user does not call this routine nor call `PCGalerkinGetKSP()` and `KSPSetOperators()` then `PCGALERKIN`
227f1580f4eSBarry Smith   could automatically compute the submatrix via calls to `MatGalerkin()` or `MatRARt()`
228b3402f20SBarry Smith 
229*562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`,
230db781477SPatrick Sanan           `PCGalerkinSetRestriction()`, `PCGalerkinSetInterpolation()`, `PCGalerkinGetKSP()`
231b3402f20SBarry Smith @*/
23204c3f3b8SBarry Smith PetscErrorCode PCGalerkinSetComputeSubmatrix(PC pc, PetscErrorCode (*computeAsub)(PC pc, Mat A, Mat Ap, Mat *cAp, void *ctx), void *ctx)
233d71ae5a4SJacob Faibussowitsch {
234b3402f20SBarry Smith   PetscFunctionBegin;
235b3402f20SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
236cac4c232SBarry Smith   PetscTryMethod(pc, "PCGalerkinSetComputeSubmatrix_C", (PC, PetscErrorCode(*)(PC, Mat, Mat, Mat *, void *), void *), (pc, computeAsub, ctx));
2373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
238b3402f20SBarry Smith }
239b3402f20SBarry Smith 
240b3402f20SBarry Smith /*@
241f1580f4eSBarry Smith   PCGalerkinGetKSP - Gets the `KSP` object in the `PCGALERKIN`
2422a6744ebSBarry Smith 
2432a6744ebSBarry Smith   Not Collective
2442a6744ebSBarry Smith 
2452a6744ebSBarry Smith   Input Parameter:
2462a6744ebSBarry Smith . pc - the preconditioner context
2472a6744ebSBarry Smith 
248f1580f4eSBarry Smith   Output Parameter:
249f1580f4eSBarry Smith . ksp - the `KSP` object
2502a6744ebSBarry Smith 
251feefa0e1SJacob Faibussowitsch   Level: intermediate
2522a6744ebSBarry Smith 
253f1580f4eSBarry Smith   Note:
25404c3f3b8SBarry Smith   Once you have called this routine you can call `KSPSetOperators()` on the resulting `KSP` to provide the operator for the Galerkin problem,
255f1580f4eSBarry Smith   an alternative is to use `PCGalerkinSetComputeSubmatrix()` to provide a routine that computes the submatrix as needed.
256b3402f20SBarry Smith 
257*562efe2eSBarry Smith .seealso: [](ch_ksp), `PC`, `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`,
258db781477SPatrick Sanan           `PCGalerkinSetRestriction()`, `PCGalerkinSetInterpolation()`, `PCGalerkinSetComputeSubmatrix()`
2592a6744ebSBarry Smith @*/
260d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGalerkinGetKSP(PC pc, KSP *ksp)
261d71ae5a4SJacob Faibussowitsch {
2622a6744ebSBarry Smith   PetscFunctionBegin;
2630700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2644f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
265cac4c232SBarry Smith   PetscUseMethod(pc, "PCGalerkinGetKSP_C", (PC, KSP *), (pc, ksp));
2663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2672a6744ebSBarry Smith }
2682a6744ebSBarry Smith 
269d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_Galerkin(PC pc, PetscOptionItems *PetscOptionsObject)
270d71ae5a4SJacob Faibussowitsch {
2714ac220ccSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
2724ac220ccSBarry Smith   const char  *prefix;
2734ac220ccSBarry Smith   PetscBool    flg;
2744ac220ccSBarry Smith 
2754ac220ccSBarry Smith   PetscFunctionBegin;
2769566063dSJacob Faibussowitsch   PetscCall(KSPGetOptionsPrefix(jac->ksp, &prefix));
2779566063dSJacob Faibussowitsch   PetscCall(PetscStrendswith(prefix, "galerkin_", &flg));
2784ac220ccSBarry Smith   if (!flg) {
2799566063dSJacob Faibussowitsch     PetscCall(PCGetOptionsPrefix(pc, &prefix));
2809566063dSJacob Faibussowitsch     PetscCall(KSPSetOptionsPrefix(jac->ksp, prefix));
2819566063dSJacob Faibussowitsch     PetscCall(KSPAppendOptionsPrefix(jac->ksp, "galerkin_"));
2824ac220ccSBarry Smith   }
2834ac220ccSBarry Smith 
284d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "Galerkin options");
2851baa6e33SBarry Smith   if (jac->ksp) PetscCall(KSPSetFromOptions(jac->ksp));
286d0609cedSBarry Smith   PetscOptionsHeadEnd();
2873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2884ac220ccSBarry Smith }
2892a6744ebSBarry Smith 
2902a6744ebSBarry Smith /*MC
2912a6744ebSBarry Smith      PCGALERKIN - Build (part of) a preconditioner by P S R (where P is often R^T)
2922a6744ebSBarry Smith 
2932a6744ebSBarry Smith     Level: intermediate
2942a6744ebSBarry Smith 
29520f4b53cSBarry Smith     Note:
29620f4b53cSBarry Smith     Use
29720f4b53cSBarry Smith .vb
29820f4b53cSBarry Smith      `PCGalerkinSetRestriction`(pc,R) and/or `PCGalerkinSetInterpolation`(pc,P)
29920f4b53cSBarry Smith      `PCGalerkinGetKSP`(pc,&ksp);
30020f4b53cSBarry Smith      `KSPSetOperators`(ksp,A,....)
30120f4b53cSBarry Smith      ...
30220f4b53cSBarry Smith .ve
30320f4b53cSBarry Smith 
304f1580f4eSBarry Smith     Developer Notes:
305f1580f4eSBarry Smith     If `KSPSetOperators()` has not been called on the inner `KSP` then `PCGALERKIN` could use `MatRARt()` or `MatPtAP()` to compute
3067817a140SBarry Smith     the operators automatically.
307f1580f4eSBarry Smith 
308f1580f4eSBarry Smith     Should there be a prefix for the inner `KSP`?
309f1580f4eSBarry Smith 
310f1580f4eSBarry Smith     There is no `KSPSetFromOptions_Galerkin()` that calls `KSPSetFromOptions()` on the inner `KSP`
3117817a140SBarry Smith 
312*562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`,
313db781477SPatrick Sanan           `PCSHELL`, `PCKSP`, `PCGalerkinSetRestriction()`, `PCGalerkinSetInterpolation()`, `PCGalerkinGetKSP()`
3142a6744ebSBarry Smith M*/
3152a6744ebSBarry Smith 
316d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_Galerkin(PC pc)
317d71ae5a4SJacob Faibussowitsch {
3182a6744ebSBarry Smith   PC_Galerkin *jac;
3192a6744ebSBarry Smith 
3202a6744ebSBarry Smith   PetscFunctionBegin;
3214dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
3222fa5cd67SKarl Rupp 
3232a6744ebSBarry Smith   pc->ops->apply           = PCApply_Galerkin;
3242a6744ebSBarry Smith   pc->ops->setup           = PCSetUp_Galerkin;
325a06653b4SBarry Smith   pc->ops->reset           = PCReset_Galerkin;
3262a6744ebSBarry Smith   pc->ops->destroy         = PCDestroy_Galerkin;
3272a6744ebSBarry Smith   pc->ops->view            = PCView_Galerkin;
3284ac220ccSBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_Galerkin;
3294ac220ccSBarry Smith   pc->ops->applyrichardson = NULL;
3302a6744ebSBarry Smith 
3319566063dSJacob Faibussowitsch   PetscCall(KSPCreate(PetscObjectComm((PetscObject)pc), &jac->ksp));
3323821be0aSBarry Smith   PetscCall(KSPSetNestLevel(jac->ksp, pc->kspnestlevel));
3339566063dSJacob Faibussowitsch   PetscCall(KSPSetErrorIfNotConverged(jac->ksp, pc->erroriffailure));
3349566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)jac->ksp, (PetscObject)pc, 1));
3352a6744ebSBarry Smith 
3362a6744ebSBarry Smith   pc->data = (void *)jac;
3372a6744ebSBarry Smith 
3389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinSetRestriction_C", PCGalerkinSetRestriction_Galerkin));
3399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinSetInterpolation_C", PCGalerkinSetInterpolation_Galerkin));
3409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinGetKSP_C", PCGalerkinGetKSP_Galerkin));
3419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinSetComputeSubmatrix_C", PCGalerkinSetComputeSubmatrix_Galerkin));
3423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3432a6744ebSBarry Smith }
344