Actual source code: shellpc.c

  1: /*
  2:    This provides a simple shell for Fortran (and C programmers) to
  3:   create their own preconditioner without writing much interface code.
  4: */

  6: #include <petsc/private/pcimpl.h>

  8: typedef struct {
  9:   PetscCtx ctx; /* user provided contexts for preconditioner */

 11:   PetscErrorCode (*destroy)(PC);
 12:   PetscErrorCode (*setup)(PC);
 13:   PetscErrorCode (*apply)(PC, Vec, Vec);
 14:   PetscErrorCode (*matapply)(PC, Mat, Mat);
 15:   PetscErrorCode (*applysymmetricleft)(PC, Vec, Vec);
 16:   PetscErrorCode (*applysymmetricright)(PC, Vec, Vec);
 17:   PetscErrorCode (*applyBA)(PC, PCSide, Vec, Vec, Vec);
 18:   PetscErrorCode (*presolve)(PC, KSP, Vec, Vec);
 19:   PetscErrorCode (*postsolve)(PC, KSP, Vec, Vec);
 20:   PetscErrorCode (*view)(PC, PetscViewer);
 21:   PetscErrorCode (*applytranspose)(PC, Vec, Vec);
 22:   PetscErrorCode (*matapplytranspose)(PC, Mat, Mat);
 23:   PetscErrorCode (*applyrich)(PC, Vec, Vec, Vec, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *);
 24:   PetscErrorCode (*matapplyrich)(PC, Mat, Mat, Mat, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *);

 26:   char *name;
 27: } PC_Shell;

 29: /*@
 30:   PCShellGetContext - Returns the user-provided context associated with a shell `PC` that was provided with `PCShellSetContext()`

 32:   Not Collective

 34:   Input Parameter:
 35: . pc - of type `PCSHELL`

 37:   Output Parameter:
 38: . ctx - the user provided context

 40:   Level: advanced

 42:   Note:
 43:   This routine is intended for use within the various user-provided routines set with, for example, `PCShellSetApply()`

 45:   Fortran Notes:
 46:   This only works when the context is a Fortran derived type or a `PetscObject`. Define `ctx` with
 47: .vb
 48:   type(tUsertype), pointer :: ctx
 49: .ve

 51: .seealso: [](ch_ksp), `PC`, `PCSHELL`, `PCShellSetContext()`, `PCShellSetApply()`, `PCShellSetDestroy()`
 52: @*/
 53: PetscErrorCode PCShellGetContext(PC pc, PetscCtxRt ctx)
 54: {
 55:   PetscBool flg;

 57:   PetscFunctionBegin;
 59:   PetscAssertPointer(ctx, 2);
 60:   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCSHELL, &flg));
 61:   if (!flg) *(void **)ctx = NULL;
 62:   else *(void **)ctx = ((PC_Shell *)pc->data)->ctx;
 63:   PetscFunctionReturn(PETSC_SUCCESS);
 64: }

 66: /*@
 67:   PCShellSetContext - sets the context for a shell `PC` that can be accessed with `PCShellGetContext()`

 69:   Logically Collective

 71:   Input Parameters:
 72: + pc  - the `PC` of type `PCSHELL`
 73: - ctx - the context

 75:   Level: advanced

 77:   Notes:
 78:   This routine is intended for use within the various user-provided routines set with, for example, `PCShellSetApply()`

 80:   One should also provide a routine to destroy the context when `pc` is destroyed with `PCShellSetDestroy()`

 82:   Fortran Notes:
 83:   To use this from Fortran you must write a Fortran interface definition for this
 84:   function that tells Fortran the Fortran derived data type that you are passing in as the `ctx` argument.

 86: .seealso: [](ch_ksp), `PC`, `PCShellGetContext()`, `PCSHELL`, `PCShellSetApply()`, `PCShellSetDestroy()`
 87: @*/
 88: PetscErrorCode PCShellSetContext(PC pc, PetscCtx ctx)
 89: {
 90:   PC_Shell *shell = (PC_Shell *)pc->data;
 91:   PetscBool flg;

 93:   PetscFunctionBegin;
 95:   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCSHELL, &flg));
 96:   if (flg) shell->ctx = ctx;
 97:   PetscFunctionReturn(PETSC_SUCCESS);
 98: }

100: static PetscErrorCode PCSetUp_Shell(PC pc)
101: {
102:   PC_Shell *shell = (PC_Shell *)pc->data;

104:   PetscFunctionBegin;
105:   PetscCheck(shell->setup, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No setup() routine provided to Shell PC");
106:   PetscCallBack("PCSHELL callback setup", (*shell->setup)(pc));
107:   PetscFunctionReturn(PETSC_SUCCESS);
108: }

110: static PetscErrorCode PCApply_Shell(PC pc, Vec x, Vec y)
111: {
112:   PC_Shell        *shell = (PC_Shell *)pc->data;
113:   PetscObjectState instate, outstate;

115:   PetscFunctionBegin;
116:   PetscCheck(shell->apply, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No apply() routine provided to Shell PC");
117:   PetscCall(PetscObjectStateGet((PetscObject)y, &instate));
118:   PetscCallBack("PCSHELL callback apply", (*shell->apply)(pc, x, y));
119:   PetscCall(PetscObjectStateGet((PetscObject)y, &outstate));
120:   /* increase the state of the output vector if the user did not update its state themself as should have been done */
121:   if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)y));
122:   PetscFunctionReturn(PETSC_SUCCESS);
123: }

