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: }