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