125: static PetscErrorCode PCMatApply_Shell(PC pc, Mat X, Mat Y)
126: {
127:   PC_Shell        *shell = (PC_Shell *)pc->data;
128:   PetscObjectState instate, outstate;

130:   PetscFunctionBegin;
131:   PetscCheck(shell->matapply, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No apply() routine provided to Shell PC");
132:   PetscCall(PetscObjectStateGet((PetscObject)Y, &instate));
133:   PetscCallBack("PCSHELL callback apply", (*shell->matapply)(pc, X, Y));
134:   PetscCall(PetscObjectStateGet((PetscObject)Y, &outstate));
135:   /* increase the state of the output vector if the user did not update its state themself as should have been done */
136:   if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)Y));
137:   PetscFunctionReturn(PETSC_SUCCESS);
138: }

140: static PetscErrorCode PCApplySymmetricLeft_Shell(PC pc, Vec x, Vec y)
141: {
142:   PC_Shell *shell = (PC_Shell *)pc->data;

144:   PetscFunctionBegin;
145:   PetscCheck(shell->applysymmetricleft, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No apply() routine provided to Shell PC");
146:   PetscCallBack("PCSHELL callback apply symmetric left", (*shell->applysymmetricleft)(pc, x, y));
147:   PetscFunctionReturn(PETSC_SUCCESS);
148: }

150: static PetscErrorCode PCApplySymmetricRight_Shell(PC pc, Vec x, Vec y)
151: {
152:   PC_Shell *shell = (PC_Shell *)pc->data;

154:   PetscFunctionBegin;
155:   PetscCheck(shell->applysymmetricright, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No apply() routine provided to Shell PC");
156:   PetscCallBack("PCSHELL callback apply symmetric right", (*shell->applysymmetricright)(pc, x, y));
157:   PetscFunctionReturn(PETSC_SUCCESS);
158: }

160: static PetscErrorCode PCApplyBA_Shell(PC pc, PCSide side, Vec x, Vec y, Vec w)
161: {
162:   PC_Shell        *shell = (PC_Shell *)pc->data;
163:   PetscObjectState instate, outstate;

165:   PetscFunctionBegin;
166:   PetscCheck(shell->applyBA, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No applyBA() routine provided to Shell PC");
167:   PetscCall(PetscObjectStateGet((PetscObject)w, &instate));
168:   PetscCallBack("PCSHELL callback applyBA", (*shell->applyBA)(pc, side, x, y, w));
169:   PetscCall(PetscObjectStateGet((PetscObject)w, &outstate));
170:   /* increase the state of the output vector if the user did not update its state themself as should have been done */
171:   if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)w));
172:   PetscFunctionReturn(PETSC_SUCCESS);
173: }

175: static PetscErrorCode PCPreSolveChangeRHS_Shell(PC pc, PetscBool *change)
176: {
177:   PetscFunctionBegin;
178:   *change = PETSC_TRUE;
179:   PetscFunctionReturn(PETSC_SUCCESS);
180: }

182: static PetscErrorCode PCPreSolve_Shell(PC pc, KSP ksp, Vec b, Vec x)
183: {
184:   PC_Shell *shell = (PC_Shell *)pc->data;

186:   PetscFunctionBegin;
187:   PetscCheck(shell->presolve, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No presolve() routine provided to Shell PC");
188:   PetscCallBack("PCSHELL callback presolve", (*shell->presolve)(pc, ksp, b, x));
189:   PetscFunctionReturn(PETSC_SUCCESS);
190: }

192: static PetscErrorCode PCPostSolve_Shell(PC pc, KSP ksp, Vec b, Vec x)
193: {
194:   PC_Shell *shell = (PC_Shell *)pc->data;

196:   PetscFunctionBegin;
197:   PetscCheck(shell->postsolve, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No postsolve() routine provided to Shell PC");
198:   PetscCallBack("PCSHELL callback postsolve()", (*shell->postsolve)(pc, ksp, b, x));
199:   PetscFunctionReturn(PETSC_SUCCESS);
200: }

202: static PetscErrorCode PCApplyTranspose_Shell(PC pc, Vec x, Vec y)
203: {
204:   PC_Shell        *shell = (PC_Shell *)pc->data;
205:   PetscObjectState instate, outstate;

207:   PetscFunctionBegin;
208:   PetscCheck(shell->applytranspose, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No applytranspose() routine provided to Shell PC");
209:   PetscCall(PetscObjectStateGet((PetscObject)y, &instate));
210:   PetscCallBack("PCSHELL callback applytranspose", (*shell->applytranspose)(pc, x, y));
211:   PetscCall(PetscObjectStateGet((PetscObject)y, &outstate));
212:   /* increase the state of the output vector if the user did not update its state themself as should have been done */
213:   if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)y));
214:   PetscFunctionReturn(PETSC_SUCCESS);
215: }

217: static PetscErrorCode PCMatApplyTranspose_Shell(PC pc, Mat x, Mat y)
218: {
219:   PC_Shell        *shell = (PC_Shell *)pc->data;
220:   PetscObjectState instate, outstate;

222:   PetscFunctionBegin;
223:   PetscCheck(shell->matapplytranspose, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No matapplytranspose() routine provided to Shell PC");
224:   PetscCall(PetscObjectStateGet((PetscObject)y, &instate));
225:   PetscCallBack("PCSHELL callback matapplytranspose", (*shell->matapplytranspose)(pc, x, y));
226:   PetscCall(PetscObjectStateGet((PetscObject)y, &outstate));
227:   /* increase the state of the output matrix if the user did not update its state themself as should have been done */
228:   if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)y));
229:   PetscFunctionReturn(PETSC_SUCCESS);
230: }

