Actual source code: taotermshell.c

      1: #include <petsc/private/taoimpl.h>

      3: typedef struct _n_TaoTerm_Shell TaoTerm_Shell;

      5: struct _n_TaoTerm_Shell {
      6:   PetscContainer ctxcontainer;
      7:   PetscBool3     iscomputehessianfdpossible;
      8: };

     10: /*@C
     11:   TaoTermShellSetContextDestroy - Set a method to destroy the context resources when a `TAOTERMSHELL` is destroyed

     13:   Logically collective

     15:   Input Parameters:
     16: + term    - a `TaoTerm` of type `TAOTERMSHELL`
     17: - destroy - the context destroy function

     19:   Level: intermediate

     21: .seealso: [](sec_tao_term), `TaoTerm`, `TAOTERMSHELL`, `TaoTermShellSetContext()`, `TaoTermShellGetContext()`
     22: @*/
     23: PetscErrorCode TaoTermShellSetContextDestroy(TaoTerm term, PetscCtxDestroyFn *destroy)
     24: {
     25:   PetscFunctionBegin;
     27:   PetscTryMethod(term, "TaoTermShellSetContextDestroy_C", (TaoTerm, PetscCtxDestroyFn *), (term, destroy));
     28:   PetscFunctionReturn(PETSC_SUCCESS);
     29: }

     31: static PetscErrorCode TaoTermShellSetContextDestroy_Shell(TaoTerm term, PetscCtxDestroyFn *f)
     32: {
     33:   TaoTerm_Shell *shell = (TaoTerm_Shell *)term->data;

     35:   PetscFunctionBegin;
     36:   if (shell->ctxcontainer) PetscCall(PetscContainerSetCtxDestroy(shell->ctxcontainer, f));
     37:   PetscFunctionReturn(PETSC_SUCCESS);
     38: }

     40: /*@
     41:   TaoTermShellGetContext - Get the context for a `TAOTERMSHELL`

     43:   Not collective

     45:   Input Parameter:
     46: . term - a `TaoTerm` of type `TAOTERMSHELL`

     48:   Output Parameter:
     49: . ctx - a context

     51:   Level: intermediate

     53: .seealso: [](sec_tao_term), `TaoTerm`, `TAOTERMSHELL`, `TaoTermShellSetContext()`, `TaoTermShellSetContextDestroy()`
     54: @*/
     55: PetscErrorCode TaoTermShellGetContext(TaoTerm term, PetscCtxRt ctx)
     56: {
     57:   PetscFunctionBegin;
     59:   PetscAssertPointer(ctx, 2);
     60:   PetscUseMethod(term, "TaoTermShellGetContext_C", (TaoTerm, PetscCtxRt), (term, ctx));
     61:   PetscFunctionReturn(PETSC_SUCCESS);
     62: }

     64: static PetscErrorCode TaoTermShellGetContext_Shell(TaoTerm term, PetscCtxRt ctx)
     65: {
     66:   TaoTerm_Shell *shell = (TaoTerm_Shell *)term->data;

     68:   PetscFunctionBegin;
     69:   if (shell->ctxcontainer) PetscCall(PetscContainerGetPointer(shell->ctxcontainer, (void **)ctx));
     70:   else *(void **)ctx = NULL;
     71:   PetscFunctionReturn(PETSC_SUCCESS);
     72: }

     74: /*@
     75:   TaoTermShellSetContext - Set a context for a `TAOTERMSHELL`

     77:   Logically collective

     79:   Input Parameters:
     80: + term - a `TaoTerm` of type `TAOTERMSHELL`
     81: - ctx  - a context

     83:   Level: intermediate

     85:   Note:
     86:   The context can be accessed in callbacks using `TaoTermShellGetContext()`

     88: .seealso: [](sec_tao_term), `TaoTerm`, `TAOTERMSHELL`, `TaoTermShellGetContext()`, `TaoTermShellSetContextDestroy()`
     89: @*/
     90: PetscErrorCode TaoTermShellSetContext(TaoTerm term, PetscCtx ctx)
     91: {
     92:   PetscFunctionBegin;
     94:   PetscTryMethod(term, "TaoTermShellSetContext_C", (TaoTerm, PetscCtx), (term, ctx));
     95:   PetscFunctionReturn(PETSC_SUCCESS);
     96: }

     98: static PetscErrorCode TaoTermShellSetContext_Shell(TaoTerm term, PetscCtx ctx)
     99: {
    100:   TaoTerm_Shell *shell = (TaoTerm_Shell *)term->data;

    102:   PetscFunctionBegin;
    103:   if (ctx) {
    104:     PetscContainer ctxcontainer;

    106:     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)term), &ctxcontainer));
    107:     PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
    108:     PetscCall(PetscObjectCompose((PetscObject)term, "TaoTermShell ctx", (PetscObject)ctxcontainer));
    109:     shell->ctxcontainer = ctxcontainer;
    110:     PetscCall(PetscContainerDestroy(&ctxcontainer));
    111:   } else {
    112:     PetscCall(PetscObjectCompose((PetscObject)term, "TaoTermShell ctx", NULL));
    113:     shell->ctxcontainer = NULL;
    114:   }
    115:   PetscFunctionReturn(PETSC_SUCCESS);
    116: }

    118: static PetscErrorCode TaoTermView_Shell(TaoTerm term, PetscViewer viewer)
    119: {
    120:   TaoTerm_Shell *shell = (TaoTerm_Shell *)term->data;
    121:   PetscBool      iascii;

    123:   PetscFunctionBegin;
    124:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
    125:   if (iascii) {
    126:     PetscBool any;
    127:     if (shell->ctxcontainer) PetscCall(PetscViewerASCIIPrintf(viewer, "Context has been set\n"));
    128:     else PetscCall(PetscViewerASCIIPrintf(viewer, "No context has been set\n"));

    130:     PetscCall(PetscViewerASCIIPrintf(viewer, "The following methods have been set:"));
    131:     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
    132:     any = PETSC_FALSE;
    133:     if (term->ops->objective) {
    134:       any = PETSC_TRUE;
    135:       PetscCall(PetscViewerASCIIPrintf(viewer, " objective,"));
    136:     }
    137:     if (term->ops->gradient) {
    138:       any = PETSC_TRUE;
    139:       PetscCall(PetscViewerASCIIPrintf(viewer, " gradient,"));
    140:     }
    141:     if (term->ops->objectiveandgradient) {
    142:       any = PETSC_TRUE;
    143:       PetscCall(PetscViewerASCIIPrintf(viewer, " objectiveandgradient,"));
    144:     }
    145:     if (term->ops->hessian) {
    146:       any = PETSC_TRUE;
    147:       PetscCall(PetscViewerASCIIPrintf(viewer, " hessian,"));
    148:     }
    149:     if (any == PETSC_FALSE) PetscCall(PetscViewerASCIIPrintf(viewer, " (none)"));
    150:     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
    151:     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
    152:   }
    153:   PetscFunctionReturn(PETSC_SUCCESS);
    154: }

    156: static PetscErrorCode TaoTermDestroy_Shell(TaoTerm term)
    157: {
    158:   TaoTerm_Shell *shell = (TaoTerm_Shell *)term->data;

    160:   PetscFunctionBegin;
    161:   PetscCall(TaoTermShellSetContext_Shell(term, NULL));
    162:   PetscCall(PetscFree(shell));
    163:   term->data                      = NULL;
    164:   term->ops->objective            = NULL;
    165:   term->ops->gradient             = NULL;
    166:   term->ops->objectiveandgradient = NULL;
    167:   term->ops->hessian              = NULL;
    168:   term->ops->view                 = NULL;

    170:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetContextDestroy_C", NULL));
    171:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetContext_C", NULL));
    172:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellGetContext_C", NULL));
    173:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetObjective_C", NULL));
    174:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetGradient_C", NULL));
    175:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetObjectiveAndGradient_C", NULL));
    176:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetHessian_C", NULL));
    177:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetIsComputeHessianFDPossible_C", NULL));
    178:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetView_C", NULL));
    179:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetCreateSolutionVec_C", NULL));
    180:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetCreateParametersVec_C", NULL));
    181:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetCreateHessianMatrices_C", NULL));
    182:   PetscFunctionReturn(PETSC_SUCCESS);
    183: }

    185: /*@C
    186:   TaoTermShellSetObjective - Set the objective function of a `TAOTERMSHELL`

    188:   Logically collective

    190:   Input Parameters:
    191: + term      - a `TaoTerm` of type `TAOTERMSHELL`
    192: - objective - a `TaoTermObjectiveFn` function pointer

    194:   Level: intermediate

    196: .seealso: [](sec_tao_term), `TaoTerm`, `TAOTERMSHELL`, `TaoTermShellGetContext()`, `TaoTermShellSetContextDestroy()`,
    197:           `TaoTermShellSetGradient()`,
    198:           `TaoTermShellSetObjectiveAndGradient()`,
    199:           `TaoTermShellSetHessian()`,
    200:           `TaoTermShellSetView()`,
    201:           `TaoTermObjectiveFn`
    202: @*/
    203: PetscErrorCode TaoTermShellSetObjective(TaoTerm term, TaoTermObjectiveFn *objective)
    204: {
    205:   PetscFunctionBegin;
    207:   PetscTryMethod(term, "TaoTermShellSetObjective_C", (TaoTerm, TaoTermObjectiveFn *), (term, objective));
    208:   PetscFunctionReturn(PETSC_SUCCESS);
    209: }

    211: static PetscErrorCode TaoTermShellSetObjective_Shell(TaoTerm term, TaoTermObjectiveFn *objective)
    212: {
    213:   PetscFunctionBegin;
    214:   term->ops->objective = objective;
    215:   PetscFunctionReturn(PETSC_SUCCESS);
    216: }

    218: /*@C
    219:   TaoTermShellSetGradient - Set the gradient function of a `TAOTERMSHELL`

    221:   Logically collective

    223:   Input Parameters:
    224: + term     - a `TaoTerm` of type `TAOTERMSHELL`
    225: - gradient - a `TaoTermGradientFn` function pointer

    227:   Level: intermediate

    229: .seealso: [](sec_tao_term), `TaoTerm`, `TAOTERMSHELL`, `TaoTermShellGetContext()`, `TaoTermShellSetContextDestroy()`,
    230:           `TaoTermShellSetObjective()`,
    231:           `TaoTermShellSetObjectiveAndGradient()`,
    232:           `TaoTermShellSetHessian()`,
    233:           `TaoTermShellSetView()`,
    234:           `TaoTermGradientFn`
    235: @*/
    236: PetscErrorCode TaoTermShellSetGradient(TaoTerm term, TaoTermGradientFn *gradient)
    237: {
    238:   PetscFunctionBegin;
    240:   PetscTryMethod(term, "TaoTermShellSetGradient_C", (TaoTerm, TaoTermGradientFn *), (term, gradient));
    241:   PetscFunctionReturn(PETSC_SUCCESS);
    242: }

    244: static PetscErrorCode TaoTermShellSetGradient_Shell(TaoTerm term, TaoTermGradientFn *gradient)
    245: {
    246:   PetscFunctionBegin;
    247:   term->ops->gradient = gradient;
    248:   PetscFunctionReturn(PETSC_SUCCESS);
    249: }

    251: /*@C
    252:   TaoTermShellSetObjectiveAndGradient - Set the objective and gradient function of a `TAOTERMSHELL`

    254:   Logically collective

    256:   Input Parameters:
    257: + term       - a `TaoTerm` of type `TAOTERMSHELL`
    258: - objandgrad - a `TaoTermObjectiveAndGradientFn` function pointer

    260:   Level: intermediate

    262: .seealso: [](sec_tao_term), `TaoTerm`, `TAOTERMSHELL`, `TaoTermShellGetContext()`, `TaoTermShellSetContextDestroy()`,
    263:           `TaoTermShellSetObjective()`,
    264:           `TaoTermShellSetGradient()`,
    265:           `TaoTermShellSetHessian()`,
    266:           `TaoTermShellSetView()`,
    267:           `TaoTermObjectiveAndGradientFn`
    268: @*/
    269: PetscErrorCode TaoTermShellSetObjectiveAndGradient(TaoTerm term, TaoTermObjectiveAndGradientFn *objandgrad)
    270: {
    271:   PetscFunctionBegin;
    273:   PetscTryMethod(term, "TaoTermShellSetObjectiveAndGradient_C", (TaoTerm, TaoTermObjectiveAndGradientFn *), (term, objandgrad));
    274:   PetscFunctionReturn(PETSC_SUCCESS);
    275: }

    277: static PetscErrorCode TaoTermShellSetObjectiveAndGradient_Shell(TaoTerm term, TaoTermObjectiveAndGradientFn *objandgrad)
    278: {
    279:   PetscFunctionBegin;
    280:   term->ops->objectiveandgradient = objandgrad;
    281:   PetscFunctionReturn(PETSC_SUCCESS);
    282: }

    284: /*@C
    285:   TaoTermShellSetHessian - Set the Hessian function of a `TAOTERMSHELL`

    287:   Logically collective

    289:   Input Parameters:
    290: + term    - a `TaoTerm` of type `TAOTERMSHELL`
    291: - hessian - a `TaoTermHessianFn` function pointer

    293:   Level: intermediate

    295: .seealso: [](sec_tao_term), `TaoTerm`, `TAOTERMSHELL`, `TaoTermShellGetContext()`, `TaoTermShellSetContextDestroy()`,
    296:           `TaoTermShellSetObjective()`,
    297:           `TaoTermShellSetGradient()`,
    298:           `TaoTermShellSetObjectiveAndGradient()`,
    299:           `TaoTermShellSetView()`,
    300:           `TaoTermHessianFn`
    301: @*/
    302: PetscErrorCode TaoTermShellSetHessian(TaoTerm term, TaoTermHessianFn *hessian)
    303: {
    304:   PetscFunctionBegin;
    306:   PetscTryMethod(term, "TaoTermShellSetHessian_C", (TaoTerm, TaoTermHessianFn *), (term, hessian));
    307:   PetscFunctionReturn(PETSC_SUCCESS);
    308: }

    310: static PetscErrorCode TaoTermShellSetHessian_Shell(TaoTerm term, TaoTermHessianFn *hessian)
    311: {
    312:   PetscFunctionBegin;
    313:   term->ops->hessian = hessian;
    314:   PetscFunctionReturn(PETSC_SUCCESS);
    315: }

    317: static PetscErrorCode TaoTermIsComputeHessianFDPossible_Shell(TaoTerm term, PetscBool3 *ispossible)
    318: {
    319:   TaoTerm_Shell *shell = (TaoTerm_Shell *)term->data;

    321:   PetscFunctionBegin;
    322:   *ispossible = shell->iscomputehessianfdpossible;
    323:   PetscFunctionReturn(PETSC_SUCCESS);
    324: }

    326: /*@C
    327:   TaoTermShellSetIsComputeHessianFDPossible - Set whether this term can compute Hessian with finite differences for a `TAOTERMSHELL`

    329:   Logically collective

    331:   Input Parameters:
    332: + term       - a `TaoTerm` of type `TAOTERMSHELL`
    333: - ispossible - whether Hessian computation with finite differences is possible

    335:   Level: intermediate

    337: .seealso: [](sec_tao_term), `TaoTerm`, `TAOTERMSHELL`, `TaoTermShellGetContext()`, `TaoTermShellSetContextDestroy()`,
    338:           `TaoTermShellSetObjective()`,
    339:           `TaoTermShellSetGradient()`,
    340:           `TaoTermShellSetObjectiveAndGradient()`,
    341:           `TaoTermShellSetHessian()`,
    342:           `TaoTermIsComputeHessianFDPossible()`
    343: @*/
    344: PetscErrorCode TaoTermShellSetIsComputeHessianFDPossible(TaoTerm term, PetscBool3 ispossible)
    345: {
    346:   PetscFunctionBegin;
    348:   PetscTryMethod(term, "TaoTermShellSetIsComputeHessianFDPossible_C", (TaoTerm, PetscBool3), (term, ispossible));
    349:   PetscFunctionReturn(PETSC_SUCCESS);
    350: }

    352: static PetscErrorCode TaoTermShellSetIsComputeHessianFDPossible_Shell(TaoTerm term, PetscBool3 ispossible)
    353: {
    354:   TaoTerm_Shell *shell = (TaoTerm_Shell *)term->data;

    356:   PetscFunctionBegin;
    357:   shell->iscomputehessianfdpossible     = ispossible;
    358:   term->ops->iscomputehessianfdpossible = TaoTermIsComputeHessianFDPossible_Shell;
    359:   PetscFunctionReturn(PETSC_SUCCESS);
    360: }

    362: /*@C
    363:   TaoTermShellSetView - Set the view function of a `TAOTERMSHELL`

    365:   Logically collective

    367:   Input Parameters:
    368: + term - a `TaoTerm` of type `TAOTERMSHELL`
    369: - view - a function with the same signature as `TaoTermView()`

    371:   Calling sequence of `view`:
    372: + term   - the `TaoTerm`
    373: - viewer - a `PetscViewer`

    375:   Level: intermediate

    377: .seealso: [](sec_tao_term), `TaoTerm`, `TAOTERMSHELL`, `TaoTermShellGetContext()`, `TaoTermShellSetContextDestroy()`,
    378:           `TaoTermShellSetObjective()`,
    379:           `TaoTermShellSetGradient()`,
    380:           `TaoTermShellSetObjectiveAndGradient()`,
    381:           `TaoTermShellSetHessian()`
    382: @*/
    383: PetscErrorCode TaoTermShellSetView(TaoTerm term, PetscErrorCode (*view)(TaoTerm term, PetscViewer viewer))
    384: {
    385:   PetscFunctionBegin;
    387:   PetscTryMethod(term, "TaoTermShellSetView_C", (TaoTerm, PetscErrorCode (*)(TaoTerm, PetscViewer)), (term, view));
    388:   PetscFunctionReturn(PETSC_SUCCESS);
    389: }

    391: static PetscErrorCode TaoTermShellSetView_Shell(TaoTerm term, PetscErrorCode (*view)(TaoTerm, PetscViewer))
    392: {
    393:   PetscFunctionBegin;
    394:   term->ops->view = view;
    395:   PetscFunctionReturn(PETSC_SUCCESS);
    396: }

    398: /*@C
    399:   TaoTermShellSetCreateSolutionVec - Set the routine that creates solution vector for a `TaoTerm` of type `TAOTERMSHELL`

    401:   Logically collective

    403:   Input Parameters:
    404: + term              - a `TaoTerm` of type `TAOTERMSHELL`
    405: - createsolutionvec - a function with the same signature as `TaoTermCreateSolutionVec()`

    407:   Calling sequence of `createsolutionvec`:
    408: + term     - the `TaoTerm`
    409: - solution - a solution vector for `term`

    411:   Level: intermediate

    413: .seealso: [](sec_tao_term), `TaoTerm`, `TAOTERMSHELL`, `TaoTermShellGetContext()`, `TaoTermShellSetContextDestroy()`,
    414:           `TaoTermShellSetCreateHessianMatrices()`
    415: @*/
    416: PetscErrorCode TaoTermShellSetCreateSolutionVec(TaoTerm term, PetscErrorCode (*createsolutionvec)(TaoTerm term, Vec *solution))
    417: {
    418:   PetscFunctionBegin;
    420:   PetscTryMethod(term, "TaoTermShellSetCreateSolutionVec_C", (TaoTerm, PetscErrorCode (*)(TaoTerm, Vec *)), (term, createsolutionvec));
    421:   PetscFunctionReturn(PETSC_SUCCESS);
    422: }

    424: /*@C
    425:   TaoTermShellSetCreateParametersVec - Set the routine that creates parameters vector for a `TaoTerm` of type `TAOTERMSHELL`

    427:   Logically collective

    429:   Input Parameters:
    430: + term                - a `TaoTerm` of type `TAOTERMSHELL`
    431: - createparametersvec - a function with the same signature as `TaoTermCreateParametersVec()`

    433:   Calling sequence of `createparametersvec`:
    434: + term       - the `TaoTerm`
    435: - parameters - a parameters vector for `term`

    437:   Level: intermediate

    439: .seealso: [](sec_tao_term), `TaoTerm`, `TAOTERMSHELL`, `TaoTermShellGetContext()`, `TaoTermShellSetContextDestroy()`,
    440:           `TaoTermShellSetCreateHessianMatrices()`
    441: @*/
    442: PetscErrorCode TaoTermShellSetCreateParametersVec(TaoTerm term, PetscErrorCode (*createparametersvec)(TaoTerm term, Vec *parameters))
    443: {
    444:   PetscFunctionBegin;
    446:   PetscTryMethod(term, "TaoTermShellSetCreateParametersVec_C", (TaoTerm, PetscErrorCode (*)(TaoTerm, Vec *)), (term, createparametersvec));
    447:   PetscFunctionReturn(PETSC_SUCCESS);
    448: }

    450: static PetscErrorCode TaoTermShellSetCreateSolutionVec_Shell(TaoTerm term, PetscErrorCode (*createsolutionvec)(TaoTerm, Vec *))
    451: {
    452:   PetscFunctionBegin;
    453:   term->ops->createsolutionvec = createsolutionvec;
    454:   PetscFunctionReturn(PETSC_SUCCESS);
    455: }

    457: static PetscErrorCode TaoTermShellSetCreateParametersVec_Shell(TaoTerm term, PetscErrorCode (*createparametersvec)(TaoTerm, Vec *))
    458: {
    459:   PetscFunctionBegin;
    460:   term->ops->createparametersvec = createparametersvec;
    461:   PetscFunctionReturn(PETSC_SUCCESS);
    462: }

    464: /*@C
    465:   TaoTermShellSetCreateHessianMatrices - Set the routine that creates Hessian matrices for a `TaoTerm` of type `TAOTERMSHELL`

    467:   Logically collective

    469:   Input Parameters:
    470: + term       - a `TaoTerm` of type `TAOTERMSHELL`
    471: - createmats - a function with the same signature as `TaoTermCreateHessianMatrices()`

    473:   Calling sequence of `createmats`:
    474: + f    - the `TaoTerm`
    475: . H    - (optional) a matrix of the appropriate type and size for the Hessian of `term`
    476: - Hpre - (optional) a matrix of the appropriate type and size for constructing a preconditioner for the Hessian of `term`

    478:   Level: intermediate

    480: .seealso: [](sec_tao_term), `TaoTerm`, `TAOTERMSHELL`, `TaoTermShellGetContext()`, `TaoTermShellSetContextDestroy()`,
    481:           `TaoTermShellSetCreateSolutionVec()`, `TaoTermShellSetCreateParametersVec()`
    482: @*/
    483: PetscErrorCode TaoTermShellSetCreateHessianMatrices(TaoTerm term, PetscErrorCode (*createmats)(TaoTerm f, Mat *H, Mat *Hpre))
    484: {
    485:   PetscFunctionBegin;
    487:   PetscTryMethod(term, "TaoTermShellSetCreateHessianMatrices_C", (TaoTerm, PetscErrorCode (*)(TaoTerm, Mat *, Mat *)), (term, createmats));
    488:   PetscFunctionReturn(PETSC_SUCCESS);
    489: }

    491: static PetscErrorCode TaoTermShellSetCreateHessianMatrices_Shell(TaoTerm term, PetscErrorCode (*createhessianmatrices)(TaoTerm, Mat *, Mat *))
    492: {
    493:   PetscFunctionBegin;
    494:   term->ops->createhessianmatrices = createhessianmatrices;
    495:   PetscFunctionReturn(PETSC_SUCCESS);
    496: }

    498: /*MC
    499:   TAOTERMSHELL - A `TaoTerm` that uses user-provided function callbacks for its operations

    501:   Level: intermediate

    503: .seealso: [](sec_tao_term), `TaoTerm`, `TaoTermShellGetContext()`, `TaoTermShellSetContextDestroy()`, `TaoTermCreateShell()`,
    504:           `TaoTermShellSetObjective()`,
    505:           `TaoTermShellSetGradient()`,
    506:           `TaoTermShellSetObjectiveAndGradient()`,
    507:           `TaoTermShellSetHessian()`
    508: M*/
    509: PETSC_INTERN PetscErrorCode TaoTermCreate_Shell(TaoTerm term)
    510: {
    511:   TaoTerm_Shell *shell;

    513:   PetscFunctionBegin;
    514:   PetscCall(PetscNew(&shell));
    515:   term->data = (void *)shell;

    517:   shell->iscomputehessianfdpossible     = PETSC_BOOL3_UNKNOWN;
    518:   term->ops->iscomputehessianfdpossible = NULL;
    519:   term->ops->destroy                    = TaoTermDestroy_Shell;
    520:   term->ops->view                       = TaoTermView_Shell;

    522:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetContextDestroy_C", TaoTermShellSetContextDestroy_Shell));
    523:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetContext_C", TaoTermShellSetContext_Shell));
    524:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellGetContext_C", TaoTermShellGetContext_Shell));
    525:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetObjective_C", TaoTermShellSetObjective_Shell));
    526:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetGradient_C", TaoTermShellSetGradient_Shell));
    527:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetObjectiveAndGradient_C", TaoTermShellSetObjectiveAndGradient_Shell));
    528:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetHessian_C", TaoTermShellSetHessian_Shell));
    529:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetIsComputeHessianFDPossible_C", TaoTermShellSetIsComputeHessianFDPossible_Shell));
    530:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetView_C", TaoTermShellSetView_Shell));
    531:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetCreateSolutionVec_C", TaoTermShellSetCreateSolutionVec_Shell));
    532:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetCreateParametersVec_C", TaoTermShellSetCreateParametersVec_Shell));
    533:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermShellSetCreateHessianMatrices_C", TaoTermShellSetCreateHessianMatrices_Shell));
    534:   PetscFunctionReturn(PETSC_SUCCESS);
    535: }

    537: /*@C
    538:   TaoTermCreateShell - Create a `TaoTerm` of type `TAOTERMSHELL` that is ready to accept user-provided callback operations.

    540:   Collective

    542:   Input Parameters:
    543: + comm    - the MPI communicator for computing the term
    544: . ctx     - (optional) a context to be used by routines
    545: - destroy - (optional) a routine to destroy the context when `term` is destroyed

    547:   Output Parameter:
    548: . term - a `TaoTerm` of type `TAOTERMSHELL`

    550:   Level: intermediate

    552: .seealso: [](sec_tao_term), `TaoTerm`, `TAOTERMSHELL`
    553: @*/
    554: PetscErrorCode TaoTermCreateShell(MPI_Comm comm, PetscCtx ctx, PetscCtxDestroyFn *destroy, TaoTerm *term)
    555: {
    556:   PetscFunctionBegin;
    557:   PetscAssertPointer(term, 4);
    558:   PetscCall(TaoTermCreate(comm, term));
    559:   PetscCall(TaoTermSetType(*term, TAOTERMSHELL));
    560:   if (ctx) PetscCall(TaoTermShellSetContext(*term, ctx));
    561:   if (destroy) PetscCall(TaoTermShellSetContextDestroy(*term, destroy));
    562:   PetscFunctionReturn(PETSC_SUCCESS);
    563: }