Actual source code: taotermcallbacks.c

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

      3: typedef struct _n_TaoTerm_Callbacks TaoTerm_Callbacks;

      5: struct _n_TaoTerm_Callbacks {
      6:   Tao tao;
      7:   PetscErrorCode (*objective)(Tao, Vec, PetscReal *, PetscCtx);
      8:   PetscErrorCode (*gradient)(Tao, Vec, Vec, PetscCtx);
      9:   PetscErrorCode (*objectiveandgradient)(Tao, Vec, PetscReal *, Vec, PetscCtx);
     10:   PetscErrorCode (*hessian)(Tao, Vec, Mat, Mat, PetscCtx);
     11:   PetscCtx obj_ctx;
     12:   PetscCtx grad_ctx;
     13:   PetscCtx objgrad_ctx;
     14:   PetscCtx hess_ctx;
     15:   char    *obj_name;
     16:   char    *grad_name;
     17:   char    *objgrad_name;
     18:   char    *hess_name;
     19:   char    *set_obj_name;
     20:   char    *set_grad_name;
     21:   char    *set_objgrad_name;
     22:   char    *set_hess_name;
     23: };

     25: #define PetscCheckTaoTermCallbacksValid(term, tt, params) \
     26:   do { \
     27:     PetscCheck((params) == NULL, PetscObjectComm((PetscObject)(term)), PETSC_ERR_ARG_INCOMP, "TAOTERMCALLBACKS does not accept a vector of parameters"); \
     28:     PetscCheck((tt)->tao != NULL, PetscObjectComm((PetscObject)(term)), PETSC_ERR_ARG_WRONGSTATE, "TAOTERMCALLBACKS does not have an outer Tao"); \
     29:   } while (0)

     31: static PetscErrorCode TaoTermDestroy_Callbacks(TaoTerm term)
     32: {
     33:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

     35:   PetscFunctionBegin;
     36:   // tt->tao is a weak reference, we do not destroy it
     37:   PetscCall(PetscFree(tt->obj_name));
     38:   PetscCall(PetscFree(tt->grad_name));
     39:   PetscCall(PetscFree(tt->objgrad_name));
     40:   PetscCall(PetscFree(tt->hess_name));
     41:   PetscCall(PetscFree(tt->set_obj_name));
     42:   PetscCall(PetscFree(tt->set_grad_name));
     43:   PetscCall(PetscFree(tt->set_objgrad_name));
     44:   PetscCall(PetscFree(tt->set_hess_name));
     45:   PetscCall(PetscFree(tt));
     46:   term->data = NULL;
     47:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksSetObjective_C", NULL));
     48:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksGetObjective_C", NULL));
     49:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksSetGradient_C", NULL));
     50:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksGetGradient_C", NULL));
     51:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksSetObjectiveAndGradient_C", NULL));
     52:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksGetObjectiveAndGradient_C", NULL));
     53:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksSetHessian_C", NULL));
     54:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksGetHessian_C", NULL));
     55:   PetscFunctionReturn(PETSC_SUCCESS);
     56: }

     58: static PetscErrorCode TaoTermComputeObjective_Callbacks(TaoTerm term, Vec x, Vec params, PetscReal *value)
     59: {
     60:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

     62:   PetscFunctionBegin;
     63:   PetscCheckTaoTermCallbacksValid(term, tt, params);
     64:   if (tt->objective) {
     65:     PetscCallBack(tt->obj_name, (*tt->objective)(tt->tao, x, value, tt->obj_ctx));
     66:   } else if (tt->objectiveandgradient) {
     67:     Vec dummy;

     69:     PetscCall(PetscInfo(term, "%s: Duplicating variable vector in order to call func/grad routine\n", ((PetscObject)term)->prefix));
     70:     PetscCall(VecDuplicate(x, &dummy));
     71:     PetscCallBack(tt->objgrad_name, (*tt->objectiveandgradient)(tt->tao, x, value, dummy, tt->objgrad_ctx));
     72:     PetscCall(VecDestroy(&dummy));
     73:   } else SETERRQ(PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONGSTATE, "Objective routine not set: call %s", tt->set_obj_name);
     74:   PetscFunctionReturn(PETSC_SUCCESS);
     75: }

     77: static PetscErrorCode TaoTermComputeGradient_Callbacks(TaoTerm term, Vec x, Vec params, Vec g)
     78: {
     79:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

     81:   PetscFunctionBegin;
     82:   PetscCheckTaoTermCallbacksValid(term, tt, params);
     83:   if (tt->gradient) {
     84:     PetscCallBack(tt->grad_name, (*tt->gradient)(tt->tao, x, g, tt->grad_ctx));
     85:   } else if (tt->objectiveandgradient) {
     86:     PetscReal dummy;

     88:     PetscCallBack(tt->objgrad_name, (*tt->objectiveandgradient)(tt->tao, x, &dummy, g, tt->objgrad_ctx));
     89:   } else SETERRQ(PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONGSTATE, "Gradient routine not set: call %s", tt->set_grad_name);
     90:   PetscFunctionReturn(PETSC_SUCCESS);
     91: }

     93: static PetscErrorCode TaoTermComputeObjectiveAndGradient_Callbacks(TaoTerm term, Vec x, Vec params, PetscReal *value, Vec g)
     94: {
     95:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

     97:   PetscFunctionBegin;
     98:   PetscCheckTaoTermCallbacksValid(term, tt, params);
     99:   if (tt->objectiveandgradient) {
    100:     PetscCallBack(tt->objgrad_name, (*tt->objectiveandgradient)(tt->tao, x, value, g, tt->objgrad_ctx));
    101:   } else if (tt->objective && tt->gradient) {
    102:     PetscCallBack(tt->obj_name, (*tt->objective)(tt->tao, x, value, tt->obj_ctx));
    103:     PetscCallBack(tt->grad_name, (*tt->gradient)(tt->tao, x, g, tt->grad_ctx));
    104:   } else SETERRQ(PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONGSTATE, "Objective/gradient routine not set: call %s", tt->set_objgrad_name);
    105:   PetscFunctionReturn(PETSC_SUCCESS);
    106: }

    108: static PetscErrorCode TaoTermComputeHessian_Callbacks(TaoTerm term, Vec x, Vec params, Mat H, Mat Hpre)
    109: {
    110:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

    112:   PetscFunctionBegin;
    113:   PetscCheckTaoTermCallbacksValid(term, tt, params);
    114:   PetscCheck(tt->hessian, PetscObjectComm((PetscObject)term), PETSC_ERR_ARG_WRONGSTATE, "Hessian routine not set: call %s", tt->set_hess_name);
    115:   PetscCallBack(tt->hess_name, (*tt->hessian)(tt->tao, x, H, Hpre, tt->hess_ctx));
    116:   PetscFunctionReturn(PETSC_SUCCESS);
    117: }

    119: static PetscErrorCode TaoTermView_Callbacks(TaoTerm term, PetscViewer viewer)
    120: {
    121:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;
    122:   PetscBool          iascii;

    124:   PetscFunctionBegin;
    125:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
    126:   if (iascii) {
    127:     if (tt->tao == NULL) {
    128:       PetscCall(PetscViewerASCIIPrintf(viewer, "not attached to a Tao\n"));
    129:     } else {
    130:       const char *name = "[name omitted]";
    131:       const char *prefix;

    133:       if (!PetscCIEnabled) PetscCall(PetscObjectGetName((PetscObject)tt->tao, &name));
    134:       else if (tt->tao->hdr.name) name = tt->tao->hdr.name;
    135:       PetscCall(PetscObjectGetOptionsPrefix((PetscObject)tt->tao, &prefix));
    136:       if (prefix) PetscCall(PetscViewerASCIIPrintf(viewer, "attached to Tao %s (%s)\n", name, prefix));
    137:       else PetscCall(PetscViewerASCIIPrintf(viewer, "attached to Tao %s\n", name));
    138:     }
    139:   }
    140:   PetscFunctionReturn(PETSC_SUCCESS);
    141: }

    143: PETSC_INTERN PetscErrorCode TaoTermCallbacksSetObjective(TaoTerm term, PetscErrorCode (*tao_obj)(Tao, Vec, PetscReal *, PetscCtx), PetscCtx ctx)
    144: {
    145:   PetscFunctionBegin;
    147:   PetscTryMethod(term, "TaoTermCallbacksSetObjective_C", (TaoTerm, PetscErrorCode (*)(Tao, Vec, PetscReal *, PetscCtx), PetscCtx), (term, tao_obj, ctx));
    148:   PetscFunctionReturn(PETSC_SUCCESS);
    149: }

    151: static PetscErrorCode TaoTermCallbacksSetObjective_Callbacks(TaoTerm term, PetscErrorCode (*tao_obj)(Tao, Vec, PetscReal *, PetscCtx), PetscCtx ctx)
    152: {
    153:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

    155:   PetscFunctionBegin;
    156:   tt->objective = tao_obj;
    157:   tt->obj_ctx   = ctx;
    158:   PetscFunctionReturn(PETSC_SUCCESS);
    159: }

    161: PETSC_INTERN PetscErrorCode TaoTermCallbacksGetObjective(TaoTerm term, PetscErrorCode (**tao_obj)(Tao, Vec, PetscReal *, PetscCtx), PetscCtxRt ctx)
    162: {
    163:   PetscFunctionBegin;
    165:   if (tao_obj) *tao_obj = NULL;
    166:   if (ctx) *(void **)ctx = NULL;
    167:   PetscTryMethod(term, "TaoTermCallbacksGetObjective_C", (TaoTerm, PetscErrorCode (**)(Tao, Vec, PetscReal *, PetscCtx), PetscCtxRt), (term, tao_obj, ctx));
    168:   PetscFunctionReturn(PETSC_SUCCESS);
    169: }

    171: static PetscErrorCode TaoTermCallbacksGetObjective_Callbacks(TaoTerm term, PetscErrorCode (**tao_obj)(Tao, Vec, PetscReal *, PetscCtx), PetscCtxRt ctx)
    172: {
    173:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

    175:   PetscFunctionBegin;
    176:   if (tao_obj) *tao_obj = tt->objective;
    177:   if (ctx) *(void **)ctx = tt->obj_ctx;
    178:   PetscFunctionReturn(PETSC_SUCCESS);
    179: }

    181: PETSC_INTERN PetscErrorCode TaoTermCallbacksSetGradient(TaoTerm term, PetscErrorCode (*tao_grad)(Tao, Vec, Vec, PetscCtx), PetscCtx ctx)
    182: {
    183:   PetscFunctionBegin;
    185:   PetscTryMethod(term, "TaoTermCallbacksSetGradient_C", (TaoTerm, PetscErrorCode (*)(Tao, Vec, Vec, PetscCtx), PetscCtx), (term, tao_grad, ctx));
    186:   PetscFunctionReturn(PETSC_SUCCESS);
    187: }

    189: static PetscErrorCode TaoTermCallbacksSetGradient_Callbacks(TaoTerm term, PetscErrorCode (*tao_grad)(Tao, Vec, Vec, PetscCtx), PetscCtx ctx)
    190: {
    191:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

    193:   PetscFunctionBegin;
    194:   tt->gradient = tao_grad;
    195:   tt->grad_ctx = ctx;
    196:   PetscFunctionReturn(PETSC_SUCCESS);
    197: }

    199: PETSC_INTERN PetscErrorCode TaoTermCallbacksGetGradient(TaoTerm term, PetscErrorCode (**tao_grad)(Tao, Vec, Vec, PetscCtx), PetscCtxRt ctx)
    200: {
    201:   PetscFunctionBegin;
    203:   if (tao_grad) *tao_grad = NULL;
    204:   if (ctx) *(void **)ctx = NULL;
    205:   PetscTryMethod(term, "TaoTermCallbacksGetGradient_C", (TaoTerm, PetscErrorCode (**)(Tao, Vec, Vec, PetscCtx), PetscCtxRt), (term, tao_grad, ctx));
    206:   PetscFunctionReturn(PETSC_SUCCESS);
    207: }

    209: static PetscErrorCode TaoTermCallbacksGetGradient_Callbacks(TaoTerm term, PetscErrorCode (**tao_grad)(Tao, Vec, Vec, PetscCtx), PetscCtxRt ctx)
    210: {
    211:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

    213:   PetscFunctionBegin;
    214:   if (tao_grad) *tao_grad = tt->gradient;
    215:   if (ctx) *(void **)ctx = tt->grad_ctx;
    216:   PetscFunctionReturn(PETSC_SUCCESS);
    217: }

    219: PETSC_INTERN PetscErrorCode TaoTermCallbacksSetObjectiveAndGradient(TaoTerm term, PetscErrorCode (*tao_objgrad)(Tao, Vec, PetscReal *, Vec, PetscCtx), PetscCtx ctx)
    220: {
    221:   PetscFunctionBegin;
    223:   PetscTryMethod(term, "TaoTermCallbacksSetObjectiveAndGradient_C", (TaoTerm, PetscErrorCode (*)(Tao, Vec, PetscReal *, Vec, PetscCtx), PetscCtx), (term, tao_objgrad, ctx));
    224:   PetscFunctionReturn(PETSC_SUCCESS);
    225: }

    227: static PetscErrorCode TaoTermCallbacksSetObjectiveAndGradient_Callbacks(TaoTerm term, PetscErrorCode (*tao_objgrad)(Tao, Vec, PetscReal *, Vec, PetscCtx), PetscCtx ctx)
    228: {
    229:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

    231:   PetscFunctionBegin;
    232:   tt->objectiveandgradient = tao_objgrad;
    233:   tt->objgrad_ctx          = ctx;
    234:   PetscFunctionReturn(PETSC_SUCCESS);
    235: }

    237: PETSC_INTERN PetscErrorCode TaoTermCallbacksGetObjectiveAndGradient(TaoTerm term, PetscErrorCode (**tao_objgrad)(Tao, Vec, PetscReal *, Vec, PetscCtx), PetscCtxRt ctx)
    238: {
    239:   PetscFunctionBegin;
    241:   if (tao_objgrad) *tao_objgrad = NULL;
    242:   if (ctx) *(void **)ctx = NULL;
    243:   PetscTryMethod(term, "TaoTermCallbacksGetObjectiveAndGradient_C", (TaoTerm, PetscErrorCode (**)(Tao, Vec, PetscReal *, Vec, PetscCtx), PetscCtxRt), (term, tao_objgrad, ctx));
    244:   PetscFunctionReturn(PETSC_SUCCESS);
    245: }

    247: static PetscErrorCode TaoTermCallbacksGetObjectiveAndGradient_Callbacks(TaoTerm term, PetscErrorCode (**tao_objgrad)(Tao, Vec, PetscReal *, Vec, PetscCtx), PetscCtxRt ctx)
    248: {
    249:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

    251:   PetscFunctionBegin;
    252:   if (tao_objgrad) *tao_objgrad = tt->objectiveandgradient;
    253:   if (ctx) *(void **)ctx = tt->objgrad_ctx;
    254:   PetscFunctionReturn(PETSC_SUCCESS);
    255: }

    257: PETSC_INTERN PetscErrorCode TaoTermCallbacksSetHessian(TaoTerm term, PetscErrorCode (*tao_hess)(Tao, Vec, Mat, Mat, PetscCtx), PetscCtx ctx)
    258: {
    259:   PetscFunctionBegin;
    261:   PetscTryMethod(term, "TaoTermCallbacksSetHessian_C", (TaoTerm, PetscErrorCode (*)(Tao, Vec, Mat, Mat, PetscCtx), PetscCtx), (term, tao_hess, ctx));
    262:   PetscFunctionReturn(PETSC_SUCCESS);
    263: }

    265: static PetscErrorCode TaoTermCallbacksSetHessian_Callbacks(TaoTerm term, PetscErrorCode (*tao_hess)(Tao, Vec, Mat, Mat, PetscCtx), PetscCtx ctx)
    266: {
    267:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

    269:   PetscFunctionBegin;
    270:   tt->hessian  = tao_hess;
    271:   tt->hess_ctx = ctx;
    272:   PetscFunctionReturn(PETSC_SUCCESS);
    273: }

    275: PETSC_INTERN PetscErrorCode TaoTermCallbacksGetHessian(TaoTerm term, PetscErrorCode (**tao_hess)(Tao, Vec, Mat, Mat, PetscCtx), PetscCtxRt ctx)
    276: {
    277:   PetscFunctionBegin;
    279:   if (tao_hess) *tao_hess = NULL;
    280:   if (ctx) *(void **)ctx = NULL;
    281:   PetscTryMethod(term, "TaoTermCallbacksGetHessian_C", (TaoTerm, PetscErrorCode (**)(Tao, Vec, Mat, Mat, PetscCtx), PetscCtxRt), (term, tao_hess, ctx));
    282:   PetscFunctionReturn(PETSC_SUCCESS);
    283: }

    285: static PetscErrorCode TaoTermCallbacksGetHessian_Callbacks(TaoTerm term, PetscErrorCode (**tao_hess)(Tao, Vec, Mat, Mat, PetscCtx), PetscCtxRt ctx)
    286: {
    287:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

    289:   PetscFunctionBegin;
    290:   if (tao_hess) *tao_hess = tt->hessian;
    291:   if (ctx) *(void **)ctx = tt->hess_ctx;
    292:   PetscFunctionReturn(PETSC_SUCCESS);
    293: }

    295: static PetscErrorCode TaoTermIsObjectiveDefined_Callbacks(TaoTerm term, PetscBool *flg)
    296: {
    297:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

    299:   PetscFunctionBegin;
    300:   *flg = (tt->objective != NULL) ? PETSC_TRUE : PETSC_FALSE;
    301:   PetscFunctionReturn(PETSC_SUCCESS);
    302: }

    304: static PetscErrorCode TaoTermIsGradientDefined_Callbacks(TaoTerm term, PetscBool *flg)
    305: {
    306:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

    308:   PetscFunctionBegin;
    309:   *flg = (tt->gradient != NULL) ? PETSC_TRUE : PETSC_FALSE;
    310:   PetscFunctionReturn(PETSC_SUCCESS);
    311: }

    313: static PetscErrorCode TaoTermIsObjectiveAndGradientDefined_Callbacks(TaoTerm term, PetscBool *flg)
    314: {
    315:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

    317:   PetscFunctionBegin;
    318:   *flg = (tt->objectiveandgradient != NULL) ? PETSC_TRUE : PETSC_FALSE;
    319:   PetscFunctionReturn(PETSC_SUCCESS);
    320: }

    322: static PetscErrorCode TaoTermIsHessianDefined_Callbacks(TaoTerm term, PetscBool *flg)
    323: {
    324:   TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)term->data;

    326:   PetscFunctionBegin;
    327:   *flg = (tt->hessian != NULL) ? PETSC_TRUE : PETSC_FALSE;
    328:   PetscFunctionReturn(PETSC_SUCCESS);
    329: }

    331: static PetscErrorCode TaoTermCreateHessianMatrices_Callbacks(TaoTerm term, Mat *H, Mat *Hpre)
    332: {
    333:   PetscFunctionBegin;
    334:   if (H) *H = NULL;
    335:   if (Hpre) *Hpre = NULL;
    336:   PetscFunctionReturn(PETSC_SUCCESS);
    337: }

    339: static PetscErrorCode TaoTermCreate_Callbacks_Internal(TaoTerm term, const char obj[], const char set_obj[], const char grad[], const char set_grad[], const char objgrad[], const char set_objgrad[], const char hess[], const char set_hess[])
    340: {
    341:   TaoTerm_Callbacks *tt;
    342:   char               buf[256];
    343:   size_t             len = PETSC_STATIC_ARRAY_LENGTH(buf);

    345:   PetscFunctionBegin;
    346:   term->parameters_mode = TAOTERM_PARAMETERS_NONE;

    348:   PetscCall(PetscNew(&tt));
    349:   term->data = (void *)tt;

    351:   term->ops->destroy                       = TaoTermDestroy_Callbacks;
    352:   term->ops->objective                     = TaoTermComputeObjective_Callbacks;
    353:   term->ops->gradient                      = TaoTermComputeGradient_Callbacks;
    354:   term->ops->objectiveandgradient          = TaoTermComputeObjectiveAndGradient_Callbacks;
    355:   term->ops->hessian                       = TaoTermComputeHessian_Callbacks;
    356:   term->ops->createhessianmatrices         = TaoTermCreateHessianMatrices_Callbacks;
    357:   term->ops->view                          = TaoTermView_Callbacks;
    358:   term->ops->isobjectivedefined            = TaoTermIsObjectiveDefined_Callbacks;
    359:   term->ops->isgradientdefined             = TaoTermIsGradientDefined_Callbacks;
    360:   term->ops->isobjectiveandgradientdefined = TaoTermIsObjectiveAndGradientDefined_Callbacks;
    361:   term->ops->ishessiandefined              = TaoTermIsHessianDefined_Callbacks;
    362:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksSetObjective_C", TaoTermCallbacksSetObjective_Callbacks));
    363:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksGetObjective_C", TaoTermCallbacksGetObjective_Callbacks));
    364:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksSetGradient_C", TaoTermCallbacksSetGradient_Callbacks));
    365:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksGetGradient_C", TaoTermCallbacksGetGradient_Callbacks));
    366:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksSetObjectiveAndGradient_C", TaoTermCallbacksSetObjectiveAndGradient_Callbacks));
    367:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksGetObjectiveAndGradient_C", TaoTermCallbacksGetObjectiveAndGradient_Callbacks));
    368:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksSetHessian_C", TaoTermCallbacksSetHessian_Callbacks));
    369:   PetscCall(PetscObjectComposeFunction((PetscObject)term, "TaoTermCallbacksGetHessian_C", TaoTermCallbacksGetHessian_Callbacks));

    371:   PetscCall(PetscSNPrintf(buf, len, "%s callback", obj ? obj : "unknown objective"));
    372:   PetscCall(PetscStrallocpy(buf, &tt->obj_name));
    373:   PetscCall(PetscStrallocpy(set_obj, &tt->set_obj_name));

    375:   PetscCall(PetscSNPrintf(buf, len, "%s callback", grad ? grad : "unknown gradient"));
    376:   PetscCall(PetscStrallocpy(buf, &tt->grad_name));
    377:   PetscCall(PetscStrallocpy(set_grad, &tt->set_grad_name));

    379:   PetscCall(PetscSNPrintf(buf, len, "%s callback", objgrad ? objgrad : "unknown objective/gradient"));
    380:   PetscCall(PetscStrallocpy(buf, &tt->objgrad_name));
    381:   PetscCall(PetscStrallocpy(set_objgrad, &tt->set_objgrad_name));

    383:   PetscCall(PetscSNPrintf(buf, len, "%s callback", hess ? hess : "unknown hessian"));
    384:   PetscCall(PetscStrallocpy(buf, &tt->hess_name));
    385:   PetscCall(PetscStrallocpy(set_hess, &tt->set_hess_name));
    386:   PetscFunctionReturn(PETSC_SUCCESS);
    387: }

    389: /*MC
    390:   TAOTERMCALLBACKS - A `TaoTerm` implementation that accesses the callback functions that have
    391:   been provided with in `TaoSetObjective()`, `TaoSetGradient()`,
    392:   `TaoSetObjectiveAndGradient()`, and `TaoSetHessian()`.

    394:   Level: developer

    396:   Notes:
    397:   If you are interested in creating your own term, you should not use this. Use
    398:   `TAOTERMSHELL` or create your own implementation of `TaoTerm` with
    399:   `TaoTermRegister()`.

    401:   A `TAOTERMCALLBACKS` is always `TAOTERM_PARAMETERS_NONE`, so the `params`
    402:   argument of `TaoTerm` evaluation routines should always be `NULL`.

    404:   A `TAOTERMCALLBACKS` cannot create Hessian matrices; the user needs to pass the
    405:   Hessian matrices used in algorithms in `TaoSetHessian()`.

    407:   Developer Notes:
    408:   Internally each `Tao` has a `TaoTerm` of type `TAOTERMCALLBACKS` that is updated
    409:   by the `Tao` callback routines (`TaoSetObjective()`, `TaoSetGradient()`,
    410:   `TaoSetObjectiveAndGradient()`, and `TaoSetHessian()`).

    412:   The routines that get the user-defined `Tao` callback functions
    413:   (`TaoGetObjective()`, `TaoGetObjectiveAndGradient()`, `TaoGetGradient()`,
    414:   `TaoGetHessian()`) will always return those original callbacks, even if the
    415:   objective function has been changed by `TaoAddTerm()`,
    416:   so PETSc/TAO should not assume that those callbacks are valid in any library code.

    418:   A `TAOTERMCALLBACKS` has a weak-reference to the `Tao` that created it,
    419:   which may not be the `Tao` currently using it because the term could have been shared
    420:   using `TaoGetTerm()` and `TaoAddTerm()`.

    422: .seealso: [](sec_tao_term),
    423:           `TaoTerm`,
    424:           `TaoTermType`
    425: M*/
    426: PETSC_INTERN PetscErrorCode TaoTermCreate_Callbacks(TaoTerm term)
    427: {
    428:   PetscFunctionBegin;
    429:   // clang-format off
    430:   PetscCall(TaoTermCreate_Callbacks_Internal(term,
    431:         "TaoComputeObjective()",            "TaoSetObjective()",
    432:         "TaoComputeGradient()",             "TaoSetGradient()",
    433:         "TaoComputeObjectiveAndGradient()", "TaoSetObjectiveAndGradient()",
    434:         "TaoComputeHessian()",              "TaoSetHessian()"));
    435:   // clang-format on
    436:   PetscFunctionReturn(PETSC_SUCCESS);
    437: }

    439: PETSC_INTERN PetscErrorCode TaoTermCreateCallbacks(Tao tao, TaoTerm *term)
    440: {
    441:   PetscFunctionBegin;
    442:   PetscCall(TaoTermCreate(PetscObjectComm((PetscObject)tao), term));
    443:   PetscCall(TaoTermSetType(*term, TAOTERMCALLBACKS));
    444:   {
    445:     TaoTerm_Callbacks *tt = (TaoTerm_Callbacks *)((*term)->data);

    447:     tt->tao = tao; // weak reference, do not increment reference count
    448:   }
    449:   PetscFunctionReturn(PETSC_SUCCESS);
    450: }