232: static PetscErrorCode PCApplyRichardson_Shell(PC pc, Vec x, Vec y, Vec w, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt it, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
233: {
234:   PC_Shell        *shell = (PC_Shell *)pc->data;
235:   PetscObjectState instate, outstate;

237:   PetscFunctionBegin;
238:   PetscCheck(shell->applyrich, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No applyrichardson() routine provided to Shell PC");
239:   PetscCall(PetscObjectStateGet((PetscObject)y, &instate));
240:   PetscCallBack("PCSHELL callback applyrichardson", (*shell->applyrich)(pc, x, y, w, rtol, abstol, dtol, it, guesszero, outits, reason));
241:   PetscCall(PetscObjectStateGet((PetscObject)y, &outstate));
242:   /* increase the state of the output vector since the user did not update its state themself as should have been done */
243:   if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)y));
244:   PetscFunctionReturn(PETSC_SUCCESS);
245: }

247: static PetscErrorCode PCMatApplyRichardson_Shell(PC pc, Mat B, Mat Y, Mat W, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt it, PetscBool guesszero, PetscInt *outits, PCRichardsonConvergedReason *reason)
248: {
249:   PC_Shell        *shell = (PC_Shell *)pc->data;
250:   PetscObjectState instate, outstate;

252:   PetscFunctionBegin;
253:   PetscCheck(shell->matapplyrich, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "No matapplyrichardson() routine provided to Shell PC");
254:   PetscCall(PetscObjectStateGet((PetscObject)Y, &instate));
255:   PetscCallBack("PCSHELL callback matapplyrichardson", (*shell->matapplyrich)(pc, B, Y, W, rtol, abstol, dtol, it, guesszero, outits, reason));
256:   PetscCall(PetscObjectStateGet((PetscObject)Y, &outstate));
257:   /* increase the state of the output block of vectors since the user did not update its state themself as should have been done */
258:   if (instate == outstate) PetscCall(PetscObjectStateIncrease((PetscObject)Y));
259:   PetscFunctionReturn(PETSC_SUCCESS);
260: }

262: static PetscErrorCode PCDestroy_Shell(PC pc)
263: {
264:   PC_Shell *shell = (PC_Shell *)pc->data;

266:   PetscFunctionBegin;
267:   PetscCall(PetscFree(shell->name));
268:   if (shell->destroy) PetscCallBack("PCSHELL callback destroy", (*shell->destroy)(pc));
269:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetDestroy_C", NULL));
270:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetSetUp_C", NULL));
271:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApply_C", NULL));
272:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetMatApply_C", NULL));
273:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplySymmetricLeft_C", NULL));
274:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplySymmetricRight_C", NULL));
275:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyBA_C", NULL));
276:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetPreSolve_C", NULL));
277:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetPostSolve_C", NULL));
278:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetView_C", NULL));
279:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyTranspose_C", NULL));
280:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetMatApplyTranspose_C", NULL));
281:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetName_C", NULL));
282:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellGetName_C", NULL));
283:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyRichardson_C", NULL));
284:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetMatApplyRichardson_C", NULL));
285:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL));
286:   PetscCall(PetscFree(pc->data));
287:   PetscFunctionReturn(PETSC_SUCCESS);
288: }

290: static PetscErrorCode PCView_Shell(PC pc, PetscViewer viewer)
291: {
292:   PC_Shell *shell = (PC_Shell *)pc->data;
293:   PetscBool isascii;

295:   PetscFunctionBegin;
296:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
297:   if (isascii) {
298:     if (shell->name) PetscCall(PetscViewerASCIIPrintf(viewer, "  %s\n", shell->name));
299:     else PetscCall(PetscViewerASCIIPrintf(viewer, "  no name\n"));
300:   }
301:   if (shell->view) {
302:     PetscCall(PetscViewerASCIIPushTab(viewer));
303:     PetscCall((*shell->view)(pc, viewer));
304:     PetscCall(PetscViewerASCIIPopTab(viewer));
305:   }
306:   PetscFunctionReturn(PETSC_SUCCESS);
307: }

309: static PetscErrorCode PCShellSetDestroy_Shell(PC pc, PetscErrorCode (*destroy)(PC))
310: {
311:   PC_Shell *shell = (PC_Shell *)pc->data;

313:   PetscFunctionBegin;
314:   shell->destroy = destroy;
315:   PetscFunctionReturn(PETSC_SUCCESS);
316: }

318: static PetscErrorCode PCShellSetSetUp_Shell(PC pc, PetscErrorCode (*setup)(PC))
319: {
320:   PC_Shell *shell = (PC_Shell *)pc->data;

322:   PetscFunctionBegin;
323:   shell->setup = setup;
324:   if (setup) pc->ops->setup = PCSetUp_Shell;
325:   else pc->ops->setup = NULL;
326:   PetscFunctionReturn(PETSC_SUCCESS);
327: }

329: static PetscErrorCode PCShellSetApply_Shell(PC pc, PetscErrorCode (*apply)(PC, Vec, Vec))
330: {
331:   PC_Shell *shell = (PC_Shell *)pc->data;

333:   PetscFunctionBegin;
334:   shell->apply = apply;
335:   PetscFunctionReturn(PETSC_SUCCESS);
336: }

338: static PetscErrorCode PCShellSetMatApply_Shell(PC pc, PetscErrorCode (*matapply)(PC, Mat, Mat))
339: {
340:   PC_Shell *shell = (PC_Shell *)pc->data;

342:   PetscFunctionBegin;
343:   shell->matapply = matapply;
344:   if (matapply) pc->ops->matapply = PCMatApply_Shell;
345:   else pc->ops->matapply = NULL;
346:   PetscFunctionReturn(PETSC_SUCCESS);
347: }

349: static PetscErrorCode PCShellSetApplySymmetricLeft_Shell(PC pc, PetscErrorCode (*apply)(PC, Vec, Vec))
350: {
351:   PC_Shell *shell = (PC_Shell *)pc->data;

353:   PetscFunctionBegin;
354:   shell->applysymmetricleft = apply;
355:   PetscFunctionReturn(PETSC_SUCCESS);
356: }

