xref: /petsc/src/ksp/pc/impls/galerkin/galerkin.c (revision 7827d75ba736e00c19d105c058b1c2ddcca945c7)
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 
162a6744ebSBarry Smith static PetscErrorCode PCApply_Galerkin(PC pc,Vec x,Vec y)
172a6744ebSBarry Smith {
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   }
332a6744ebSBarry Smith   PetscFunctionReturn(0);
342a6744ebSBarry Smith }
352a6744ebSBarry Smith 
362a6744ebSBarry Smith static PetscErrorCode PCSetUp_Galerkin(PC pc)
372a6744ebSBarry Smith {
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   }
64*7827d75bSBarry 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 
672a6744ebSBarry Smith   PetscFunctionReturn(0);
682a6744ebSBarry Smith }
692a6744ebSBarry Smith 
70a06653b4SBarry Smith static PetscErrorCode PCReset_Galerkin(PC pc)
712a6744ebSBarry Smith {
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));
80a06653b4SBarry Smith   PetscFunctionReturn(0);
81a06653b4SBarry Smith }
82a06653b4SBarry Smith 
83a06653b4SBarry Smith static PetscErrorCode PCDestroy_Galerkin(PC pc)
84a06653b4SBarry Smith {
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));
912a6744ebSBarry Smith   PetscFunctionReturn(0);
922a6744ebSBarry Smith }
932a6744ebSBarry Smith 
942a6744ebSBarry Smith static PetscErrorCode PCView_Galerkin(PC pc,PetscViewer viewer)
952a6744ebSBarry Smith {
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));
1062a6744ebSBarry Smith   PetscFunctionReturn(0);
1072a6744ebSBarry Smith }
1082a6744ebSBarry Smith 
1091e6b0712SBarry Smith static PetscErrorCode  PCGalerkinGetKSP_Galerkin(PC pc,KSP *ksp)
1102a6744ebSBarry Smith {
1112a6744ebSBarry Smith   PC_Galerkin *jac = (PC_Galerkin*)pc->data;
1122a6744ebSBarry Smith 
1132a6744ebSBarry Smith   PetscFunctionBegin;
1142a6744ebSBarry Smith   *ksp = jac->ksp;
1152a6744ebSBarry Smith   PetscFunctionReturn(0);
1162a6744ebSBarry Smith }
1172a6744ebSBarry Smith 
1181e6b0712SBarry Smith static PetscErrorCode  PCGalerkinSetRestriction_Galerkin(PC pc,Mat R)
1192a6744ebSBarry Smith {
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;
1262a6744ebSBarry Smith   PetscFunctionReturn(0);
1272a6744ebSBarry Smith }
1282a6744ebSBarry Smith 
1291e6b0712SBarry Smith static PetscErrorCode  PCGalerkinSetInterpolation_Galerkin(PC pc,Mat P)
1302a6744ebSBarry Smith {
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;
1372a6744ebSBarry Smith   PetscFunctionReturn(0);
1382a6744ebSBarry Smith }
1392a6744ebSBarry Smith 
140b3402f20SBarry Smith static PetscErrorCode  PCGalerkinSetComputeSubmatrix_Galerkin(PC pc,PetscErrorCode (*computeAsub)(PC,Mat,Mat,Mat*,void*),void *ctx)
141b3402f20SBarry Smith {
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;
147b3402f20SBarry Smith   PetscFunctionReturn(0);
148b3402f20SBarry Smith }
149b3402f20SBarry Smith 
1502a6744ebSBarry Smith /* -------------------------------------------------------------------------------- */
1512a6744ebSBarry Smith /*@
1522a6744ebSBarry Smith    PCGalerkinSetRestriction - Sets the restriction operator for the "Galerkin-type" preconditioner
1532a6744ebSBarry Smith 
154ad4df100SBarry Smith    Logically Collective on PC
1552a6744ebSBarry Smith 
156d8d19677SJose E. Roman    Input Parameters:
1572a6744ebSBarry Smith +  pc - the preconditioner context
1582a6744ebSBarry Smith -  R - the restriction operator
1592a6744ebSBarry Smith 
16095452b02SPatrick Sanan    Notes:
16195452b02SPatrick Sanan     Either this or PCGalerkinSetInterpolation() or both must be called
1622a6744ebSBarry Smith 
1632a6744ebSBarry Smith    Level: Intermediate
1642a6744ebSBarry Smith 
1652a6744ebSBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PCGALERKIN,
1662a6744ebSBarry Smith            PCGalerkinSetInterpolation(), PCGalerkinGetKSP()
1672a6744ebSBarry Smith 
1682a6744ebSBarry Smith @*/
1697087cfbeSBarry Smith PetscErrorCode  PCGalerkinSetRestriction(PC pc,Mat R)
1702a6744ebSBarry Smith {
1712a6744ebSBarry Smith   PetscFunctionBegin;
1720700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1739566063dSJacob Faibussowitsch   PetscCall(PetscTryMethod(pc,"PCGalerkinSetRestriction_C",(PC,Mat),(pc,R)));
1742a6744ebSBarry Smith   PetscFunctionReturn(0);
1752a6744ebSBarry Smith }
1762a6744ebSBarry Smith 
1772a6744ebSBarry Smith /*@
1782a6744ebSBarry Smith    PCGalerkinSetInterpolation - Sets the interpolation operator for the "Galerkin-type" preconditioner
1792a6744ebSBarry Smith 
180ad4df100SBarry Smith    Logically Collective on PC
1812a6744ebSBarry Smith 
182d8d19677SJose E. Roman    Input Parameters:
1832a6744ebSBarry Smith +  pc - the preconditioner context
1842a6744ebSBarry Smith -  R - the interpolation operator
1852a6744ebSBarry Smith 
18695452b02SPatrick Sanan    Notes:
18795452b02SPatrick Sanan     Either this or PCGalerkinSetRestriction() or both must be called
1882a6744ebSBarry Smith 
1892a6744ebSBarry Smith    Level: Intermediate
1902a6744ebSBarry Smith 
1912a6744ebSBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PCGALERKIN,
1922a6744ebSBarry Smith            PCGalerkinSetRestriction(), PCGalerkinGetKSP()
1932a6744ebSBarry Smith 
1942a6744ebSBarry Smith @*/
1957087cfbeSBarry Smith PetscErrorCode  PCGalerkinSetInterpolation(PC pc,Mat P)
1962a6744ebSBarry Smith {
1972a6744ebSBarry Smith   PetscFunctionBegin;
1980700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1999566063dSJacob Faibussowitsch   PetscCall(PetscTryMethod(pc,"PCGalerkinSetInterpolation_C",(PC,Mat),(pc,P)));
2002a6744ebSBarry Smith   PetscFunctionReturn(0);
2012a6744ebSBarry Smith }
2022a6744ebSBarry Smith 
2032a6744ebSBarry Smith /*@
204b3402f20SBarry Smith    PCGalerkinSetComputeSubmatrix - Provide a routine that will be called to compute the Galerkin submatrix
205b3402f20SBarry Smith 
206b3402f20SBarry Smith    Logically Collective
207b3402f20SBarry Smith 
208d8d19677SJose E. Roman    Input Parameters:
209b3402f20SBarry Smith +  pc - the preconditioner context
210b3402f20SBarry Smith .  computeAsub - routine that computes the submatrix from the global matrix
211b3402f20SBarry Smith -  ctx - context used by the routine, or NULL
212b3402f20SBarry Smith 
213b3402f20SBarry Smith    Calling sequence of computeAsub:
214b3402f20SBarry Smith $    computeAsub(PC pc,Mat A, Mat Ap, Mat *cAP,void *ctx);
215b3402f20SBarry Smith 
216b3402f20SBarry Smith +  PC - the Galerkin PC
217b3402f20SBarry Smith .  A - the matrix in the Galerkin PC
218b3402f20SBarry Smith .  Ap - the computed submatrix from any previous computation, if NULL it has not previously been computed
219b3402f20SBarry Smith .  cAp - the submatrix computed by this routine
220b3402f20SBarry Smith -  ctx - optional user-defined function context
221b3402f20SBarry Smith 
222b3402f20SBarry Smith    Level: Intermediate
223b3402f20SBarry Smith 
22495452b02SPatrick Sanan    Notes:
22595452b02SPatrick Sanan     Instead of providing this routine you can call PCGalerkinGetKSP() and then KSPSetOperators() to provide the submatrix,
226b3402f20SBarry Smith           but that will not work for multiple KSPSolves with different matrices unless you call it for each solve.
227b3402f20SBarry Smith 
228910cf402Sprj-           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
229b3402f20SBarry Smith           matrix and computes its values in cAp. On each subsequent call the routine should up the Ap matrix.
230b3402f20SBarry Smith 
23195452b02SPatrick Sanan    Developer Notes:
23295452b02SPatrick Sanan     If the user does not call this routine nor call PCGalerkinGetKSP() and KSPSetOperators() then PCGalerkin could
233b3402f20SBarry Smith                     could automatically compute the submatrix via calls to MatGalerkin() or MatRARt()
234b3402f20SBarry Smith 
235b3402f20SBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PCGALERKIN,
236b3402f20SBarry Smith            PCGalerkinSetRestriction(), PCGalerkinSetInterpolation(), PCGalerkinGetKSP()
237b3402f20SBarry Smith 
238b3402f20SBarry Smith @*/
239b3402f20SBarry Smith PetscErrorCode  PCGalerkinSetComputeSubmatrix(PC pc,PetscErrorCode (*computeAsub)(PC,Mat,Mat,Mat*,void*),void *ctx)
240b3402f20SBarry Smith {
241b3402f20SBarry Smith   PetscFunctionBegin;
242b3402f20SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2439566063dSJacob Faibussowitsch   PetscCall(PetscTryMethod(pc,"PCGalerkinSetComputeSubmatrix_C",(PC,PetscErrorCode (*)(PC,Mat,Mat,Mat*,void*),void*),(pc,computeAsub,ctx)));
244b3402f20SBarry Smith   PetscFunctionReturn(0);
245b3402f20SBarry Smith }
246b3402f20SBarry Smith 
247b3402f20SBarry Smith /*@
2482a6744ebSBarry Smith    PCGalerkinGetKSP - Gets the KSP object in the Galerkin PC.
2492a6744ebSBarry Smith 
2502a6744ebSBarry Smith    Not Collective
2512a6744ebSBarry Smith 
2522a6744ebSBarry Smith    Input Parameter:
2532a6744ebSBarry Smith .  pc - the preconditioner context
2542a6744ebSBarry Smith 
2552a6744ebSBarry Smith    Output Parameters:
2562a6744ebSBarry Smith .  ksp - the KSP object
2572a6744ebSBarry Smith 
2582a6744ebSBarry Smith    Level: Intermediate
2592a6744ebSBarry Smith 
26095452b02SPatrick Sanan    Notes:
26195452b02SPatrick Sanan     Once you have called this routine you can call KSPSetOperators() on the resulting ksp to provide the operator for the Galerkin problem,
262b3402f20SBarry Smith           an alternative is to use PCGalerkinSetComputeSubmatrix() to provide a routine that computes the submatrix as needed.
263b3402f20SBarry Smith 
2642a6744ebSBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PCGALERKIN,
265b3402f20SBarry Smith            PCGalerkinSetRestriction(), PCGalerkinSetInterpolation(), PCGalerkinSetComputeSubmatrix()
2662a6744ebSBarry Smith 
2672a6744ebSBarry Smith @*/
2687087cfbeSBarry Smith PetscErrorCode  PCGalerkinGetKSP(PC pc,KSP *ksp)
2692a6744ebSBarry Smith {
2702a6744ebSBarry Smith   PetscFunctionBegin;
2710700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2722a6744ebSBarry Smith   PetscValidPointer(ksp,2);
2739566063dSJacob Faibussowitsch   PetscCall(PetscUseMethod(pc,"PCGalerkinGetKSP_C",(PC,KSP*),(pc,ksp)));
2742a6744ebSBarry Smith   PetscFunctionReturn(0);
2752a6744ebSBarry Smith }
2762a6744ebSBarry Smith 
2774ac220ccSBarry Smith static PetscErrorCode PCSetFromOptions_Galerkin(PetscOptionItems *PetscOptionsObject,PC pc)
2784ac220ccSBarry Smith {
2794ac220ccSBarry Smith   PC_Galerkin    *jac = (PC_Galerkin*)pc->data;
2804ac220ccSBarry Smith   const char     *prefix;
2814ac220ccSBarry Smith   PetscBool      flg;
2824ac220ccSBarry Smith 
2834ac220ccSBarry Smith   PetscFunctionBegin;
2849566063dSJacob Faibussowitsch   PetscCall(KSPGetOptionsPrefix(jac->ksp,&prefix));
2859566063dSJacob Faibussowitsch   PetscCall(PetscStrendswith(prefix,"galerkin_",&flg));
2864ac220ccSBarry Smith   if (!flg) {
2879566063dSJacob Faibussowitsch     PetscCall(PCGetOptionsPrefix(pc,&prefix));
2889566063dSJacob Faibussowitsch     PetscCall(KSPSetOptionsPrefix(jac->ksp,prefix));
2899566063dSJacob Faibussowitsch     PetscCall(KSPAppendOptionsPrefix(jac->ksp,"galerkin_"));
2904ac220ccSBarry Smith   }
2914ac220ccSBarry Smith 
2929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHead(PetscOptionsObject,"Galerkin options"));
2934ac220ccSBarry Smith   if (jac->ksp) {
2949566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(jac->ksp));
2954ac220ccSBarry Smith   }
2969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsTail());
2974ac220ccSBarry Smith   PetscFunctionReturn(0);
2984ac220ccSBarry Smith }
2992a6744ebSBarry Smith 
3002a6744ebSBarry Smith /* -------------------------------------------------------------------------------------------*/
3012a6744ebSBarry Smith 
3022a6744ebSBarry Smith /*MC
3032a6744ebSBarry Smith      PCGALERKIN - Build (part of) a preconditioner by P S R (where P is often R^T)
3042a6744ebSBarry Smith 
3052a6744ebSBarry Smith $   Use PCGalerkinSetRestriction(pc,R) and/or PCGalerkinSetInterpolation(pc,P) followed by
3067817a140SBarry Smith $   PCGalerkinGetKSP(pc,&ksp); KSPSetOperators(ksp,A,....)
3072a6744ebSBarry Smith 
3082a6744ebSBarry Smith    Level: intermediate
3092a6744ebSBarry Smith 
310b59c8b46SBarry Smith    Developer Note: If KSPSetOperators() has not been called on the inner KSP then PCGALERKIN could use MatRARt() or MatPtAP() to compute
3117817a140SBarry Smith                    the operators automatically.
3127817a140SBarry Smith                    Should there be a prefix for the inner KSP.
3137817a140SBarry Smith                    There is no KSPSetFromOptions_Galerkin() that calls KSPSetFromOptions() on the inner KSP
3147817a140SBarry Smith 
3152a6744ebSBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
3162a6744ebSBarry Smith            PCSHELL, PCKSP, PCGalerkinSetRestriction(), PCGalerkinSetInterpolation(), PCGalerkinGetKSP()
3172a6744ebSBarry Smith 
3182a6744ebSBarry Smith M*/
3192a6744ebSBarry Smith 
3208cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_Galerkin(PC pc)
3212a6744ebSBarry Smith {
3222a6744ebSBarry Smith   PC_Galerkin    *jac;
3232a6744ebSBarry Smith 
3242a6744ebSBarry Smith   PetscFunctionBegin;
3259566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc,&jac));
3262fa5cd67SKarl Rupp 
3272a6744ebSBarry Smith   pc->ops->apply           = PCApply_Galerkin;
3282a6744ebSBarry Smith   pc->ops->setup           = PCSetUp_Galerkin;
329a06653b4SBarry Smith   pc->ops->reset           = PCReset_Galerkin;
3302a6744ebSBarry Smith   pc->ops->destroy         = PCDestroy_Galerkin;
3312a6744ebSBarry Smith   pc->ops->view            = PCView_Galerkin;
3324ac220ccSBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_Galerkin;
3334ac220ccSBarry Smith   pc->ops->applyrichardson = NULL;
3342a6744ebSBarry Smith 
3359566063dSJacob Faibussowitsch   PetscCall(KSPCreate(PetscObjectComm((PetscObject)pc),&jac->ksp));
3369566063dSJacob Faibussowitsch   PetscCall(KSPSetErrorIfNotConverged(jac->ksp,pc->erroriffailure));
3379566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)jac->ksp,(PetscObject)pc,1));
3382a6744ebSBarry Smith 
3392a6744ebSBarry Smith   pc->data = (void*)jac;
3402a6744ebSBarry Smith 
3419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGalerkinSetRestriction_C",PCGalerkinSetRestriction_Galerkin));
3429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGalerkinSetInterpolation_C",PCGalerkinSetInterpolation_Galerkin));
3439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGalerkinGetKSP_C",PCGalerkinGetKSP_Galerkin));
3449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGalerkinSetComputeSubmatrix_C",PCGalerkinSetComputeSubmatrix_Galerkin));
3452a6744ebSBarry Smith   PetscFunctionReturn(0);
3462a6744ebSBarry Smith }
347