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
8: Input Parameters:
9: + tao - the `Tao` context
10: - x0 - the initial guess
12: Level: beginner
14: .seealso: [](ch_tao), `Tao`, `TaoCreate()`, `TaoSolve()`, `TaoGetSolution()`
15: @*/
16: PetscErrorCode TaoSetSolution(Tao tao, Vec x0)
17: {
18: PetscFunctionBegin;
21: PetscCall(PetscObjectReference((PetscObject)x0));
22: PetscCall(VecDestroy(&tao->solution));
23: tao->solution = x0;
24: if (x0) PetscCall(TaoTermSetSolutionTemplate(tao->callbacks, x0));
25: PetscFunctionReturn(PETSC_SUCCESS);
26: }
28: PETSC_INTERN PetscErrorCode TaoTestGradient_Internal(Tao tao, Vec x, Vec g1, PetscViewer viewer, PetscViewer mviewer)
29: {
30: Vec g2, g3;
31: PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
32: PetscScalar dot;
34: PetscFunctionBegin;
35: PetscCall(VecDuplicate(x, &g2));
36: PetscCall(VecDuplicate(x, &g3));
38: /* Compute finite difference gradient, assume the gradient is already computed by TaoComputeGradient() and put into g1 */
39: PetscCall(TaoDefaultComputeGradient(tao, x, g2, NULL));
41: PetscCall(VecNorm(g2, NORM_2, &fdnorm));
42: PetscCall(VecNorm(g1, NORM_2, &hcnorm));
43: PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
44: PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
45: PetscCall(VecDot(g1, g2, &dot));
46: PetscCall(VecCopy(g1, g3));
47: PetscCall(VecAXPY(g3, -1.0, g2));
48: PetscCall(VecNorm(g3, NORM_2, &diffnorm));
49: PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
50: PetscCall(PetscViewerASCIIPrintf(viewer, " ||Gfd|| %g, ||G|| = %g, angle cosine = (Gfd'G)/||Gfd||||G|| = %g\n", (double)fdnorm, (double)hcnorm, (double)(PetscRealPart(dot) / (fdnorm * hcnorm))));
51: PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
52: PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
54: if (mviewer) {
55: PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded gradient ----------\n"));
56: PetscCall(VecView(g1, mviewer));
57: PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference gradient ----------\n"));
58: PetscCall(VecView(g2, mviewer));
59: PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference gradient ----------\n"));
60: PetscCall(VecView(g3, mviewer));
61: }
62: PetscCall(VecDestroy(&g2));
63: PetscCall(VecDestroy(&g3));
64: PetscFunctionReturn(PETSC_SUCCESS);
65: }
67: /*@
68: TaoTestGradient - Compare the user-supplied gradient with a finite-difference approximation, when requested via
69: the options database, and print the difference.
71: Collective
73: Input Parameters:
74: + tao - the `Tao` context
75: . x - the point at which to evaluate the gradient
76: - g1 - the user-supplied gradient at `x`
78: Options Database Keys:
79: + -tao_test_gradient - enable the comparison
80: - -tao_test_gradient_view - display the user-supplied gradient, the finite-difference gradient, and their difference
82: Level: intermediate
84: Note:
85: If `-tao_test_gradient` is not set, this routine returns immediately without performing any work.
87: .seealso: [](ch_tao), `Tao`, `TaoTestHessian()`, `TaoComputeGradient()`
88: @*/
89: PetscErrorCode TaoTestGradient(Tao tao, Vec x, Vec g1)
90: {
91: PetscBool complete_print = PETSC_FALSE, test = PETSC_FALSE;
92: MPI_Comm comm;
93: PetscViewer viewer, mviewer;
94: PetscViewerFormat format;
95: PetscInt tabs;
96: static PetscBool directionsprinted = PETSC_FALSE;
98: PetscFunctionBegin;
99: PetscObjectOptionsBegin((PetscObject)tao);
100: PetscCall(PetscOptionsName("-tao_test_gradient", "Compare hand-coded and finite difference Gradients", "None", &test));
101: PetscCall(PetscOptionsViewer("-tao_test_gradient_view", "View difference between hand-coded and finite difference Gradients element entries", "None", &mviewer, &format, &complete_print));
102: PetscOptionsEnd();
103: if (!test) {
104: if (complete_print) PetscCall(PetscViewerDestroy(&mviewer));
105: PetscFunctionReturn(PETSC_SUCCESS);
106: }
108: PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));
109: PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
110: PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
111: PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
112: PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Gradient -------------\n"));
113: if (!complete_print && !directionsprinted) {
114: PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -tao_test_gradient_view and optionally -tao_test_gradient <threshold> to show difference\n"));
115: PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference gradient entries greater than <threshold>.\n"));
116: }
117: if (!directionsprinted) {
118: PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Gradient, if (for double precision runs) ||G - Gfd||/||G|| is\n"));
119: PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Gradient is probably correct.\n"));
120: directionsprinted = PETSC_TRUE;
121: }
122: if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
123: PetscCall(TaoTestGradient_Internal(tao, x, g1, viewer, complete_print ? mviewer : NULL));
124: if (complete_print) {
125: PetscCall(PetscViewerPopFormat(mviewer));
126: PetscCall(PetscViewerDestroy(&mviewer));
127: }
128: PetscCall(PetscViewerASCIISetTab(viewer, tabs));
129: PetscFunctionReturn(PETSC_SUCCESS);
130: }
132: /*@
133: TaoComputeGradient - Computes the gradient of the objective function
135: Collective
137: Input Parameters:
138: + tao - the `Tao` context
139: - X - input vector
141: Output Parameter:
142: . G - gradient vector
144: Options Database Keys:
145: + -tao_test_gradient - compare the user provided gradient with one compute via finite differences to check for errors
146: - -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
148: Level: developer
150: Note:
151: `TaoComputeGradient()` is typically used within the implementation of the optimization method,
152: so most users would not generally call this routine themselves.
154: .seealso: [](ch_tao), `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetGradient()`
155: @*/
156: PetscErrorCode TaoComputeGradient(Tao tao, Vec X, Vec G)
157: {
158: PetscFunctionBegin;
162: PetscCheckSameComm(tao, 1, X, 2);
163: PetscCheckSameComm(tao, 1, G, 3);
164: PetscCall(TaoTermMappingComputeGradient(&tao->objective_term, X, tao->objective_parameters, INSERT_VALUES, G));
165: PetscCall(TaoTestGradient(tao, X, G));
166: PetscFunctionReturn(PETSC_SUCCESS);
167: }
169: /*@
170: TaoComputeObjective - Computes the objective function value at a given point
172: Collective
174: Input Parameters:
175: + tao - the `Tao` context
176: - X - input vector
178: Output Parameter:
179: . f - Objective value at X
181: Level: developer
183: Note:
184: `TaoComputeObjective()` is typically used within the implementation of the optimization algorithm
185: so most users would not generally call this routine themselves.
187: .seealso: [](ch_tao), `Tao`, `TaoComputeGradient()`, `TaoComputeObjectiveAndGradient()`, `TaoSetObjective()`
188: @*/
189: PetscErrorCode TaoComputeObjective(Tao tao, Vec X, PetscReal *f)
190: {
191: PetscFunctionBegin;
194: PetscAssertPointer(f, 3);
195: PetscCheckSameComm(tao, 1, X, 2);
196: PetscCall(TaoTermMappingComputeObjective(&tao->objective_term, X, tao->objective_parameters, INSERT_VALUES, f));
197: PetscFunctionReturn(PETSC_SUCCESS);
198: }
200: /*@
201: TaoComputeObjectiveAndGradient - Computes the objective function value at a given point
203: Collective
205: Input Parameters:
206: + tao - the `Tao` context
207: - X - input vector
209: Output Parameters:
210: + f - Objective value at `X`
211: - G - Gradient vector at `X`
213: Level: developer
215: Note:
216: `TaoComputeObjectiveAndGradient()` is typically used within the implementation of the optimization algorithm,
217: so most users would not generally call this routine themselves.
219: .seealso: [](ch_tao), `TaoComputeGradient()`, `TaoSetObjective()`
220: @*/
221: PetscErrorCode TaoComputeObjectiveAndGradient(Tao tao, Vec X, PetscReal *f, Vec G)
222: {
223: PetscFunctionBegin;
226: PetscAssertPointer(f, 3);
228: PetscCheckSameComm(tao, 1, X, 2);
229: PetscCheckSameComm(tao, 1, G, 4);
230: PetscCall(TaoTermMappingComputeObjectiveAndGradient(&tao->objective_term, X, tao->objective_parameters, INSERT_VALUES, f, G));
231: PetscCall(TaoTestGradient(tao, X, G));
232: PetscFunctionReturn(PETSC_SUCCESS);
233: }
235: /*@C
236: TaoSetObjective - Sets the function evaluation routine for minimization
238: Logically Collective
240: Input Parameters:
241: + tao - the `Tao` context
242: . func - the objective function
243: - ctx - [optional] user-defined context for private data for the function evaluation
244: routine (may be `NULL`)
246: Calling sequence of `func`:
247: + tao - the optimizer
248: . x - input vector
249: . f - function value
250: - ctx - [optional] user-defined function context
252: Level: beginner
254: .seealso: [](ch_tao), `TaoSetGradient()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoGetObjective()`
255: @*/
256: PetscErrorCode TaoSetObjective(Tao tao, PetscErrorCode (*func)(Tao tao, Vec x, PetscReal *f, PetscCtx ctx), PetscCtx ctx)
257: {
258: PetscFunctionBegin;
260: PetscCall(TaoTermCallbacksSetObjective(tao->callbacks, func, ctx));
261: PetscFunctionReturn(PETSC_SUCCESS);
262: }
264: /*@C
265: TaoGetObjective - Gets the function evaluation routine for the function to be minimized
267: Not Collective
269: Input Parameter:
270: . tao - the `Tao` context
272: Output Parameters:
273: + func - the objective function
274: - ctx - the user-defined context for private data for the function evaluation
276: Calling sequence of `func`:
277: + tao - the optimizer
278: . x - input vector
279: . f - function value
280: - ctx - [optional] user-defined function context
282: Level: beginner
284: Notes:
285: In addition to specifying an objective function using callbacks such as
286: `TaoSetObjective()` and `TaoSetGradient()`, users can specify
287: objective functions with `TaoAddTerm()`.
289: `TaoGetObjective()` will always return the callback specified with
290: `TaoSetObjective()`, even if the objective function has been changed by
291: calling `TaoAddTerm()`.
293: .seealso: [](ch_tao), `Tao`, `TaoSetGradient()`, `TaoSetHessian()`, `TaoSetObjective()`
294: @*/
295: PetscErrorCode TaoGetObjective(Tao tao, PetscErrorCode (**func)(Tao tao, Vec x, PetscReal *f, PetscCtx ctx), PetscCtxRt ctx)
296: {
297: PetscFunctionBegin;
299: if (func || ctx) PetscCall(TaoTermCallbacksGetObjective(tao->callbacks, func, ctx));
300: PetscFunctionReturn(PETSC_SUCCESS);
301: }
303: /*@C
304: TaoSetResidualRoutine - Sets the residual evaluation routine for least-square applications
306: Logically Collective
308: Input Parameters:
309: + tao - the `Tao` context
310: . res - the residual vector
311: . func - the residual evaluation routine
312: - ctx - [optional] user-defined context for private data for the function evaluation
313: routine (may be `NULL`)
315: Calling sequence of `func`:
316: + tao - the optimizer
317: . x - input vector
318: . res - function value vector
319: - ctx - [optional] user-defined function context
321: Level: beginner
323: .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetJacobianRoutine()`
324: @*/
325: PetscErrorCode TaoSetResidualRoutine(Tao tao, Vec res, PetscErrorCode (*func)(Tao tao, Vec x, Vec res, PetscCtx ctx), PetscCtx ctx)
326: {
327: PetscFunctionBegin;
330: PetscCall(PetscObjectReference((PetscObject)res));
331: PetscCall(VecDestroy(&tao->ls_res));
332: tao->ls_res = res;
333: tao->user_lsresP = ctx;
334: tao->ops->computeresidual = func;
335: PetscFunctionReturn(PETSC_SUCCESS);
336: }
338: /*@
339: TaoSetResidualWeights - Give weights for the residual values. A vector can be used if only diagonal terms are used, otherwise a matrix can be give.
341: Collective
343: Input Parameters:
344: + tao - the `Tao` context
345: . sigma_v - vector of weights (diagonal terms only)
346: . n - the number of weights (if using off-diagonal)
347: . rows - index list of rows for `sigma_v`
348: . cols - index list of columns for `sigma_v`
349: - vals - array of weights
351: Level: intermediate
353: Notes:
354: If this function is not provided, or if `sigma_v` and `vals` are both `NULL`, then the
355: identity matrix will be used for weights.
357: Either `sigma_v` or `vals` should be `NULL`
359: .seealso: [](ch_tao), `Tao`, `TaoSetResidualRoutine()`
360: @*/
361: PetscErrorCode TaoSetResidualWeights(Tao tao, Vec sigma_v, PetscInt n, PetscInt *rows, PetscInt *cols, PetscReal *vals)
362: {
363: PetscInt i;
365: PetscFunctionBegin;
368: PetscCall(PetscObjectReference((PetscObject)sigma_v));
369: PetscCall(VecDestroy(&tao->res_weights_v));
370: tao->res_weights_v = sigma_v;
371: if (vals) {
372: PetscCall(PetscFree(tao->res_weights_rows));
373: PetscCall(PetscFree(tao->res_weights_cols));
374: PetscCall(PetscFree(tao->res_weights_w));
375: PetscCall(PetscMalloc1(n, &tao->res_weights_rows));
376: PetscCall(PetscMalloc1(n, &tao->res_weights_cols));
377: PetscCall(PetscMalloc1(n, &tao->res_weights_w));
378: tao->res_weights_n = n;
379: for (i = 0; i < n; i++) {
380: tao->res_weights_rows[i] = rows[i];
381: tao->res_weights_cols[i] = cols[i];
382: tao->res_weights_w[i] = vals[i];
383: }
384: } else {
385: tao->res_weights_n = 0;
386: tao->res_weights_rows = NULL;
387: tao->res_weights_cols = NULL;
388: }
389: PetscFunctionReturn(PETSC_SUCCESS);
390: }
392: /*@
393: TaoComputeResidual - Computes a least-squares residual vector at a given point
395: Collective
397: Input Parameters:
398: + tao - the `Tao` context
399: - X - input vector
401: Output Parameter:
402: . F - Objective vector at `X`
404: Level: advanced
406: Notes:
407: `TaoComputeResidual()` is typically used within the implementation of the optimization algorithm,
408: so most users would not generally call this routine themselves.
410: .seealso: [](ch_tao), `Tao`, `TaoSetResidualRoutine()`
411: @*/
412: PetscErrorCode TaoComputeResidual(Tao tao, Vec X, Vec F)
413: {
414: PetscFunctionBegin;
418: PetscCheckSameComm(tao, 1, X, 2);
419: PetscCheckSameComm(tao, 1, F, 3);
420: PetscCheck(tao->ops->computeresidual, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "TaoSetResidualRoutine() has not been called");
421: PetscCall(PetscLogEventBegin(TAO_ResidualEval, tao, X, NULL, NULL));
422: PetscCallBack("Tao callback least-squares residual", (*tao->ops->computeresidual)(tao, X, F, tao->user_lsresP));
423: PetscCall(PetscLogEventEnd(TAO_ResidualEval, tao, X, NULL, NULL));
424: tao->nres++;
425: PetscCall(PetscInfo(tao, "TAO least-squares residual evaluation.\n"));
426: PetscFunctionReturn(PETSC_SUCCESS);
427: }
429: /*@C
430: TaoSetGradient - Sets the gradient evaluation routine for the function to be optimized
432: Logically Collective
434: Input Parameters:
435: + tao - the `Tao` context
436: . g - [optional] the vector to internally hold the gradient computation
437: . func - the gradient function
438: - ctx - [optional] user-defined context for private data for the gradient evaluation
439: routine (may be `NULL`)
441: Calling sequence of `func`:
442: + tao - the optimization solver
443: . x - input vector
444: . g - gradient value (output)
445: - ctx - [optional] user-defined function context
447: Level: beginner
449: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoGetGradient()`
450: @*/
451: PetscErrorCode TaoSetGradient(Tao tao, Vec g, PetscErrorCode (*func)(Tao tao, Vec x, Vec g, PetscCtx ctx), PetscCtx ctx)
452: {
453: PetscFunctionBegin;
455: if (g) {
457: PetscCheckSameComm(tao, 1, g, 2);
458: PetscCall(PetscObjectReference((PetscObject)g));
459: PetscCall(VecDestroy(&tao->gradient));
460: tao->gradient = g;
461: }
462: PetscCall(TaoTermCallbacksSetGradient(tao->callbacks, func, ctx));
463: PetscFunctionReturn(PETSC_SUCCESS);
464: }
466: /*@C
467: TaoGetGradient - Gets the gradient evaluation routine for the function being optimized
469: Not Collective
471: Input Parameter:
472: . tao - the `Tao` context
474: Output Parameters:
475: + g - the vector to internally hold the gradient computation
476: . func - the gradient function
477: - ctx - user-defined context for private data for the gradient evaluation routine
479: Calling sequence of `func`:
480: + tao - the optimizer
481: . x - input vector
482: . g - gradient value (output)
483: - ctx - [optional] user-defined function context
485: Level: beginner
487: Notes:
488: In addition to specifying an objective function using callbacks such as
489: `TaoSetObjective()` and `TaoSetGradient()`, users can specify
490: objective functions with `TaoAddTerm()`.
492: `TaoGetGradient()` will always return the callback specified with
493: `TaoSetGradient()`, even if the objective function has been changed by
494: calling `TaoAddTerm()`.
496: .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetGradient()`
497: @*/
498: PetscErrorCode TaoGetGradient(Tao tao, Vec *g, PetscErrorCode (**func)(Tao tao, Vec x, Vec g, PetscCtx ctx), PetscCtxRt ctx)
499: {
500: PetscFunctionBegin;
502: if (g) *g = tao->gradient;
503: if (func || ctx) PetscCall(TaoTermCallbacksGetGradient(tao->callbacks, func, ctx));
504: PetscFunctionReturn(PETSC_SUCCESS);
505: }
507: /*@C
508: TaoSetObjectiveAndGradient - Sets a combined objective function and gradient evaluation routine for the function to be optimized
510: Logically Collective
512: Input Parameters:
513: + tao - the `Tao` context
514: . g - [optional] the vector to internally hold the gradient computation
515: . func - the gradient function
516: - ctx - [optional] user-defined context for private data for the gradient evaluation
517: routine (may be `NULL`)
519: Calling sequence of `func`:
520: + tao - the optimization object
521: . x - input vector
522: . f - objective value (output)
523: . g - gradient value (output)
524: - ctx - [optional] user-defined function context
526: Level: beginner
528: Note:
529: For some optimization methods using a combined function can be more efficient.
531: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetGradient()`, `TaoGetObjectiveAndGradient()`
532: @*/
533: PetscErrorCode TaoSetObjectiveAndGradient(Tao tao, Vec g, PetscErrorCode (*func)(Tao tao, Vec x, PetscReal *f, Vec g, PetscCtx ctx), PetscCtx ctx)
534: {
535: PetscFunctionBegin;
537: if (g) {
539: PetscCheckSameComm(tao, 1, g, 2);
540: PetscCall(PetscObjectReference((PetscObject)g));
541: PetscCall(VecDestroy(&tao->gradient));
542: tao->gradient = g;
543: }
544: PetscCall(TaoTermCallbacksSetObjectiveAndGradient(tao->callbacks, func, ctx));
545: PetscFunctionReturn(PETSC_SUCCESS);
546: }
548: /*@C
549: TaoGetObjectiveAndGradient - Gets the combined objective function and gradient evaluation routine for the function to be optimized
551: Not Collective
553: Input Parameter:
554: . tao - the `Tao` context
556: Output Parameters:
557: + g - the vector to internally hold the gradient computation
558: . func - the gradient function
559: - ctx - user-defined context for private data for the gradient evaluation routine
561: Calling sequence of `func`:
562: + tao - the optimizer
563: . x - input vector
564: . f - objective value (output)
565: . g - gradient value (output)
566: - ctx - [optional] user-defined function context
568: Level: beginner
570: Note:
571: In addition to specifying an objective function using callbacks such as
572: `TaoSetObjectiveAndGradient()`, users can specify
573: objective functions with `TaoAddTerm()`.
575: `TaoGetObjectiveAndGradient()` will always return the callback specified with
576: `TaoSetObjectiveAndGradient()`, even if the objective function has been changed by
577: calling `TaoAddTerm()`.
579: .seealso: [](ch_tao), `Tao`, `TaoSolve()`, `TaoSetObjective()`, `TaoSetGradient()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`
580: @*/
581: PetscErrorCode TaoGetObjectiveAndGradient(Tao tao, Vec *g, PetscErrorCode (**func)(Tao tao, Vec x, PetscReal *f, Vec g, PetscCtx ctx), PetscCtxRt ctx)
582: {
583: PetscFunctionBegin;
585: if (g) *g = tao->gradient;
586: if (func || ctx) PetscCall(TaoTermCallbacksGetObjectiveAndGradient(tao->callbacks, func, ctx));
587: PetscFunctionReturn(PETSC_SUCCESS);
588: }
590: /*@
591: TaoIsObjectiveDefined - Checks to see if the user has
592: declared an objective-only routine. Useful for determining when
593: it is appropriate to call `TaoComputeObjective()` or
594: `TaoComputeObjectiveAndGradient()`
596: Not Collective
598: Input Parameter:
599: . tao - the `Tao` context
601: Output Parameter:
602: . flg - `PETSC_TRUE` if the `Tao` has this routine `PETSC_FALSE` otherwise
604: Level: developer
606: Note:
607: If the objective of `Tao` has been altered via `TaoAddTerm()`, it will
608: return whether the summation of all terms has this routine.
610: .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoIsGradientDefined()`, `TaoIsObjectiveAndGradientDefined()`
611: @*/
612: PetscErrorCode TaoIsObjectiveDefined(Tao tao, PetscBool *flg)
613: {
614: PetscFunctionBegin;
616: PetscCall(TaoTermIsObjectiveDefined(tao->objective_term.term, flg));
617: PetscFunctionReturn(PETSC_SUCCESS);
618: }
620: /*@
621: TaoIsGradientDefined - Checks to see if the user has
622: declared a gradient-only routine. Useful for determining when
623: it is appropriate to call `TaoComputeGradient()` or
624: `TaoComputeObjectiveAndGradient()`
626: Not Collective
628: Input Parameter:
629: . tao - the `Tao` context
631: Output Parameter:
632: . flg - `PETSC_TRUE` if the objective `TaoTerm` has this routine, `PETSC_FALSE` otherwise
634: Level: developer
636: Note:
637: If the objective of `Tao` has been altered via `TaoAddTerm()`, it will
638: return whether the summation of all terms has this routine.
640: .seealso: [](ch_tao), `TaoSetGradient()`, `TaoIsObjectiveDefined()`, `TaoIsObjectiveAndGradientDefined()`
641: @*/
642: PetscErrorCode TaoIsGradientDefined(Tao tao, PetscBool *flg)
643: {
644: PetscFunctionBegin;
646: PetscCall(TaoTermIsGradientDefined(tao->objective_term.term, flg));
647: PetscFunctionReturn(PETSC_SUCCESS);
648: }
650: /*@
651: TaoIsObjectiveAndGradientDefined - Checks to see if the user has
652: declared a joint objective/gradient routine. Useful for determining when
653: it is appropriate to call `TaoComputeObjectiveAndGradient()`
655: Not Collective
657: Input Parameter:
658: . tao - the `Tao` context
660: Output Parameter:
661: . flg - `PETSC_TRUE` if the objective `TaoTerm` has this routine `PETSC_FALSE` otherwise
663: Level: developer
665: Note:
666: If the objective of `Tao` has been altered via `TaoAddTerm()`, it will
667: return whether the summation of all terms has this routine.
669: .seealso: [](ch_tao), `TaoSetObjectiveAndGradient()`, `TaoIsObjectiveDefined()`, `TaoIsGradientDefined()`
670: @*/
671: PetscErrorCode TaoIsObjectiveAndGradientDefined(Tao tao, PetscBool *flg)
672: {
673: PetscFunctionBegin;
675: PetscCall(TaoTermIsObjectiveAndGradientDefined(tao->objective_term.term, flg));
676: PetscFunctionReturn(PETSC_SUCCESS);
677: }