358: static PetscErrorCode PCShellSetApplySymmetricRight_Shell(PC pc, PetscErrorCode (*apply)(PC, Vec, Vec))
359: {
360:   PC_Shell *shell = (PC_Shell *)pc->data;

362:   PetscFunctionBegin;
363:   shell->applysymmetricright = apply;
364:   PetscFunctionReturn(PETSC_SUCCESS);
365: }

367: static PetscErrorCode PCShellSetApplyBA_Shell(PC pc, PetscErrorCode (*applyBA)(PC, PCSide, Vec, Vec, Vec))
368: {
369:   PC_Shell *shell = (PC_Shell *)pc->data;

371:   PetscFunctionBegin;
372:   shell->applyBA = applyBA;
373:   if (applyBA) pc->ops->applyBA = PCApplyBA_Shell;
374:   else pc->ops->applyBA = NULL;
375:   PetscFunctionReturn(PETSC_SUCCESS);
376: }

378: static PetscErrorCode PCShellSetPreSolve_Shell(PC pc, PCShellPSolveFn *presolve)
379: {
380:   PC_Shell *shell = (PC_Shell *)pc->data;

382:   PetscFunctionBegin;
383:   shell->presolve = presolve;
384:   if (presolve) {
385:     pc->ops->presolve = PCPreSolve_Shell;
386:     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_Shell));
387:   } else {
388:     pc->ops->presolve = NULL;
389:     PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL));
390:   }
391:   PetscFunctionReturn(PETSC_SUCCESS);
392: }

394: static PetscErrorCode PCShellSetPostSolve_Shell(PC pc, PCShellPSolveFn *postsolve)
395: {
396:   PC_Shell *shell = (PC_Shell *)pc->data;

398:   PetscFunctionBegin;
399:   shell->postsolve = postsolve;
400:   if (postsolve) pc->ops->postsolve = PCPostSolve_Shell;
401:   else pc->ops->postsolve = NULL;
402:   PetscFunctionReturn(PETSC_SUCCESS);
403: }

405: static PetscErrorCode PCShellSetView_Shell(PC pc, PetscErrorCode (*view)(PC, PetscViewer))
406: {
407:   PC_Shell *shell = (PC_Shell *)pc->data;

409:   PetscFunctionBegin;
410:   shell->view = view;
411:   PetscFunctionReturn(PETSC_SUCCESS);
412: }

414: static PetscErrorCode PCShellSetApplyTranspose_Shell(PC pc, PetscErrorCode (*applytranspose)(PC, Vec, Vec))
415: {
416:   PC_Shell *shell = (PC_Shell *)pc->data;

418:   PetscFunctionBegin;
419:   shell->applytranspose = applytranspose;
420:   if (applytranspose) pc->ops->applytranspose = PCApplyTranspose_Shell;
421:   else pc->ops->applytranspose = NULL;
422:   PetscFunctionReturn(PETSC_SUCCESS);
423: }

425: static PetscErrorCode PCShellSetMatApplyTranspose_Shell(PC pc, PetscErrorCode (*matapplytranspose)(PC, Mat, Mat))
426: {
427:   PC_Shell *shell = (PC_Shell *)pc->data;

429:   PetscFunctionBegin;
430:   shell->matapplytranspose = matapplytranspose;
431:   if (matapplytranspose) pc->ops->matapplytranspose = PCMatApplyTranspose_Shell;
432:   else pc->ops->matapplytranspose = NULL;
433:   PetscFunctionReturn(PETSC_SUCCESS);
434: }

436: static PetscErrorCode PCShellSetApplyRichardson_Shell(PC pc, PetscErrorCode (*applyrich)(PC, Vec, Vec, Vec, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *))
437: {
438:   PC_Shell *shell = (PC_Shell *)pc->data;

440:   PetscFunctionBegin;
441:   shell->applyrich = applyrich;
442:   if (applyrich) pc->ops->applyrichardson = PCApplyRichardson_Shell;
443:   else pc->ops->applyrichardson = NULL;
444:   PetscFunctionReturn(PETSC_SUCCESS);
445: }

447: static PetscErrorCode PCShellSetMatApplyRichardson_Shell(PC pc, PetscErrorCode (*matapplyrich)(PC, Mat, Mat, Mat, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *))
448: {
449:   PC_Shell *shell = (PC_Shell *)pc->data;

451:   PetscFunctionBegin;
452:   shell->matapplyrich = matapplyrich;
453:   if (matapplyrich) pc->ops->matapplyrichardson = PCMatApplyRichardson_Shell;
454:   else pc->ops->matapplyrichardson = NULL;
455:   PetscFunctionReturn(PETSC_SUCCESS);
456: }

458: static PetscErrorCode PCShellSetName_Shell(PC pc, const char name[])
459: {
460:   PC_Shell *shell = (PC_Shell *)pc->data;

462:   PetscFunctionBegin;
463:   PetscCall(PetscFree(shell->name));
464:   PetscCall(PetscStrallocpy(name, &shell->name));
465:   PetscFunctionReturn(PETSC_SUCCESS);
466: }

468: static PetscErrorCode PCShellGetName_Shell(PC pc, const char *name[])
469: {
470:   PC_Shell *shell = (PC_Shell *)pc->data;

472:   PetscFunctionBegin;
473:   *name = shell->name;
474:   PetscFunctionReturn(PETSC_SUCCESS);
475: }

477: /*@
478:   PCShellSetDestroy - Sets routine to use to destroy the user-provided application context that was provided with `PCShellSetContext()`

480:   Logically Collective

482:   Input Parameters:
483: + pc      - the preconditioner context
484: - destroy - the application-provided destroy routine

486:   Calling sequence of `destroy`:
487: . pc - the preconditioner

489:   Level: intermediate

491: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApply()`, `PCShellSetContext()`, `PCShellGetContext()`
492: @*/
493: PetscErrorCode PCShellSetDestroy(PC pc, PetscErrorCode (*destroy)(PC pc))
494: {
495:   PetscFunctionBegin;
497:   PetscTryMethod(pc, "PCShellSetDestroy_C", (PC, PetscErrorCode (*)(PC)), (pc, destroy));
498:   PetscFunctionReturn(PETSC_SUCCESS);
499: }

