xref: /petsc/src/ksp/pc/impls/galerkin/galerkin.c (revision 20f4b53cbb5e9bd9ef12b76a8697d60d197cda17)
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 
16d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_Galerkin(PC pc, Vec x, Vec y)
17d71ae5a4SJacob Faibussowitsch {
182a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
192a6744ebSBarry Smith 
202a6744ebSBarry Smith   PetscFunctionBegin;
212fa5cd67SKarl Rupp   if (jac->R) {
229566063dSJacob Faibussowitsch     PetscCall(MatRestrict(jac->R, x, jac->b));
232fa5cd67SKarl Rupp   } else {
249566063dSJacob Faibussowitsch     PetscCall(MatRestrict(jac->P, x, jac->b));
252fa5cd67SKarl Rupp   }
269566063dSJacob Faibussowitsch   PetscCall(KSPSolve(jac->ksp, jac->b, jac->x));
279566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(jac->ksp, pc, jac->x));
282fa5cd67SKarl Rupp   if (jac->P) {
299566063dSJacob Faibussowitsch     PetscCall(MatInterpolate(jac->P, jac->x, y));
302fa5cd67SKarl Rupp   } else {
319566063dSJacob Faibussowitsch     PetscCall(MatInterpolate(jac->R, jac->x, y));
322fa5cd67SKarl Rupp   }
333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
342a6744ebSBarry Smith }
352a6744ebSBarry Smith 
36d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_Galerkin(PC pc)
37d71ae5a4SJacob Faibussowitsch {
382a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
39ace3abfcSBarry Smith   PetscBool    a;
40906ed7ccSBarry Smith   Vec         *xx, *yy;
412a6744ebSBarry Smith 
422a6744ebSBarry Smith   PetscFunctionBegin;
43b3402f20SBarry Smith   if (jac->computeasub) {
44b3402f20SBarry Smith     Mat Ap;
45b3402f20SBarry Smith     if (!pc->setupcalled) {
469566063dSJacob Faibussowitsch       PetscCall((*jac->computeasub)(pc, pc->pmat, NULL, &Ap, jac->computeasub_ctx));
479566063dSJacob Faibussowitsch       PetscCall(KSPSetOperators(jac->ksp, Ap, Ap));
489566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Ap));
49b3402f20SBarry Smith     } else {
509566063dSJacob Faibussowitsch       PetscCall(KSPGetOperators(jac->ksp, NULL, &Ap));
519566063dSJacob Faibussowitsch       PetscCall((*jac->computeasub)(pc, pc->pmat, Ap, NULL, jac->computeasub_ctx));
52b3402f20SBarry Smith     }
53b3402f20SBarry Smith   }
54b3402f20SBarry Smith 
552a6744ebSBarry Smith   if (!jac->x) {
569566063dSJacob Faibussowitsch     PetscCall(KSPGetOperatorsSet(jac->ksp, &a, NULL));
5728b400f6SJacob Faibussowitsch     PetscCheck(a, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set operator of PCGALERKIN KSP with PCGalerkinGetKSP()/KSPSetOperators()");
589566063dSJacob Faibussowitsch     PetscCall(KSPCreateVecs(jac->ksp, 1, &xx, 1, &yy));
59906ed7ccSBarry Smith     jac->x = *xx;
60906ed7ccSBarry Smith     jac->b = *yy;
619566063dSJacob Faibussowitsch     PetscCall(PetscFree(xx));
629566063dSJacob Faibussowitsch     PetscCall(PetscFree(yy));
632a6744ebSBarry Smith   }
647827d75bSBarry Smith   PetscCheck(jac->R || jac->P, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Must set restriction or interpolation of PCGALERKIN with PCGalerkinSetRestriction()/Interpolation()");
652a6744ebSBarry Smith   /* should check here that sizes of R/P match size of a */
66b3402f20SBarry Smith 
673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
682a6744ebSBarry Smith }
692a6744ebSBarry Smith 
70d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCReset_Galerkin(PC pc)
71d71ae5a4SJacob Faibussowitsch {
722a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
732a6744ebSBarry Smith 
742a6744ebSBarry Smith   PetscFunctionBegin;
759566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->R));
769566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->P));
779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->x));
789566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&jac->b));
799566063dSJacob Faibussowitsch   PetscCall(KSPReset(jac->ksp));
803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81a06653b4SBarry Smith }
82a06653b4SBarry Smith 
83d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_Galerkin(PC pc)
84d71ae5a4SJacob Faibussowitsch {
85a06653b4SBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
86a06653b4SBarry Smith 
87a06653b4SBarry Smith   PetscFunctionBegin;
889566063dSJacob Faibussowitsch   PetscCall(PCReset_Galerkin(pc));
899566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&jac->ksp));
909566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
922a6744ebSBarry Smith }
932a6744ebSBarry Smith 
94d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_Galerkin(PC pc, PetscViewer viewer)
95d71ae5a4SJacob Faibussowitsch {
962a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
97ace3abfcSBarry Smith   PetscBool    iascii;
982a6744ebSBarry Smith 
992a6744ebSBarry Smith   PetscFunctionBegin;
1009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1012a6744ebSBarry Smith   if (iascii) {
1029566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  KSP on Galerkin follow\n"));
1039566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------------------------------\n"));
1042a6744ebSBarry Smith   }
1059566063dSJacob Faibussowitsch   PetscCall(KSPView(jac->ksp, viewer));
1063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1072a6744ebSBarry Smith }
1082a6744ebSBarry Smith 
109d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGalerkinGetKSP_Galerkin(PC pc, KSP *ksp)
110d71ae5a4SJacob Faibussowitsch {
1112a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
1122a6744ebSBarry Smith 
1132a6744ebSBarry Smith   PetscFunctionBegin;
1142a6744ebSBarry Smith   *ksp = jac->ksp;
1153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1162a6744ebSBarry Smith }
1172a6744ebSBarry Smith 
118d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGalerkinSetRestriction_Galerkin(PC pc, Mat R)
119d71ae5a4SJacob Faibussowitsch {
1202a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
1212a6744ebSBarry Smith 
1222a6744ebSBarry Smith   PetscFunctionBegin;
1239566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)R));
1249566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->R));
1252a6744ebSBarry Smith   jac->R = R;
1263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1272a6744ebSBarry Smith }
1282a6744ebSBarry Smith 
129d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGalerkinSetInterpolation_Galerkin(PC pc, Mat P)
130d71ae5a4SJacob Faibussowitsch {
1312a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
1322a6744ebSBarry Smith 
1332a6744ebSBarry Smith   PetscFunctionBegin;
1349566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)P));
1359566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&jac->P));
1362a6744ebSBarry Smith   jac->P = P;
1373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1382a6744ebSBarry Smith }
1392a6744ebSBarry Smith 
140d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGalerkinSetComputeSubmatrix_Galerkin(PC pc, PetscErrorCode (*computeAsub)(PC, Mat, Mat, Mat *, void *), void *ctx)
141d71ae5a4SJacob Faibussowitsch {
142b3402f20SBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
143b3402f20SBarry Smith 
144b3402f20SBarry Smith   PetscFunctionBegin;
145b3402f20SBarry Smith   jac->computeasub     = computeAsub;
146b3402f20SBarry Smith   jac->computeasub_ctx = ctx;
1473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
148b3402f20SBarry Smith }
149b3402f20SBarry Smith 
1502a6744ebSBarry Smith /*@
151f1580f4eSBarry Smith    PCGalerkinSetRestriction - Sets the restriction operator for the `PCGALERKIN` preconditioner
1522a6744ebSBarry Smith 
153c3339decSBarry Smith    Logically Collective
1542a6744ebSBarry Smith 
155d8d19677SJose E. Roman    Input Parameters:
1562a6744ebSBarry Smith +  pc - the preconditioner context
1572a6744ebSBarry Smith -  R - the restriction operator
1582a6744ebSBarry Smith 
159*20f4b53cSBarry Smith    Level: Intermediate
160*20f4b53cSBarry Smith 
161f1580f4eSBarry Smith    Note:
162f1580f4eSBarry Smith    Either this or `PCGalerkinSetInterpolation()` or both must be called
1632a6744ebSBarry Smith 
164*20f4b53cSBarry Smith .seealso: `PC`, `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`,
165db781477SPatrick Sanan           `PCGalerkinSetInterpolation()`, `PCGalerkinGetKSP()`
1662a6744ebSBarry Smith @*/
167d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGalerkinSetRestriction(PC pc, Mat R)
168d71ae5a4SJacob Faibussowitsch {
1692a6744ebSBarry Smith   PetscFunctionBegin;
1700700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
171cac4c232SBarry Smith   PetscTryMethod(pc, "PCGalerkinSetRestriction_C", (PC, Mat), (pc, R));
1723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1732a6744ebSBarry Smith }
1742a6744ebSBarry Smith 
1752a6744ebSBarry Smith /*@
176f1580f4eSBarry Smith    PCGalerkinSetInterpolation - Sets the interpolation operator for the `PCGALERKIN` preconditioner
1772a6744ebSBarry Smith 
178c3339decSBarry Smith    Logically Collective
1792a6744ebSBarry Smith 
180d8d19677SJose E. Roman    Input Parameters:
1812a6744ebSBarry Smith +  pc - the preconditioner context
1822a6744ebSBarry Smith -  R - the interpolation operator
1832a6744ebSBarry Smith 
184*20f4b53cSBarry Smith    Level: Intermediate
185*20f4b53cSBarry Smith 
186f1580f4eSBarry Smith    Note:
187f1580f4eSBarry Smith    Either this or `PCGalerkinSetRestriction()` or both must be called
1882a6744ebSBarry Smith 
189*20f4b53cSBarry Smith .seealso: `PC`, `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`,
190db781477SPatrick Sanan           `PCGalerkinSetRestriction()`, `PCGalerkinGetKSP()`
1912a6744ebSBarry Smith @*/
192d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGalerkinSetInterpolation(PC pc, Mat P)
193d71ae5a4SJacob Faibussowitsch {
1942a6744ebSBarry Smith   PetscFunctionBegin;
1950700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
196cac4c232SBarry Smith   PetscTryMethod(pc, "PCGalerkinSetInterpolation_C", (PC, Mat), (pc, P));
1973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1982a6744ebSBarry Smith }
1992a6744ebSBarry Smith 
2002a6744ebSBarry Smith /*@
201b3402f20SBarry Smith    PCGalerkinSetComputeSubmatrix - Provide a routine that will be called to compute the Galerkin submatrix
202b3402f20SBarry Smith 
203b3402f20SBarry Smith    Logically Collective
204b3402f20SBarry Smith 
205d8d19677SJose E. Roman    Input Parameters:
206b3402f20SBarry Smith +  pc - the preconditioner context
207b3402f20SBarry Smith .  computeAsub - routine that computes the submatrix from the global matrix
208*20f4b53cSBarry Smith -  ctx - context used by the routine, or `NULL`
209b3402f20SBarry Smith 
210*20f4b53cSBarry Smith    Calling sequence of `computeAsub`:
211*20f4b53cSBarry Smith $  PetscErrorCode computeAsub(PC pc, Mat A, Mat Ap, Mat *cAP, void *ctx);
212f1580f4eSBarry Smith +  PC - the `PCGALERKIN`
213f1580f4eSBarry Smith .  A - the matrix in the `PCGALERKIN`
214*20f4b53cSBarry Smith .  Ap - the computed submatrix from any previous computation, if `NULL` it has not previously been computed
215b3402f20SBarry Smith .  cAp - the submatrix computed by this routine
216b3402f20SBarry Smith -  ctx - optional user-defined function context
217b3402f20SBarry Smith 
218b3402f20SBarry Smith    Level: Intermediate
219b3402f20SBarry Smith 
22095452b02SPatrick Sanan    Notes:
221f1580f4eSBarry Smith    Instead of providing this routine you can call `PCGalerkinGetKSP()` and then `KSPSetOperators()` to provide the submatrix,
222f1580f4eSBarry Smith    but that will not work for multiple `KSPSolve()`s with different matrices unless you call it for each solve.
223b3402f20SBarry Smith 
224*20f4b53cSBarry 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
225b3402f20SBarry Smith    matrix and computes its values in cAp. On each subsequent call the routine should up the Ap matrix.
226b3402f20SBarry Smith 
227f1580f4eSBarry Smith    Developer Note:
228f1580f4eSBarry Smith    If the user does not call this routine nor call `PCGalerkinGetKSP()` and `KSPSetOperators()` then `PCGALERKIN`
229f1580f4eSBarry Smith    could automatically compute the submatrix via calls to `MatGalerkin()` or `MatRARt()`
230b3402f20SBarry Smith 
231*20f4b53cSBarry Smith .seealso: `PC`, `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`,
232db781477SPatrick Sanan           `PCGalerkinSetRestriction()`, `PCGalerkinSetInterpolation()`, `PCGalerkinGetKSP()`
233b3402f20SBarry Smith @*/
234d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGalerkinSetComputeSubmatrix(PC pc, PetscErrorCode (*computeAsub)(PC, Mat, Mat, Mat *, void *), void *ctx)
235d71ae5a4SJacob Faibussowitsch {
236b3402f20SBarry Smith   PetscFunctionBegin;
237b3402f20SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
238cac4c232SBarry Smith   PetscTryMethod(pc, "PCGalerkinSetComputeSubmatrix_C", (PC, PetscErrorCode(*)(PC, Mat, Mat, Mat *, void *), void *), (pc, computeAsub, ctx));
2393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
240b3402f20SBarry Smith }
241b3402f20SBarry Smith 
242b3402f20SBarry Smith /*@
243f1580f4eSBarry Smith    PCGalerkinGetKSP - Gets the `KSP` object in the `PCGALERKIN`
2442a6744ebSBarry Smith 
2452a6744ebSBarry Smith    Not Collective
2462a6744ebSBarry Smith 
2472a6744ebSBarry Smith    Input Parameter:
2482a6744ebSBarry Smith .  pc - the preconditioner context
2492a6744ebSBarry Smith 
250f1580f4eSBarry Smith    Output Parameter:
251f1580f4eSBarry Smith .  ksp - the `KSP` object
2522a6744ebSBarry Smith 
2532a6744ebSBarry Smith    Level: Intermediate
2542a6744ebSBarry Smith 
255f1580f4eSBarry Smith    Note:
256f1580f4eSBarry Smith    Once you have called this routine you can call `KSPSetOperators()` on the resulting ksp to provide the operator for the Galerkin problem,
257f1580f4eSBarry Smith    an alternative is to use `PCGalerkinSetComputeSubmatrix()` to provide a routine that computes the submatrix as needed.
258b3402f20SBarry Smith 
259*20f4b53cSBarry Smith .seealso: `PC`, `PCCreate()`, `PCSetType()`, `PCType`, `PCGALERKIN`,
260db781477SPatrick Sanan           `PCGalerkinSetRestriction()`, `PCGalerkinSetInterpolation()`, `PCGalerkinSetComputeSubmatrix()`
2612a6744ebSBarry Smith @*/
262d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGalerkinGetKSP(PC pc, KSP *ksp)
263d71ae5a4SJacob Faibussowitsch {
2642a6744ebSBarry Smith   PetscFunctionBegin;
2650700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
2662a6744ebSBarry Smith   PetscValidPointer(ksp, 2);
267cac4c232SBarry Smith   PetscUseMethod(pc, "PCGalerkinGetKSP_C", (PC, KSP *), (pc, ksp));
2683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2692a6744ebSBarry Smith }
2702a6744ebSBarry Smith 
271d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_Galerkin(PC pc, PetscOptionItems *PetscOptionsObject)
272d71ae5a4SJacob Faibussowitsch {
2734ac220ccSBarry Smith   PC_Galerkin *jac = (PC_Galerkin *)pc->data;
2744ac220ccSBarry Smith   const char  *prefix;
2754ac220ccSBarry Smith   PetscBool    flg;
2764ac220ccSBarry Smith 
2774ac220ccSBarry Smith   PetscFunctionBegin;
2789566063dSJacob Faibussowitsch   PetscCall(KSPGetOptionsPrefix(jac->ksp, &prefix));
2799566063dSJacob Faibussowitsch   PetscCall(PetscStrendswith(prefix, "galerkin_", &flg));
2804ac220ccSBarry Smith   if (!flg) {
2819566063dSJacob Faibussowitsch     PetscCall(PCGetOptionsPrefix(pc, &prefix));
2829566063dSJacob Faibussowitsch     PetscCall(KSPSetOptionsPrefix(jac->ksp, prefix));
2839566063dSJacob Faibussowitsch     PetscCall(KSPAppendOptionsPrefix(jac->ksp, "galerkin_"));
2844ac220ccSBarry Smith   }
2854ac220ccSBarry Smith 
286d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "Galerkin options");
2871baa6e33SBarry Smith   if (jac->ksp) PetscCall(KSPSetFromOptions(jac->ksp));
288d0609cedSBarry Smith   PetscOptionsHeadEnd();
2893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2904ac220ccSBarry Smith }
2912a6744ebSBarry Smith 
2922a6744ebSBarry Smith /*MC
2932a6744ebSBarry Smith      PCGALERKIN - Build (part of) a preconditioner by P S R (where P is often R^T)
2942a6744ebSBarry Smith 
2952a6744ebSBarry Smith     Level: intermediate
2962a6744ebSBarry Smith 
297*20f4b53cSBarry Smith     Note:
298*20f4b53cSBarry Smith     Use
299*20f4b53cSBarry Smith .vb
300*20f4b53cSBarry Smith      `PCGalerkinSetRestriction`(pc,R) and/or `PCGalerkinSetInterpolation`(pc,P)
301*20f4b53cSBarry Smith      `PCGalerkinGetKSP`(pc,&ksp);
302*20f4b53cSBarry Smith      `KSPSetOperators`(ksp,A,....)
303*20f4b53cSBarry Smith      ...
304*20f4b53cSBarry Smith .ve
305*20f4b53cSBarry Smith 
306f1580f4eSBarry Smith     Developer Notes:
307f1580f4eSBarry Smith     If `KSPSetOperators()` has not been called on the inner `KSP` then `PCGALERKIN` could use `MatRARt()` or `MatPtAP()` to compute
3087817a140SBarry Smith     the operators automatically.
309f1580f4eSBarry Smith 
310f1580f4eSBarry Smith     Should there be a prefix for the inner `KSP`?
311f1580f4eSBarry Smith 
312f1580f4eSBarry Smith     There is no `KSPSetFromOptions_Galerkin()` that calls `KSPSetFromOptions()` on the inner `KSP`
3137817a140SBarry Smith 
314db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`,
315db781477SPatrick Sanan           `PCSHELL`, `PCKSP`, `PCGalerkinSetRestriction()`, `PCGalerkinSetInterpolation()`, `PCGalerkinGetKSP()`
3162a6744ebSBarry Smith M*/
3172a6744ebSBarry Smith 
318d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_Galerkin(PC pc)
319d71ae5a4SJacob Faibussowitsch {
3202a6744ebSBarry Smith   PC_Galerkin *jac;
3212a6744ebSBarry Smith 
3222a6744ebSBarry Smith   PetscFunctionBegin;
3234dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&jac));
3242fa5cd67SKarl Rupp 
3252a6744ebSBarry Smith   pc->ops->apply           = PCApply_Galerkin;
3262a6744ebSBarry Smith   pc->ops->setup           = PCSetUp_Galerkin;
327a06653b4SBarry Smith   pc->ops->reset           = PCReset_Galerkin;
3282a6744ebSBarry Smith   pc->ops->destroy         = PCDestroy_Galerkin;
3292a6744ebSBarry Smith   pc->ops->view            = PCView_Galerkin;
3304ac220ccSBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_Galerkin;
3314ac220ccSBarry Smith   pc->ops->applyrichardson = NULL;
3322a6744ebSBarry Smith 
3339566063dSJacob Faibussowitsch   PetscCall(KSPCreate(PetscObjectComm((PetscObject)pc), &jac->ksp));
3349566063dSJacob Faibussowitsch   PetscCall(KSPSetErrorIfNotConverged(jac->ksp, pc->erroriffailure));
3359566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)jac->ksp, (PetscObject)pc, 1));
3362a6744ebSBarry Smith 
3372a6744ebSBarry Smith   pc->data = (void *)jac;
3382a6744ebSBarry Smith 
3399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinSetRestriction_C", PCGalerkinSetRestriction_Galerkin));
3409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinSetInterpolation_C", PCGalerkinSetInterpolation_Galerkin));
3419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinGetKSP_C", PCGalerkinGetKSP_Galerkin));
3429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGalerkinSetComputeSubmatrix_C", PCGalerkinSetComputeSubmatrix_Galerkin));
3433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3442a6744ebSBarry Smith }
345