Actual source code: taosolver_fg.c

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

      3: /*@
      4:   TaoSetSolution - Sets the vector holding the initial guess for the solve

      6:   Logically collective on Tao

      8:   Input Parameters:
      9: + tao - the Tao context
     10: - x0  - the initial guess

     12:   Level: beginner
     13: .seealso: TaoCreate(), TaoSolve(), TaoGetSolution()
     14: @*/
     15: PetscErrorCode TaoSetSolution(Tao tao, Vec x0)
     16: {
     19:   PetscObjectReference((PetscObject)x0);
     20:   VecDestroy(&tao->solution);
     21:   tao->solution = x0;
     22:   return 0;
     23: }

     25: PetscErrorCode TaoTestGradient(Tao tao,Vec x,Vec g1)
     26: {
     27:   Vec               g2,g3;
     28:   PetscBool         complete_print = PETSC_FALSE,test = PETSC_FALSE;
     29:   PetscReal         hcnorm,fdnorm,hcmax,fdmax,diffmax,diffnorm;
     30:   PetscScalar       dot;
     31:   MPI_Comm          comm;
     32:   PetscViewer       viewer,mviewer;
     33:   PetscViewerFormat format;
     34:   PetscInt          tabs;
     35:   static PetscBool  directionsprinted = PETSC_FALSE;
     36:   PetscErrorCode    ierr;

     38:   PetscObjectOptionsBegin((PetscObject)tao);
     39:   PetscOptionsName("-tao_test_gradient","Compare hand-coded and finite difference Gradients","None",&test);
     40:   PetscOptionsViewer("-tao_test_gradient_view","View difference between hand-coded and finite difference Gradients element entries","None",&mviewer,&format,&complete_print);
     41:   PetscOptionsEnd();
     42:   if (!test) {
     43:     if (complete_print) {
     44:       PetscViewerDestroy(&mviewer);
     45:     }
     46:     return 0;
     47:   }

     49:   PetscObjectGetComm((PetscObject)tao,&comm);
     50:   PetscViewerASCIIGetStdout(comm,&viewer);
     51:   PetscViewerASCIIGetTab(viewer, &tabs);
     52:   PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel);
     53:   PetscViewerASCIIPrintf(viewer,"  ---------- Testing Gradient -------------\n");
     54:   if (!complete_print && !directionsprinted) {
     55:     PetscViewerASCIIPrintf(viewer,"  Run with -tao_test_gradient_view and optionally -tao_test_gradient <threshold> to show difference\n");
     56:     PetscViewerASCIIPrintf(viewer,"    of hand-coded and finite difference gradient entries greater than <threshold>.\n");
     57:   }
     58:   if (!directionsprinted) {
     59:     PetscViewerASCIIPrintf(viewer,"  Testing hand-coded Gradient, if (for double precision runs) ||G - Gfd||/||G|| is\n");
     60:     PetscViewerASCIIPrintf(viewer,"    O(1.e-8), the hand-coded Gradient is probably correct.\n");
     61:     directionsprinted = PETSC_TRUE;
     62:   }
     63:   if (complete_print) {
     64:     PetscViewerPushFormat(mviewer,format);
     65:   }

     67:   VecDuplicate(x,&g2);
     68:   VecDuplicate(x,&g3);

     70:   /* Compute finite difference gradient, assume the gradient is already computed by TaoComputeGradient() and put into g1 */
     71:   TaoDefaultComputeGradient(tao,x,g2,NULL);

     73:   VecNorm(g2,NORM_2,&fdnorm);
     74:   VecNorm(g1,NORM_2,&hcnorm);
     75:   VecNorm(g2,NORM_INFINITY,&fdmax);
     76:   VecNorm(g1,NORM_INFINITY,&hcmax);
     77:   VecDot(g1,g2,&dot);
     78:   VecCopy(g1,g3);
     79:   VecAXPY(g3,-1.0,g2);
     80:   VecNorm(g3,NORM_2,&diffnorm);
     81:   VecNorm(g3,NORM_INFINITY,&diffmax);
     82:   PetscViewerASCIIPrintf(viewer,"  ||Gfd|| %g, ||G|| = %g, angle cosine = (Gfd'G)/||Gfd||||G|| = %g\n", (double)fdnorm, (double)hcnorm, (double)(PetscRealPart(dot)/(fdnorm*hcnorm)));
     83:   PetscViewerASCIIPrintf(viewer,"  2-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n",(double)(diffnorm/PetscMax(hcnorm,fdnorm)),(double)diffnorm);
     84:   PetscViewerASCIIPrintf(viewer,"  max-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n",(double)(diffmax/PetscMax(hcmax,fdmax)),(double)diffmax);

     86:   if (complete_print) {
     87:     PetscViewerASCIIPrintf(viewer,"  Hand-coded gradient ----------\n");
     88:     VecView(g1,mviewer);
     89:     PetscViewerASCIIPrintf(viewer,"  Finite difference gradient ----------\n");
     90:     VecView(g2,mviewer);
     91:     PetscViewerASCIIPrintf(viewer,"  Hand-coded minus finite-difference gradient ----------\n");
     92:     VecView(g3,mviewer);
     93:   }
     94:   VecDestroy(&g2);
     95:   VecDestroy(&g3);

     97:   if (complete_print) {
     98:     PetscViewerPopFormat(mviewer);
     99:     PetscViewerDestroy(&mviewer);
    100:   }
    101:   PetscViewerASCIISetTab(viewer,tabs);
    102:   return 0;
    103: }

    105: /*@
    106:   TaoComputeGradient - Computes the gradient of the objective function

    108:   Collective on Tao

    110:   Input Parameters:
    111: + tao - the Tao context
    112: - X - input vector

    114:   Output Parameter:
    115: . G - gradient vector

    117:   Options Database Keys:
    118: +    -tao_test_gradient - compare the user provided gradient with one compute via finite differences to check for errors
    119: -    -tao_test_gradient_view - display the user provided gradient, the finite difference gradient and the difference between them to help users detect the location of errors in the user provided gradient

    121:   Notes:
    122:     TaoComputeGradient() is typically used within minimization implementations,
    123:   so most users would not generally call this routine themselves.

    125:   Level: advanced

    127: .seealso: TaoComputeObjective(), TaoComputeObjectiveAndGradient(), TaoSetGradient()
    128: @*/
    129: PetscErrorCode TaoComputeGradient(Tao tao, Vec X, Vec G)
    130: {
    131:   PetscReal      dummy;

    138:   VecLockReadPush(X);
    139:   if (tao->ops->computegradient) {
    140:     PetscLogEventBegin(TAO_GradientEval,tao,X,G,NULL);
    141:     PetscStackPush("Tao user gradient evaluation routine");
    142:     (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);
    143:     PetscStackPop;
    144:     PetscLogEventEnd(TAO_GradientEval,tao,X,G,NULL);
    145:     tao->ngrads++;
    146:   } else if (tao->ops->computeobjectiveandgradient) {
    147:     PetscLogEventBegin(TAO_ObjGradEval,tao,X,G,NULL);
    148:     PetscStackPush("Tao user objective/gradient evaluation routine");
    149:     (*tao->ops->computeobjectiveandgradient)(tao,X,&dummy,G,tao->user_objgradP);
    150:     PetscStackPop;
    151:     PetscLogEventEnd(TAO_ObjGradEval,tao,X,G,NULL);
    152:     tao->nfuncgrads++;
    153:   } else SETERRQ(PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"TaoSetGradient() has not been called");
    154:   VecLockReadPop(X);

    156:   TaoTestGradient(tao,X,G);
    157:   return 0;
    158: }

    160: /*@
    161:   TaoComputeObjective - Computes the objective function value at a given point

    163:   Collective on Tao

    165:   Input Parameters:
    166: + tao - the Tao context
    167: - X - input vector

    169:   Output Parameter:
    170: . f - Objective value at X

    172:   Notes:
    173:     TaoComputeObjective() is typically used within minimization implementations,
    174:   so most users would not generally call this routine themselves.

    176:   Level: advanced

    178: .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjective()
    179: @*/
    180: PetscErrorCode TaoComputeObjective(Tao tao, Vec X, PetscReal *f)
    181: {
    182:   Vec            temp;

    187:   VecLockReadPush(X);
    188:   if (tao->ops->computeobjective) {
    189:     PetscLogEventBegin(TAO_ObjectiveEval,tao,X,NULL,NULL);
    190:     PetscStackPush("Tao user objective evaluation routine");
    191:     (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);
    192:     PetscStackPop;
    193:     PetscLogEventEnd(TAO_ObjectiveEval,tao,X,NULL,NULL);
    194:     tao->nfuncs++;
    195:   } else if (tao->ops->computeobjectiveandgradient) {
    196:     PetscInfo(tao,"Duplicating variable vector in order to call func/grad routine\n");
    197:     VecDuplicate(X,&temp);
    198:     PetscLogEventBegin(TAO_ObjGradEval,tao,X,NULL,NULL);
    199:     PetscStackPush("Tao user objective/gradient evaluation routine");
    200:     (*tao->ops->computeobjectiveandgradient)(tao,X,f,temp,tao->user_objgradP);
    201:     PetscStackPop;
    202:     PetscLogEventEnd(TAO_ObjGradEval,tao,X,NULL,NULL);
    203:     VecDestroy(&temp);
    204:     tao->nfuncgrads++;
    205:   } else SETERRQ(PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjective() has not been called");
    206:   PetscInfo(tao,"TAO Function evaluation: %20.19e\n",(double)(*f));
    207:   VecLockReadPop(X);
    208:   return 0;
    209: }

    211: /*@
    212:   TaoComputeObjectiveAndGradient - Computes the objective function value at a given point

    214:   Collective on Tao

    216:   Input Parameters:
    217: + tao - the Tao context
    218: - X - input vector

    220:   Output Parameters:
    221: + f - Objective value at X
    222: - g - Gradient vector at X

    224:   Notes:
    225:     TaoComputeObjectiveAndGradient() is typically used within minimization implementations,
    226:   so most users would not generally call this routine themselves.

    228:   Level: advanced

    230: .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjective()
    231: @*/
    232: PetscErrorCode TaoComputeObjectiveAndGradient(Tao tao, Vec X, PetscReal *f, Vec G)
    233: {
    239:   VecLockReadPush(X);
    240:   if (tao->ops->computeobjectiveandgradient) {
    241:     PetscLogEventBegin(TAO_ObjGradEval,tao,X,G,NULL);
    242:     if (tao->ops->computegradient == TaoDefaultComputeGradient) {
    243:       TaoComputeObjective(tao,X,f);
    244:       TaoDefaultComputeGradient(tao,X,G,NULL);
    245:     } else {
    246:       PetscStackPush("Tao user objective/gradient evaluation routine");
    247:       (*tao->ops->computeobjectiveandgradient)(tao,X,f,G,tao->user_objgradP);
    248:       PetscStackPop;
    249:     }
    250:     PetscLogEventEnd(TAO_ObjGradEval,tao,X,G,NULL);
    251:     tao->nfuncgrads++;
    252:   } else if (tao->ops->computeobjective && tao->ops->computegradient) {
    253:     PetscLogEventBegin(TAO_ObjectiveEval,tao,X,NULL,NULL);
    254:     PetscStackPush("Tao user objective evaluation routine");
    255:     (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);
    256:     PetscStackPop;
    257:     PetscLogEventEnd(TAO_ObjectiveEval,tao,X,NULL,NULL);
    258:     tao->nfuncs++;
    259:     PetscLogEventBegin(TAO_GradientEval,tao,X,G,NULL);
    260:     PetscStackPush("Tao user gradient evaluation routine");
    261:     (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);
    262:     PetscStackPop;
    263:     PetscLogEventEnd(TAO_GradientEval,tao,X,G,NULL);
    264:     tao->ngrads++;
    265:   } else SETERRQ(PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjective() or TaoSetGradient() not set");
    266:   PetscInfo(tao,"TAO Function evaluation: %20.19e\n",(double)(*f));
    267:   VecLockReadPop(X);

    269:   TaoTestGradient(tao,X,G);
    270:   return 0;
    271: }

    273: /*@C
    274:   TaoSetObjective - Sets the function evaluation routine for minimization

    276:   Logically collective on Tao

    278:   Input Parameters:
    279: + tao - the Tao context
    280: . func - the objective function
    281: - ctx - [optional] user-defined context for private data for the function evaluation
    282:         routine (may be NULL)

    284:   Calling sequence of func:
    285: $      func (Tao tao, Vec x, PetscReal *f, void *ctx);

    287: + x - input vector
    288: . f - function value
    289: - ctx - [optional] user-defined function context

    291:   Level: beginner

    293: .seealso: TaoSetGradient(), TaoSetHessian(), TaoSetObjectiveAndGradient(), TaoGetObjective()
    294: @*/
    295: PetscErrorCode TaoSetObjective(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal*,void*),void *ctx)
    296: {
    298:   if (ctx) tao->user_objP = ctx;
    299:   if (func) tao->ops->computeobjective = func;
    300:   return 0;
    301: }

    303: /*@C
    304:   TaoGetObjective - Gets the function evaluation routine for minimization

    306:   Not collective

    308:   Input Parameter:
    309: . tao - the Tao context

    311:   Output Parameters
    312: + func - the objective function
    313: - ctx - the user-defined context for private data for the function evaluation

    315:   Calling sequence of func:
    316: $      func (Tao tao, Vec x, PetscReal *f, void *ctx);

    318: + x - input vector
    319: . f - function value
    320: - ctx - [optional] user-defined function context

    322:   Level: beginner

    324: .seealso: TaoSetGradient(), TaoSetHessian(), TaoSetObjective()
    325: @*/
    326: PetscErrorCode TaoGetObjective(Tao tao, PetscErrorCode (**func)(Tao, Vec, PetscReal*,void*),void **ctx)
    327: {
    329:   if (func) *func = tao->ops->computeobjective;
    330:   if (ctx) *ctx = tao->user_objP;
    331:   return 0;
    332: }

    334: /*@C
    335:   TaoSetResidualRoutine - Sets the residual evaluation routine for least-square applications

    337:   Logically collective on Tao

    339:   Input Parameters:
    340: + tao - the Tao context
    341: . func - the residual evaluation routine
    342: - ctx - [optional] user-defined context for private data for the function evaluation
    343:         routine (may be NULL)

    345:   Calling sequence of func:
    346: $      func (Tao tao, Vec x, Vec f, void *ctx);

    348: + x - input vector
    349: . f - function value vector
    350: - ctx - [optional] user-defined function context

    352:   Level: beginner

    354: .seealso: TaoSetObjective(), TaoSetJacobianRoutine()
    355: @*/
    356: PetscErrorCode TaoSetResidualRoutine(Tao tao, Vec res, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx)
    357: {
    360:   PetscObjectReference((PetscObject)res);
    361:   if (tao->ls_res) {
    362:     VecDestroy(&tao->ls_res);
    363:   }
    364:   tao->ls_res = res;
    365:   tao->user_lsresP = ctx;
    366:   tao->ops->computeresidual = func;

    368:   return 0;
    369: }

    371: /*@
    372:   TaoSetResidualWeights - Give weights for the residual values. A vector can be used if only diagonal terms are used, otherwise a matrix can be give. If this function is not used, or if sigma_v and sigma_w are both NULL, then the default identity matrix will be used for weights.

    374:   Collective on Tao

    376:   Input Parameters:
    377: + tao - the Tao context
    378: . sigma_v - vector of weights (diagonal terms only)
    379: . n       - the number of weights (if using off-diagonal)
    380: . rows    - index list of rows for sigma_w
    381: . cols    - index list of columns for sigma_w
    382: - vals - array of weights

    384:   Note: Either sigma_v or sigma_w (or both) should be NULL

    386:   Level: intermediate

    388: .seealso: TaoSetResidualRoutine()
    389: @*/
    390: PetscErrorCode TaoSetResidualWeights(Tao tao, Vec sigma_v, PetscInt n, PetscInt *rows, PetscInt *cols, PetscReal *vals)
    391: {
    392:   PetscInt       i;

    396:   PetscObjectReference((PetscObject)sigma_v);
    397:   VecDestroy(&tao->res_weights_v);
    398:   tao->res_weights_v = sigma_v;
    399:   if (vals) {
    400:     PetscFree(tao->res_weights_rows);
    401:     PetscFree(tao->res_weights_cols);
    402:     PetscFree(tao->res_weights_w);
    403:     PetscMalloc1(n,&tao->res_weights_rows);
    404:     PetscMalloc1(n,&tao->res_weights_cols);
    405:     PetscMalloc1(n,&tao->res_weights_w);
    406:     tao->res_weights_n = n;
    407:     for (i=0;i<n;i++) {
    408:       tao->res_weights_rows[i] = rows[i];
    409:       tao->res_weights_cols[i] = cols[i];
    410:       tao->res_weights_w[i] = vals[i];
    411:     }
    412:   } else {
    413:     tao->res_weights_n = 0;
    414:     tao->res_weights_rows = NULL;
    415:     tao->res_weights_cols = NULL;
    416:   }
    417:   return 0;
    418: }

    420: /*@
    421:   TaoComputeResidual - Computes a least-squares residual vector at a given point

    423:   Collective on Tao

    425:   Input Parameters:
    426: + tao - the Tao context
    427: - X - input vector

    429:   Output Parameter:
    430: . f - Objective vector at X

    432:   Notes:
    433:     TaoComputeResidual() is typically used within minimization implementations,
    434:   so most users would not generally call this routine themselves.

    436:   Level: advanced

    438: .seealso: TaoSetResidualRoutine()
    439: @*/
    440: PetscErrorCode TaoComputeResidual(Tao tao, Vec X, Vec F)
    441: {
    447:   if (tao->ops->computeresidual) {
    448:     PetscLogEventBegin(TAO_ObjectiveEval,tao,X,NULL,NULL);
    449:     PetscStackPush("Tao user least-squares residual evaluation routine");
    450:     (*tao->ops->computeresidual)(tao,X,F,tao->user_lsresP);
    451:     PetscStackPop;
    452:     PetscLogEventEnd(TAO_ObjectiveEval,tao,X,NULL,NULL);
    453:     tao->nfuncs++;
    454:   } else SETERRQ(PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"TaoSetResidualRoutine() has not been called");
    455:   PetscInfo(tao,"TAO least-squares residual evaluation.\n");
    456:   return 0;
    457: }

    459: /*@C
    460:   TaoSetGradient - Sets the gradient evaluation routine for minimization

    462:   Logically collective on Tao

    464:   Input Parameters:
    465: + tao - the Tao context
    466: . g - [optional] the vector to internally hold the gradient computation
    467: . func - the gradient function
    468: - ctx - [optional] user-defined context for private data for the gradient evaluation
    469:         routine (may be NULL)

    471:   Calling sequence of func:
    472: $      func (Tao tao, Vec x, Vec g, void *ctx);

    474: + x - input vector
    475: . g - gradient value (output)
    476: - ctx - [optional] user-defined function context

    478:   Level: beginner

    480: .seealso: TaoSetObjective(), TaoSetHessian(), TaoSetObjectiveAndGradient(), TaoGetGradient()
    481: @*/
    482: PetscErrorCode TaoSetGradient(Tao tao, Vec g, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx)
    483: {
    485:   if (g) {
    488:     PetscObjectReference((PetscObject)g);
    489:     VecDestroy(&tao->gradient);
    490:     tao->gradient = g;
    491:   }
    492:   if (func) tao->ops->computegradient = func;
    493:   if (ctx) tao->user_gradP = ctx;
    494:   return 0;
    495: }

    497: /*@C
    498:   TaoGetGradient - Gets the gradient evaluation routine for minimization

    500:   Not collective

    502:   Input Parameter:
    503: . tao - the Tao context

    505:   Output Parameters:
    506: + g - the vector to internally hold the gradient computation
    507: . func - the gradient function
    508: - ctx - user-defined context for private data for the gradient evaluation routine

    510:   Calling sequence of func:
    511: $      func (Tao tao, Vec x, Vec g, void *ctx);

    513: + x - input vector
    514: . g - gradient value (output)
    515: - ctx - [optional] user-defined function context

    517:   Level: beginner

    519: .seealso: TaoSetObjective(), TaoSetHessian(), TaoSetObjectiveAndGradient(), TaoSetGradient()
    520: @*/
    521: PetscErrorCode TaoGetGradient(Tao tao, Vec *g, PetscErrorCode (**func)(Tao, Vec, Vec, void*),void **ctx)
    522: {
    524:   if (g) *g = tao->gradient;
    525:   if (func) *func = tao->ops->computegradient;
    526:   if (ctx) *ctx = tao->user_gradP;
    527:   return 0;
    528: }

    530: /*@C
    531:   TaoSetObjectiveAndGradient - Sets a combined objective function and gradient evaluation routine for minimization

    533:   Logically collective on Tao

    535:   Input Parameters:
    536: + tao - the Tao context
    537: . g - [optional] the vector to internally hold the gradient computation
    538: . func - the gradient function
    539: - ctx - [optional] user-defined context for private data for the gradient evaluation
    540:         routine (may be NULL)

    542:   Calling sequence of func:
    543: $      func (Tao tao, Vec x, PetscReal *f, Vec g, void *ctx);

    545: + x - input vector
    546: . f - objective value (output)
    547: . g - gradient value (output)
    548: - ctx - [optional] user-defined function context

    550:   Level: beginner

    552: .seealso: TaoSetObjective(), TaoSetHessian(), TaoSetGradient(), TaoGetObjectiveAndGradient()
    553: @*/
    554: PetscErrorCode TaoSetObjectiveAndGradient(Tao tao, Vec g, PetscErrorCode (*func)(Tao, Vec, PetscReal*, Vec, void*), void *ctx)
    555: {
    557:   if (g) {
    560:     PetscObjectReference((PetscObject)g);
    561:     VecDestroy(&tao->gradient);
    562:     tao->gradient = g;
    563:   }
    564:   if (ctx) tao->user_objgradP = ctx;
    565:   if (func) tao->ops->computeobjectiveandgradient = func;
    566:   return 0;
    567: }

    569: /*@C
    570:   TaoGetObjectiveAndGradient - Gets a combined objective function and gradient evaluation routine for minimization

    572:   Not collective

    574:   Input Parameter:
    575: . tao - the Tao context

    577:   Output Parameters:
    578: + g - the vector to internally hold the gradient computation
    579: . func - the gradient function
    580: - ctx - user-defined context for private data for the gradient evaluation routine

    582:   Calling sequence of func:
    583: $      func (Tao tao, Vec x, PetscReal *f, Vec g, void *ctx);

    585: + x - input vector
    586: . f - objective value (output)
    587: . g - gradient value (output)
    588: - ctx - [optional] user-defined function context

    590:   Level: beginner

    592: .seealso: TaoSetObjective(), TaoSetGradient(), TaoSetHessian(), TaoSetObjectiveAndGradient()
    593: @*/
    594: PetscErrorCode TaoGetObjectiveAndGradient(Tao tao, Vec *g, PetscErrorCode (**func)(Tao, Vec, PetscReal*, Vec, void*), void **ctx)
    595: {
    597:   if (g) *g = tao->gradient;
    598:   if (func) *func = tao->ops->computeobjectiveandgradient;
    599:   if (ctx) *ctx = tao->user_objgradP;
    600:   return 0;
    601: }

    603: /*@
    604:   TaoIsObjectiveDefined - Checks to see if the user has
    605:   declared an objective-only routine.  Useful for determining when
    606:   it is appropriate to call TaoComputeObjective() or
    607:   TaoComputeObjectiveAndGradient()

    609:   Not collective

    611:   Input Parameter:
    612: . tao - the Tao context

    614:   Output Parameter:
    615: . flg - PETSC_TRUE if function routine is set by user, PETSC_FALSE otherwise

    617:   Level: developer

    619: .seealso: TaoSetObjective(), TaoIsGradientDefined(), TaoIsObjectiveAndGradientDefined()
    620: @*/
    621: PetscErrorCode TaoIsObjectiveDefined(Tao tao, PetscBool *flg)
    622: {
    624:   if (tao->ops->computeobjective == NULL) *flg = PETSC_FALSE;
    625:   else *flg = PETSC_TRUE;
    626:   return 0;
    627: }

    629: /*@
    630:   TaoIsGradientDefined - Checks to see if the user has
    631:   declared an objective-only routine.  Useful for determining when
    632:   it is appropriate to call TaoComputeGradient() or
    633:   TaoComputeGradientAndGradient()

    635:   Not Collective

    637:   Input Parameter:
    638: . tao - the Tao context

    640:   Output Parameter:
    641: . flg - PETSC_TRUE if function routine is set by user, PETSC_FALSE otherwise

    643:   Level: developer

    645: .seealso: TaoSetGradient(), TaoIsObjectiveDefined(), TaoIsObjectiveAndGradientDefined()
    646: @*/
    647: PetscErrorCode TaoIsGradientDefined(Tao tao, PetscBool *flg)
    648: {
    650:   if (tao->ops->computegradient == NULL) *flg = PETSC_FALSE;
    651:   else *flg = PETSC_TRUE;
    652:   return 0;
    653: }

    655: /*@
    656:   TaoIsObjectiveAndGradientDefined - Checks to see if the user has
    657:   declared a joint objective/gradient routine.  Useful for determining when
    658:   it is appropriate to call TaoComputeObjective() or
    659:   TaoComputeObjectiveAndGradient()

    661:   Not Collective

    663:   Input Parameter:
    664: . tao - the Tao context

    666:   Output Parameter:
    667: . flg - PETSC_TRUE if function routine is set by user, PETSC_FALSE otherwise

    669:   Level: developer

    671: .seealso: TaoSetObjectiveAndGradient(), TaoIsObjectiveDefined(), TaoIsGradientDefined()
    672: @*/
    673: PetscErrorCode TaoIsObjectiveAndGradientDefined(Tao tao, PetscBool *flg)
    674: {
    676:   if (tao->ops->computeobjectiveandgradient == NULL) *flg = PETSC_FALSE;
    677:   else *flg = PETSC_TRUE;
    678:   return 0;
    679: }