501: /*@
502:   PCShellSetSetUp - Sets routine to use to "setup" the preconditioner whenever the
503:   matrix operator is changed.

505:   Logically Collective

507:   Input Parameters:
508: + pc    - the preconditioner context
509: - setup - the application-provided setup routine

511:   Calling sequence of `setup`:
512: . pc - the preconditioner

514:   Level: intermediate

516:   Note:
517:   You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `setup`.

519: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetApply()`, `PCShellSetContext()`, `PCShellGetContext()`
520: @*/
521: PetscErrorCode PCShellSetSetUp(PC pc, PetscErrorCode (*setup)(PC pc))
522: {
523:   PetscFunctionBegin;
525:   PetscTryMethod(pc, "PCShellSetSetUp_C", (PC, PetscErrorCode (*)(PC)), (pc, setup));
526:   PetscFunctionReturn(PETSC_SUCCESS);
527: }

529: /*@
530:   PCShellSetView - Sets routine to use as viewer of a `PCSHELL` shell preconditioner

532:   Logically Collective

534:   Input Parameters:
535: + pc   - the preconditioner context
536: - view - the application-provided view routine

538:   Calling sequence of `view`:
539: + pc - the preconditioner
540: - v  - viewer

542:   Level: advanced

544:   Note:
545:   You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `view`.

547: .seealso: [](ch_ksp), `PC`, `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`, `PCShellGetContext()`
548: @*/
549: PetscErrorCode PCShellSetView(PC pc, PetscErrorCode (*view)(PC pc, PetscViewer v))
550: {
551:   PetscFunctionBegin;
553:   PetscTryMethod(pc, "PCShellSetView_C", (PC, PetscErrorCode (*)(PC, PetscViewer)), (pc, view));
554:   PetscFunctionReturn(PETSC_SUCCESS);
555: }

557: /*@
558:   PCShellSetApply - Sets routine to use as preconditioner.

560:   Logically Collective

562:   Input Parameters:
563: + pc    - the preconditioner context
564: - apply - the application-provided preconditioning routine

566:   Calling sequence of `apply`:
567: + pc   - the preconditioner, get the application context with `PCShellGetContext()`
568: . xin  - input vector
569: - xout - output vector

571:   Level: intermediate

573:   Note:
574:   You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `apply`.

576: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`, `PCShellSetApplyBA()`, `PCShellSetApplySymmetricRight()`, `PCShellSetApplySymmetricLeft()`, `PCShellGetContext()`
577: @*/
578: PetscErrorCode PCShellSetApply(PC pc, PetscErrorCode (*apply)(PC pc, Vec xin, Vec xout))
579: {
580:   PetscFunctionBegin;
582:   PetscTryMethod(pc, "PCShellSetApply_C", (PC, PetscErrorCode (*)(PC, Vec, Vec)), (pc, apply));
583:   PetscFunctionReturn(PETSC_SUCCESS);
584: }

586: /*@
587:   PCShellSetMatApply - Sets routine to use as preconditioner on a block of vectors.

589:   Logically Collective

591:   Input Parameters:
592: + pc       - the preconditioner context
593: - matapply - the application-provided preconditioning routine

595:   Calling sequence of `matapply`:
596: + pc   - the preconditioner
597: . Xin  - input block of vectors represented as a dense `Mat`
598: - Xout - output block of vectors represented as a dense `Mat`

600:   Level: advanced

602:   Note:
603:   You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `matapply`.

605: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApply()`, `PCShellSetContext()`, `PCShellGetContext()`
606: @*/
607: PetscErrorCode PCShellSetMatApply(PC pc, PetscErrorCode (*matapply)(PC pc, Mat Xin, Mat Xout))
608: {
609:   PetscFunctionBegin;
611:   PetscTryMethod(pc, "PCShellSetMatApply_C", (PC, PetscErrorCode (*)(PC, Mat, Mat)), (pc, matapply));
612:   PetscFunctionReturn(PETSC_SUCCESS);
613: }

615: /*@
616:   PCShellSetApplySymmetricLeft - Sets routine to use as left preconditioner (when the `PC_SYMMETRIC` is used).

618:   Logically Collective

620:   Input Parameters:
621: + pc    - the preconditioner context
622: - apply - the application-provided left preconditioning routine

624:   Calling sequence of `apply`:
625: + pc   - the preconditioner
626: . xin  - input vector
627: - xout - output vector

629:   Level: advanced

631:   Note:
632:   You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `apply`.

634: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApply()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`
635: @*/
636: PetscErrorCode PCShellSetApplySymmetricLeft(PC pc, PetscErrorCode (*apply)(PC pc, Vec xin, Vec xout))
637: {
638:   PetscFunctionBegin;
640:   PetscTryMethod(pc, "PCShellSetApplySymmetricLeft_C", (PC, PetscErrorCode (*)(PC, Vec, Vec)), (pc, apply));
641:   PetscFunctionReturn(PETSC_SUCCESS);
642: }

644: /*@
645:   PCShellSetApplySymmetricRight - Sets routine to use as right preconditioner (when the `PC_SYMMETRIC` is used).

647:   Logically Collective

649:   Input Parameters:
650: + pc    - the preconditioner context
651: - apply - the application-provided right preconditioning routine

653:   Calling sequence of `apply`:
654: + pc   - the preconditioner
655: . xin  - input vector
656: - xout - output vector

658:   Level: advanced

660:   Note:
661:   You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `apply`.

663: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApply()`, `PCShellSetApplySymmetricLeft()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`, `PCShellGetContext()`
664: @*/
665: PetscErrorCode PCShellSetApplySymmetricRight(PC pc, PetscErrorCode (*apply)(PC pc, Vec xin, Vec xout))
666: {
667:   PetscFunctionBegin;
669:   PetscTryMethod(pc, "PCShellSetApplySymmetricRight_C", (PC, PetscErrorCode (*)(PC, Vec, Vec)), (pc, apply));
670:   PetscFunctionReturn(PETSC_SUCCESS);
671: }

673: /*@
674:   PCShellSetApplyBA - Sets routine to use as the preconditioner times the operator.

676:   Logically Collective

678:   Input Parameters:
679: + pc      - the preconditioner context
680: - applyBA - the application-provided BA routine

682:   Calling sequence of `applyBA`:
683: + pc   - the preconditioner
684: . side - `PC_LEFT`, `PC_RIGHT`, or `PC_SYMMETRIC`
685: . xin  - input vector
686: . xout - output vector
687: - w    - work vector

689:   Level: intermediate

691:   Note:
692:   You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `applyBA`.

694: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetContext()`, `PCShellSetApply()`, `PCShellGetContext()`, `PCSide`
695: @*/
696: PetscErrorCode PCShellSetApplyBA(PC pc, PetscErrorCode (*applyBA)(PC pc, PCSide side, Vec xin, Vec xout, Vec w))
697: {
698:   PetscFunctionBegin;
700:   PetscTryMethod(pc, "PCShellSetApplyBA_C", (PC, PetscErrorCode (*)(PC, PCSide, Vec, Vec, Vec)), (pc, applyBA));
701:   PetscFunctionReturn(PETSC_SUCCESS);
702: }

704: /*@
705:   PCShellSetApplyTranspose - Sets routine to use as preconditioner transpose.

707:   Logically Collective

709:   Input Parameters:
710: + pc             - the preconditioner context
711: - applytranspose - the application-provided preconditioning transpose routine

713:   Calling sequence of `applytranspose`:
714: + pc   - the preconditioner
715: . xin  - input vector
716: - xout - output vector

718:   Level: intermediate

720:   Note:
721:   You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `applytranspose`.

723: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApply()`, `PCShellSetContext()`, `PCShellSetApplyBA()`, `PCShellGetContext()`
724: @*/
725: PetscErrorCode PCShellSetApplyTranspose(PC pc, PetscErrorCode (*applytranspose)(PC pc, Vec xin, Vec xout))
726: {
727:   PetscFunctionBegin;
729:   PetscTryMethod(pc, "PCShellSetApplyTranspose_C", (PC, PetscErrorCode (*)(PC, Vec, Vec)), (pc, applytranspose));
730:   PetscFunctionReturn(PETSC_SUCCESS);
731: }

733: /*@
734:   PCShellSetMatApplyTranspose - Sets routine to use as preconditioner transpose.

736:   Logically Collective

738:   Input Parameters:
739: + pc                - the preconditioner context
740: - matapplytranspose - the application-provided preconditioning transpose routine

742:   Calling sequence of `matapplytranspose`:
743: + pc   - the preconditioner
744: . xin  - input matrix
745: - xout - output matrix

747:   Level: intermediate

749:   Note:
750:   You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `matapplytranspose`.

752: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApply()`, `PCShellSetContext()`, `PCShellSetApplyBA()`, `PCShellGetContext()`
753: @*/
754: PetscErrorCode PCShellSetMatApplyTranspose(PC pc, PetscErrorCode (*matapplytranspose)(PC pc, Mat xin, Mat xout))
755: {
756:   PetscFunctionBegin;
758:   PetscTryMethod(pc, "PCShellSetMatApplyTranspose_C", (PC, PetscErrorCode (*)(PC, Mat, Mat)), (pc, matapplytranspose));
759:   PetscFunctionReturn(PETSC_SUCCESS);
760: }

762: /*@
763:   PCShellSetPreSolve - Sets routine to apply to the operators/vectors before a `KSPSolve()` is
764:   applied. This usually does something like scale the linear system in some application
765:   specific way.

767:   Logically Collective

769:   Input Parameters:
770: + pc       - the preconditioner context
771: - presolve - the application-provided presolve routine, see `PCShellPSolveFn`

773:   Level: advanced

775:   Note:
776:   You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `presolve`.

778: .seealso: [](ch_ksp), `PCSHELL`, `PCShellPSolveFn`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetPostSolve()`, `PCShellSetContext()`, `PCShellGetContext()`
779: @*/
780: PetscErrorCode PCShellSetPreSolve(PC pc, PCShellPSolveFn *presolve)
781: {
782:   PetscFunctionBegin;
784:   PetscTryMethod(pc, "PCShellSetPreSolve_C", (PC, PCShellPSolveFn *), (pc, presolve));
785:   PetscFunctionReturn(PETSC_SUCCESS);
786: }

788: /*@
789:   PCShellSetPostSolve - Sets routine to apply to the operators/vectors after a `KSPSolve()` is
790:   applied. This usually does something like scale the linear system in some application
791:   specific way.

793:   Logically Collective

795:   Input Parameters:
796: + pc        - the preconditioner context
797: - postsolve - the application-provided postsolve routine, see `PCShellPSolveFn`

799:   Level: advanced

801:   Note:
802:   You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `postsolve`.

804: .seealso: [](ch_ksp), `PCSHELL`, `PCShellPSolveFn`, `PCShellSetApplyRichardson()`, `PCShellSetSetUp()`, `PCShellSetApplyTranspose()`, `PCShellSetPreSolve()`, `PCShellSetContext()`, `PCShellGetContext()`
805: @*/
806: PetscErrorCode PCShellSetPostSolve(PC pc, PCShellPSolveFn *postsolve)
807: {
808:   PetscFunctionBegin;
810:   PetscTryMethod(pc, "PCShellSetPostSolve_C", (PC, PCShellPSolveFn *), (pc, postsolve));
811:   PetscFunctionReturn(PETSC_SUCCESS);
812: }

814: /*@
815:   PCShellSetName - Sets an optional name to associate with a `PCSHELL`
816:   preconditioner.

818:   Not Collective

820:   Input Parameters:
821: + pc   - the preconditioner context
822: - name - character string describing shell preconditioner

824:   Level: intermediate

826:   Note:
827:   This is separate from the name you can provide with `PetscObjectSetName()`

829: .seealso: [](ch_ksp), `PCSHELL`, `PCShellGetName()`, `PetscObjectSetName()`, `PetscObjectGetName()`
830: @*/
831: PetscErrorCode PCShellSetName(PC pc, const char name[])
832: {
833:   PetscFunctionBegin;
835:   PetscTryMethod(pc, "PCShellSetName_C", (PC, const char[]), (pc, name));
836:   PetscFunctionReturn(PETSC_SUCCESS);
837: }

839: /*@
840:   PCShellGetName - Gets an optional name that the user has set for a `PCSHELL` with `PCShellSetName()`
841:   preconditioner.

843:   Not Collective

845:   Input Parameter:
846: . pc - the preconditioner context

848:   Output Parameter:
849: . name - character string describing shell preconditioner (you should not free this)

851:   Level: intermediate

853: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetName()`, `PetscObjectSetName()`, `PetscObjectGetName()`
854: @*/
855: PetscErrorCode PCShellGetName(PC pc, const char *name[])
856: {
857:   PetscFunctionBegin;
859:   PetscAssertPointer(name, 2);
860:   PetscUseMethod(pc, "PCShellGetName_C", (PC, const char *[]), (pc, name));
861:   PetscFunctionReturn(PETSC_SUCCESS);
862: }

864: /*@
865:   PCShellSetApplyRichardson - Sets routine to use as preconditioner
866:   in Richardson iteration.

868:   Logically Collective

870:   Input Parameters:
871: + pc    - the preconditioner context
872: - apply - the application-provided preconditioning routine

874:   Calling sequence of `apply`:
875: + pc               - the preconditioner
876: . b                - right-hand side
877: . x                - current iterate
878: . r                - work space
879: . rtol             - relative tolerance of residual norm to stop at
880: . abstol           - absolute tolerance of residual norm to stop at
881: . dtol             - if residual norm increases by this factor than return
882: . maxits           - number of iterations to run
883: . zeroinitialguess - `PETSC_TRUE` if `x` is known to be initially zero
884: . its              - returns the number of iterations used
885: - reason           - returns the reason the iteration has converged

887:   Level: advanced

889:   Notes:
890:   You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `apply`.

892:   This is used when one can provide code for multiple steps of Richardson's method that is more efficient than computing a single step,
893:   recomputing the residual via $ r = b - A x $, and then computing the next step. SOR is an algorithm for which this is true.

895: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApply()`, `PCShellSetContext()`, `PCRichardsonConvergedReason()`, `PCShellGetContext()`, `PCShellSetMatApplyRichardson()`, `KSPRICHARDSON`
896: @*/
897: PetscErrorCode PCShellSetApplyRichardson(PC pc, PetscErrorCode (*apply)(PC pc, Vec b, Vec x, Vec r, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt maxits, PetscBool zeroinitialguess, PetscInt *its, PCRichardsonConvergedReason *reason))
898: {
899:   PetscFunctionBegin;
901:   PetscTryMethod(pc, "PCShellSetApplyRichardson_C", (PC, PetscErrorCode (*)(PC, Vec, Vec, Vec, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *)), (pc, apply));
902:   PetscFunctionReturn(PETSC_SUCCESS);
903: }

905: /*@
906:   PCShellSetMatApplyRichardson - Sets routine to use as preconditioner
907:   in Richardson iteration on a block of vectors stored as a `MATDENSE`.

909:   Logically Collective

911:   Input Parameters:
912: + pc       - the preconditioner context
913: - matapply - the application-provided preconditioning routine

915:   Calling sequence of `matapply`:
916: + pc               - the preconditioner
917: . B                - block of right-hand sides
918: . X                - block of current iterates
919: . W                - block of work vectors, may be `NULL`
920: . rtol             - relative tolerance of residual norm to stop at
921: . abstol           - absolute tolerance of residual norm to stop at
922: . dtol             - if residual norm increases by this factor then return
923: . maxits           - number of iterations to run
924: . zeroinitialguess - `PETSC_TRUE` if `X` is known to be initially zero
925: . its              - returns the number of iterations used
926: - reason           - returns the reason the iteration has converged

928:   Level: advanced

930:   Notes:
931:   You can get the `PCSHELL` context set with `PCShellSetContext()` using `PCShellGetContext()` if needed by `matapply`.

933:   This is the block analog of `PCShellSetApplyRichardson()` and is used by `KSPMatSolve()` with `KSPRICHARDSON` to run Richardson's
934:   method on the whole block of right-hand sides at once instead of one right-hand side at a time. `KSPRICHARDSON` passes `NULL` for
935:   `W`, so `matapply` must allocate any scratch space it needs itself. Setting this callback without also setting
936:   `PCShellSetApplyRichardson()` makes `KSPMatSolve()` delegate to `matapply` while `KSPSolve()` runs the generic Richardson
937:   iteration with the plain apply callback, so the two can compute different solutions unless the callbacks are consistent.

939: .seealso: [](ch_ksp), `PCSHELL`, `PCShellSetApplyRichardson()`, `PCShellSetMatApply()`, `PCShellSetContext()`, `PCRichardsonConvergedReason()`, `PCShellGetContext()`, `KSPRICHARDSON`, `KSPMatSolve()`
940: @*/
941: PetscErrorCode PCShellSetMatApplyRichardson(PC pc, PetscErrorCode (*matapply)(PC pc, Mat B, Mat X, Mat W, PetscReal rtol, PetscReal abstol, PetscReal dtol, PetscInt maxits, PetscBool zeroinitialguess, PetscInt *its, PCRichardsonConvergedReason *reason))
942: {
943:   PetscFunctionBegin;
945:   PetscTryMethod(pc, "PCShellSetMatApplyRichardson_C", (PC, PetscErrorCode (*)(PC, Mat, Mat, Mat, PetscReal, PetscReal, PetscReal, PetscInt, PetscBool, PetscInt *, PCRichardsonConvergedReason *)), (pc, matapply));
946:   PetscFunctionReturn(PETSC_SUCCESS);
947: }

949: /*MC
950:   PCSHELL - Creates a new preconditioner class for use with a users
951:             own private data storage format and preconditioner application code

953:   Level: advanced

955:   Usage:
956: .vb
957:   extern PetscErrorCode apply(PC,Vec,Vec);
958:   extern PetscErrorCode applyba(PC,PCSide,Vec,Vec,Vec);
959:   extern PetscErrorCode applytranspose(PC,Vec,Vec);
960:   extern PetscErrorCode setup(PC);
961:   extern PetscErrorCode destroy(PC);

963:   PCCreate(comm,&pc);
964:   PCSetType(pc,PCSHELL);
965:   PCShellSetContext(pc,ctx)
966:   PCShellSetApply(pc,apply);
967:   PCShellSetApplyBA(pc,applyba);               (optional)
968:   PCShellSetApplyTranspose(pc,applytranspose); (optional)
969:   PCShellSetSetUp(pc,setup);                   (optional)
970:   PCShellSetDestroy(pc,destroy);               (optional)
971: .ve

973:   Notes:
974:   Information required for the preconditioner and its internal datastructures can be set with `PCShellSetContext()` and then accessed
975:   with `PCShellGetContext()` inside the routines provided above.

977:   When using `MATSHELL`, where the explicit entries of matrix are not available to build the preconditioner, `PCSHELL` can be used
978:   to construct a custom preconditioner for the `MATSHELL`, assuming the user knows enough about their problem to provide a
979:   custom preconditioner.

981: .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`,
982:           `MATSHELL`, `PCShellSetSetUp()`, `PCShellSetApply()`, `PCShellSetView()`, `PCShellSetDestroy()`, `PCShellSetPostSolve()`,
983:           `PCShellSetApplyTranspose()`, `PCShellSetName()`, `PCShellSetApplyRichardson()`, `PCShellSetPreSolve()`,
984:           `PCShellGetName()`, `PCShellSetContext()`, `PCShellGetContext()`, `PCShellSetApplyBA()`, `PCShellSetMatApply()`, `PCShellSetMatApplyRichardson()`
985: M*/

987: PETSC_EXTERN PetscErrorCode PCCreate_Shell(PC pc)
988: {
989:   PC_Shell *shell;

991:   PetscFunctionBegin;
992:   PetscCall(PetscNew(&shell));
993:   pc->data = (void *)shell;

995:   pc->ops->destroy             = PCDestroy_Shell;
996:   pc->ops->view                = PCView_Shell;
997:   pc->ops->apply               = PCApply_Shell;
998:   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_Shell;
999:   pc->ops->applysymmetricright = PCApplySymmetricRight_Shell;
1000:   pc->ops->matapply            = NULL;
1001:   pc->ops->applytranspose      = NULL;
1002:   pc->ops->applyrichardson     = NULL;
1003:   pc->ops->matapplyrichardson  = NULL;
1004:   pc->ops->setup               = NULL;
1005:   pc->ops->presolve            = NULL;
1006:   pc->ops->postsolve           = NULL;

1008:   shell->apply               = NULL;
1009:   shell->applytranspose      = NULL;
1010:   shell->name                = NULL;
1011:   shell->applyrich           = NULL;
1012:   shell->matapplyrich        = NULL;
1013:   shell->presolve            = NULL;
1014:   shell->postsolve           = NULL;
1015:   shell->ctx                 = NULL;
1016:   shell->setup               = NULL;
1017:   shell->view                = NULL;
1018:   shell->destroy             = NULL;
1019:   shell->applysymmetricleft  = NULL;
1020:   shell->applysymmetricright = NULL;

1022:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetDestroy_C", PCShellSetDestroy_Shell));
1023:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetSetUp_C", PCShellSetSetUp_Shell));
1024:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApply_C", PCShellSetApply_Shell));
1025:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetMatApply_C", PCShellSetMatApply_Shell));
1026:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplySymmetricLeft_C", PCShellSetApplySymmetricLeft_Shell));
1027:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplySymmetricRight_C", PCShellSetApplySymmetricRight_Shell));
1028:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyBA_C", PCShellSetApplyBA_Shell));
1029:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetPreSolve_C", PCShellSetPreSolve_Shell));
1030:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetPostSolve_C", PCShellSetPostSolve_Shell));
1031:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetView_C", PCShellSetView_Shell));
1032:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyTranspose_C", PCShellSetApplyTranspose_Shell));
1033:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetMatApplyTranspose_C", PCShellSetMatApplyTranspose_Shell));
1034:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetName_C", PCShellSetName_Shell));
1035:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellGetName_C", PCShellGetName_Shell));
1036:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetApplyRichardson_C", PCShellSetApplyRichardson_Shell));
1037:   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCShellSetMatApplyRichardson_C", PCShellSetMatApplyRichardson_Shell));
1038:   PetscFunctionReturn(PETSC_SUCCESS);
1039: }