xref: /petsc/src/tao/interface/taosolver_fg.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
1af0996ceSBarry Smith #include <petsc/private/taoimpl.h> /*I "petsctao.h" I*/
2a7e14dcfSSatish Balay 
3a7e14dcfSSatish Balay /*@
4a82e8c82SStefano Zampini   TaoSetSolution - Sets the vector holding the initial guess for the solve
5a7e14dcfSSatish Balay 
665ba42b6SBarry Smith   Logically collective on tao
7a7e14dcfSSatish Balay 
8a7e14dcfSSatish Balay   Input Parameters:
9441846f8SBarry Smith + tao - the Tao context
10a7e14dcfSSatish Balay - x0  - the initial guess
11a7e14dcfSSatish Balay 
12a7e14dcfSSatish Balay   Level: beginner
1365ba42b6SBarry Smith .seealso: `Tao`, `TaoCreate()`, `TaoSolve()`, `TaoGetSolution()`
14a7e14dcfSSatish Balay @*/
15*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoSetSolution(Tao tao, Vec x0)
16*d71ae5a4SJacob Faibussowitsch {
17a7e14dcfSSatish Balay   PetscFunctionBegin;
18441846f8SBarry Smith   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
19a82e8c82SStefano Zampini   if (x0) PetscValidHeaderSpecific(x0, VEC_CLASSID, 2);
209566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)x0));
219566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tao->solution));
22a7e14dcfSSatish Balay   tao->solution = x0;
23a7e14dcfSSatish Balay   PetscFunctionReturn(0);
24a7e14dcfSSatish Balay }
25a7e14dcfSSatish Balay 
26*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoTestGradient(Tao tao, Vec x, Vec g1)
27*d71ae5a4SJacob Faibussowitsch {
28412cdd55SHong Zhang   Vec               g2, g3;
2909baa881SHong Zhang   PetscBool         complete_print = PETSC_FALSE, test = PETSC_FALSE;
3009baa881SHong Zhang   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
3109baa881SHong Zhang   PetscScalar       dot;
3209baa881SHong Zhang   MPI_Comm          comm;
33913eda9aSHong Zhang   PetscViewer       viewer, mviewer;
34913eda9aSHong Zhang   PetscViewerFormat format;
3509baa881SHong Zhang   PetscInt          tabs;
3609baa881SHong Zhang   static PetscBool  directionsprinted = PETSC_FALSE;
3709baa881SHong Zhang 
3809baa881SHong Zhang   PetscFunctionBegin;
39d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)tao);
409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-tao_test_gradient", "Compare hand-coded and finite difference Gradients", "None", &test));
419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsViewer("-tao_test_gradient_view", "View difference between hand-coded and finite difference Gradients element entries", "None", &mviewer, &format, &complete_print));
42d0609cedSBarry Smith   PetscOptionsEnd();
432f4b6201SAlp Dener   if (!test) {
4448a46eb9SPierre Jolivet     if (complete_print) PetscCall(PetscViewerDestroy(&mviewer));
452f4b6201SAlp Dener     PetscFunctionReturn(0);
462f4b6201SAlp Dener   }
4709baa881SHong Zhang 
489566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));
499566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
509566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
519566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
529566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Gradient -------------\n"));
5309baa881SHong Zhang   if (!complete_print && !directionsprinted) {
549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -tao_test_gradient_view and optionally -tao_test_gradient <threshold> to show difference\n"));
559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference gradient entries greater than <threshold>.\n"));
5609baa881SHong Zhang   }
5709baa881SHong Zhang   if (!directionsprinted) {
589566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Gradient, if (for double precision runs) ||G - Gfd||/||G|| is\n"));
599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Gradient is probably correct.\n"));
6009baa881SHong Zhang     directionsprinted = PETSC_TRUE;
6109baa881SHong Zhang   }
621baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
6309baa881SHong Zhang 
649566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &g2));
659566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &g3));
6609baa881SHong Zhang 
6709baa881SHong Zhang   /* Compute finite difference gradient, assume the gradient is already computed by TaoComputeGradient() and put into g1 */
689566063dSJacob Faibussowitsch   PetscCall(TaoDefaultComputeGradient(tao, x, g2, NULL));
6909baa881SHong Zhang 
709566063dSJacob Faibussowitsch   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
719566063dSJacob Faibussowitsch   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
729566063dSJacob Faibussowitsch   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
739566063dSJacob Faibussowitsch   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
749566063dSJacob Faibussowitsch   PetscCall(VecDot(g1, g2, &dot));
759566063dSJacob Faibussowitsch   PetscCall(VecCopy(g1, g3));
769566063dSJacob Faibussowitsch   PetscCall(VecAXPY(g3, -1.0, g2));
779566063dSJacob Faibussowitsch   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
789566063dSJacob Faibussowitsch   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
799566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ||Gfd|| %g, ||G|| = %g, angle cosine = (Gfd'G)/||Gfd||||G|| = %g\n", (double)fdnorm, (double)hcnorm, (double)(PetscRealPart(dot) / (fdnorm * hcnorm))));
809566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
819566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
8209baa881SHong Zhang 
8309baa881SHong Zhang   if (complete_print) {
849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded gradient ----------\n"));
859566063dSJacob Faibussowitsch     PetscCall(VecView(g1, mviewer));
869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference gradient ----------\n"));
879566063dSJacob Faibussowitsch     PetscCall(VecView(g2, mviewer));
889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference gradient ----------\n"));
899566063dSJacob Faibussowitsch     PetscCall(VecView(g3, mviewer));
9009baa881SHong Zhang   }
919566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&g2));
929566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&g3));
93913eda9aSHong Zhang 
94913eda9aSHong Zhang   if (complete_print) {
959566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(mviewer));
969566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&mviewer));
97913eda9aSHong Zhang   }
989566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
9909baa881SHong Zhang   PetscFunctionReturn(0);
10009baa881SHong Zhang }
10109baa881SHong Zhang 
102a7e14dcfSSatish Balay /*@
103a7e14dcfSSatish Balay   TaoComputeGradient - Computes the gradient of the objective function
104a7e14dcfSSatish Balay 
10565ba42b6SBarry Smith   Collective on tao
106a7e14dcfSSatish Balay 
107a7e14dcfSSatish Balay   Input Parameters:
108441846f8SBarry Smith + tao - the Tao context
109a7e14dcfSSatish Balay - X - input vector
110a7e14dcfSSatish Balay 
111a7e14dcfSSatish Balay   Output Parameter:
112a7e14dcfSSatish Balay . G - gradient vector
113a7e14dcfSSatish Balay 
11409baa881SHong Zhang   Options Database Keys:
11509baa881SHong Zhang +    -tao_test_gradient - compare the user provided gradient with one compute via finite differences to check for errors
116dfe02fe6SHong Zhang -    -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
11709baa881SHong Zhang 
11865ba42b6SBarry Smith   Note:
11965ba42b6SBarry Smith     `TaoComputeGradient()` is typically used within the implementation of the optimization method,
120a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
121a7e14dcfSSatish Balay 
12265ba42b6SBarry Smith   Level: developer
123a7e14dcfSSatish Balay 
124db781477SPatrick Sanan .seealso: `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetGradient()`
125a7e14dcfSSatish Balay @*/
126*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoComputeGradient(Tao tao, Vec X, Vec G)
127*d71ae5a4SJacob Faibussowitsch {
128a7e14dcfSSatish Balay   PetscReal dummy;
12987f595a5SBarry Smith 
130a7e14dcfSSatish Balay   PetscFunctionBegin;
131441846f8SBarry Smith   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
132a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
133064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(G, VEC_CLASSID, 3);
134a7e14dcfSSatish Balay   PetscCheckSameComm(tao, 1, X, 2);
135a7e14dcfSSatish Balay   PetscCheckSameComm(tao, 1, G, 3);
1369566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
137a7e14dcfSSatish Balay   if (tao->ops->computegradient) {
1389566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_GradientEval, tao, X, G, NULL));
139792fecdfSBarry Smith     PetscCallBack("Tao callback gradient", (*tao->ops->computegradient)(tao, X, G, tao->user_gradP));
1409566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_GradientEval, tao, X, G, NULL));
141a7e14dcfSSatish Balay     tao->ngrads++;
142a7e14dcfSSatish Balay   } else if (tao->ops->computeobjectiveandgradient) {
1439566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_ObjGradEval, tao, X, G, NULL));
144792fecdfSBarry Smith     PetscCallBack("Tao callback objective/gradient", (*tao->ops->computeobjectiveandgradient)(tao, X, &dummy, G, tao->user_objgradP));
1459566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_ObjGradEval, tao, X, G, NULL));
146a7e14dcfSSatish Balay     tao->nfuncgrads++;
147a82e8c82SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "TaoSetGradient() has not been called");
1489566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
14909baa881SHong Zhang 
1509566063dSJacob Faibussowitsch   PetscCall(TaoTestGradient(tao, X, G));
151a7e14dcfSSatish Balay   PetscFunctionReturn(0);
152a7e14dcfSSatish Balay }
153a7e14dcfSSatish Balay 
154a7e14dcfSSatish Balay /*@
155a7e14dcfSSatish Balay   TaoComputeObjective - Computes the objective function value at a given point
156a7e14dcfSSatish Balay 
15765ba42b6SBarry Smith   Collective on tao
158a7e14dcfSSatish Balay 
159a7e14dcfSSatish Balay   Input Parameters:
160441846f8SBarry Smith + tao - the Tao context
161a7e14dcfSSatish Balay - X - input vector
162a7e14dcfSSatish Balay 
163a7e14dcfSSatish Balay   Output Parameter:
164a7e14dcfSSatish Balay . f - Objective value at X
165a7e14dcfSSatish Balay 
16665ba42b6SBarry Smith   Note:
16765ba42b6SBarry Smith     `TaoComputeObjective()` is typically used within the implementation of the optimization algorithm
168a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
169a7e14dcfSSatish Balay 
17065ba42b6SBarry Smith   Level: developer
171a7e14dcfSSatish Balay 
17265ba42b6SBarry Smith .seealso: `Tao`, `TaoComputeGradient()`, `TaoComputeObjectiveAndGradient()`, `TaoSetObjective()`
173a7e14dcfSSatish Balay @*/
174*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoComputeObjective(Tao tao, Vec X, PetscReal *f)
175*d71ae5a4SJacob Faibussowitsch {
176a7e14dcfSSatish Balay   Vec temp;
17787f595a5SBarry Smith 
178a7e14dcfSSatish Balay   PetscFunctionBegin;
179441846f8SBarry Smith   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
180a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
181a7e14dcfSSatish Balay   PetscCheckSameComm(tao, 1, X, 2);
1829566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
183a7e14dcfSSatish Balay   if (tao->ops->computeobjective) {
1849566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_ObjectiveEval, tao, X, NULL, NULL));
185792fecdfSBarry Smith     PetscCallBack("Tao callback objective", (*tao->ops->computeobjective)(tao, X, f, tao->user_objP));
1869566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_ObjectiveEval, tao, X, NULL, NULL));
187a7e14dcfSSatish Balay     tao->nfuncs++;
188a7e14dcfSSatish Balay   } else if (tao->ops->computeobjectiveandgradient) {
1899566063dSJacob Faibussowitsch     PetscCall(PetscInfo(tao, "Duplicating variable vector in order to call func/grad routine\n"));
1909566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(X, &temp));
1919566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_ObjGradEval, tao, X, NULL, NULL));
192792fecdfSBarry Smith     PetscCallBack("Tao callback objective/gradient", (*tao->ops->computeobjectiveandgradient)(tao, X, f, temp, tao->user_objgradP));
1939566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_ObjGradEval, tao, X, NULL, NULL));
1949566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&temp));
195a7e14dcfSSatish Balay     tao->nfuncgrads++;
196a82e8c82SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "TaoSetObjective() has not been called");
1979566063dSJacob Faibussowitsch   PetscCall(PetscInfo(tao, "TAO Function evaluation: %20.19e\n", (double)(*f)));
1989566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
199a7e14dcfSSatish Balay   PetscFunctionReturn(0);
200a7e14dcfSSatish Balay }
201a7e14dcfSSatish Balay 
202a7e14dcfSSatish Balay /*@
203a7e14dcfSSatish Balay   TaoComputeObjectiveAndGradient - Computes the objective function value at a given point
204a7e14dcfSSatish Balay 
20565ba42b6SBarry Smith   Collective on tao
206a7e14dcfSSatish Balay 
207a7e14dcfSSatish Balay   Input Parameters:
208441846f8SBarry Smith + tao - the Tao context
209a7e14dcfSSatish Balay - X - input vector
210a7e14dcfSSatish Balay 
211d8d19677SJose E. Roman   Output Parameters:
212a7e14dcfSSatish Balay + f - Objective value at X
213a7e14dcfSSatish Balay - g - Gradient vector at X
214a7e14dcfSSatish Balay 
21565ba42b6SBarry Smith   Note:
21665ba42b6SBarry Smith     `TaoComputeObjectiveAndGradient()` is typically used within the implementation of the optimization algorithm,
217a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
218a7e14dcfSSatish Balay 
21965ba42b6SBarry Smith   Level: developer
220a7e14dcfSSatish Balay 
221db781477SPatrick Sanan .seealso: `TaoComputeGradient()`, `TaoComputeObjectiveAndGradient()`, `TaoSetObjective()`
222a7e14dcfSSatish Balay @*/
223*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoComputeObjectiveAndGradient(Tao tao, Vec X, PetscReal *f, Vec G)
224*d71ae5a4SJacob Faibussowitsch {
225a7e14dcfSSatish Balay   PetscFunctionBegin;
226441846f8SBarry Smith   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
227a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
228a7e14dcfSSatish Balay   PetscValidHeaderSpecific(G, VEC_CLASSID, 4);
229a7e14dcfSSatish Balay   PetscCheckSameComm(tao, 1, X, 2);
230a7e14dcfSSatish Balay   PetscCheckSameComm(tao, 1, G, 4);
2319566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
232a7e14dcfSSatish Balay   if (tao->ops->computeobjectiveandgradient) {
2339566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_ObjGradEval, tao, X, G, NULL));
234f4c1ad5cSStefano Zampini     if (tao->ops->computegradient == TaoDefaultComputeGradient) {
2359566063dSJacob Faibussowitsch       PetscCall(TaoComputeObjective(tao, X, f));
2369566063dSJacob Faibussowitsch       PetscCall(TaoDefaultComputeGradient(tao, X, G, NULL));
237f4c1ad5cSStefano Zampini     } else {
238792fecdfSBarry Smith       PetscCallBack("Tao callback objective/gradient", (*tao->ops->computeobjectiveandgradient)(tao, X, f, G, tao->user_objgradP));
239a7e14dcfSSatish Balay     }
2409566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_ObjGradEval, tao, X, G, NULL));
241a7e14dcfSSatish Balay     tao->nfuncgrads++;
242a7e14dcfSSatish Balay   } else if (tao->ops->computeobjective && tao->ops->computegradient) {
2439566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_ObjectiveEval, tao, X, NULL, NULL));
244792fecdfSBarry Smith     PetscCallBack("Tao callback objective", (*tao->ops->computeobjective)(tao, X, f, tao->user_objP));
2459566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_ObjectiveEval, tao, X, NULL, NULL));
246a7e14dcfSSatish Balay     tao->nfuncs++;
2479566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_GradientEval, tao, X, G, NULL));
248792fecdfSBarry Smith     PetscCallBack("Tao callback gradient", (*tao->ops->computegradient)(tao, X, G, tao->user_gradP));
2499566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_GradientEval, tao, X, G, NULL));
250a7e14dcfSSatish Balay     tao->ngrads++;
251a82e8c82SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "TaoSetObjective() or TaoSetGradient() not set");
2529566063dSJacob Faibussowitsch   PetscCall(PetscInfo(tao, "TAO Function evaluation: %20.19e\n", (double)(*f)));
2539566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
2541657496cSHong Zhang 
2559566063dSJacob Faibussowitsch   PetscCall(TaoTestGradient(tao, X, G));
256a7e14dcfSSatish Balay   PetscFunctionReturn(0);
257a7e14dcfSSatish Balay }
258a7e14dcfSSatish Balay 
259a7e14dcfSSatish Balay /*@C
260a82e8c82SStefano Zampini   TaoSetObjective - Sets the function evaluation routine for minimization
261a7e14dcfSSatish Balay 
26265ba42b6SBarry Smith   Logically collective on tao
263a7e14dcfSSatish Balay 
264d8d19677SJose E. Roman   Input Parameters:
265441846f8SBarry Smith + tao - the Tao context
266a7e14dcfSSatish Balay . func - the objective function
267a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the function evaluation
2686c23d075SBarry Smith         routine (may be NULL)
269a7e14dcfSSatish Balay 
270a7e14dcfSSatish Balay   Calling sequence of func:
271441846f8SBarry Smith $      func (Tao tao, Vec x, PetscReal *f, void *ctx);
272a7e14dcfSSatish Balay 
273a7e14dcfSSatish Balay + x - input vector
274a7e14dcfSSatish Balay . f - function value
275a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
276a7e14dcfSSatish Balay 
277a7e14dcfSSatish Balay   Level: beginner
278a7e14dcfSSatish Balay 
279db781477SPatrick Sanan .seealso: `TaoSetGradient()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoGetObjective()`
280a7e14dcfSSatish Balay @*/
281*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoSetObjective(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal *, void *), void *ctx)
282*d71ae5a4SJacob Faibussowitsch {
283a7e14dcfSSatish Balay   PetscFunctionBegin;
284441846f8SBarry Smith   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
285a82e8c82SStefano Zampini   if (ctx) tao->user_objP = ctx;
286a82e8c82SStefano Zampini   if (func) tao->ops->computeobjective = func;
287a82e8c82SStefano Zampini   PetscFunctionReturn(0);
288a82e8c82SStefano Zampini }
289a82e8c82SStefano Zampini 
290a82e8c82SStefano Zampini /*@C
29165ba42b6SBarry Smith   TaoGetObjective - Gets the function evaluation routine for the function to be minimized
292a82e8c82SStefano Zampini 
293a82e8c82SStefano Zampini   Not collective
294a82e8c82SStefano Zampini 
295a82e8c82SStefano Zampini   Input Parameter:
296a82e8c82SStefano Zampini . tao - the Tao context
297a82e8c82SStefano Zampini 
298a82e8c82SStefano Zampini   Output Parameters
299a82e8c82SStefano Zampini + func - the objective function
300a82e8c82SStefano Zampini - ctx - the user-defined context for private data for the function evaluation
301a82e8c82SStefano Zampini 
302a82e8c82SStefano Zampini   Calling sequence of func:
303a82e8c82SStefano Zampini $      func (Tao tao, Vec x, PetscReal *f, void *ctx);
304a82e8c82SStefano Zampini 
305a82e8c82SStefano Zampini + x - input vector
306a82e8c82SStefano Zampini . f - function value
307a82e8c82SStefano Zampini - ctx - [optional] user-defined function context
308a82e8c82SStefano Zampini 
309a82e8c82SStefano Zampini   Level: beginner
310a82e8c82SStefano Zampini 
31165ba42b6SBarry Smith .seealso: `Tao`, `TaoSetGradient()`, `TaoSetHessian()`, `TaoSetObjective()`
312a82e8c82SStefano Zampini @*/
313*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoGetObjective(Tao tao, PetscErrorCode (**func)(Tao, Vec, PetscReal *, void *), void **ctx)
314*d71ae5a4SJacob Faibussowitsch {
315a82e8c82SStefano Zampini   PetscFunctionBegin;
316a82e8c82SStefano Zampini   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
317a82e8c82SStefano Zampini   if (func) *func = tao->ops->computeobjective;
318a82e8c82SStefano Zampini   if (ctx) *ctx = tao->user_objP;
319a7e14dcfSSatish Balay   PetscFunctionReturn(0);
320a7e14dcfSSatish Balay }
321a7e14dcfSSatish Balay 
322a7e14dcfSSatish Balay /*@C
3234a48860cSAlp Dener   TaoSetResidualRoutine - Sets the residual evaluation routine for least-square applications
324a7e14dcfSSatish Balay 
32565ba42b6SBarry Smith   Logically collective on tao
326a7e14dcfSSatish Balay 
327d8d19677SJose E. Roman   Input Parameters:
328441846f8SBarry Smith + tao - the Tao context
3294a48860cSAlp Dener . func - the residual evaluation routine
330a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the function evaluation
3316c23d075SBarry Smith         routine (may be NULL)
332a7e14dcfSSatish Balay 
333a7e14dcfSSatish Balay   Calling sequence of func:
334441846f8SBarry Smith $      func (Tao tao, Vec x, Vec f, void *ctx);
335a7e14dcfSSatish Balay 
336a7e14dcfSSatish Balay + x - input vector
337a7e14dcfSSatish Balay . f - function value vector
338a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
339a7e14dcfSSatish Balay 
340a7e14dcfSSatish Balay   Level: beginner
341a7e14dcfSSatish Balay 
34265ba42b6SBarry Smith .seealso: `Tao`, `TaoSetObjective()`, `TaoSetJacobianRoutine()`
343a7e14dcfSSatish Balay @*/
344*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoSetResidualRoutine(Tao tao, Vec res, PetscErrorCode (*func)(Tao, Vec, Vec, void *), void *ctx)
345*d71ae5a4SJacob Faibussowitsch {
346a7e14dcfSSatish Balay   PetscFunctionBegin;
347441846f8SBarry Smith   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
3484a48860cSAlp Dener   PetscValidHeaderSpecific(res, VEC_CLASSID, 2);
3499566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)res));
35048a46eb9SPierre Jolivet   if (tao->ls_res) PetscCall(VecDestroy(&tao->ls_res));
3514a48860cSAlp Dener   tao->ls_res               = res;
3524ffbe8acSAlp Dener   tao->user_lsresP          = ctx;
3534a48860cSAlp Dener   tao->ops->computeresidual = func;
354737f463aSAlp Dener 
355737f463aSAlp Dener   PetscFunctionReturn(0);
356737f463aSAlp Dener }
357737f463aSAlp Dener 
358737f463aSAlp Dener /*@
35965ba42b6SBarry Smith   TaoSetResidualWeights - Give weights for the residual values. A vector can be used if only diagonal terms are used, otherwise a matrix can be give.
36065ba42b6SBarry Smith    If this function is not provided, or if sigma_v and sigma_w are both NULL, then the identity matrix will be used for weights.
361737f463aSAlp Dener 
36265ba42b6SBarry Smith   Collective on tao
363737f463aSAlp Dener 
364737f463aSAlp Dener   Input Parameters:
365737f463aSAlp Dener + tao - the Tao context
366737f463aSAlp Dener . sigma_v - vector of weights (diagonal terms only)
367737f463aSAlp Dener . n       - the number of weights (if using off-diagonal)
368737f463aSAlp Dener . rows    - index list of rows for sigma_w
369737f463aSAlp Dener . cols    - index list of columns for sigma_w
370737f463aSAlp Dener - vals - array of weights
371737f463aSAlp Dener 
372737f463aSAlp Dener   Note: Either sigma_v or sigma_w (or both) should be NULL
373737f463aSAlp Dener 
374737f463aSAlp Dener   Level: intermediate
375737f463aSAlp Dener 
37665ba42b6SBarry Smith .seealso: `Tao`, `TaoSetResidualRoutine()`
377737f463aSAlp Dener @*/
378*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoSetResidualWeights(Tao tao, Vec sigma_v, PetscInt n, PetscInt *rows, PetscInt *cols, PetscReal *vals)
379*d71ae5a4SJacob Faibussowitsch {
380737f463aSAlp Dener   PetscInt i;
381a82e8c82SStefano Zampini 
382737f463aSAlp Dener   PetscFunctionBegin;
383737f463aSAlp Dener   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
384a82e8c82SStefano Zampini   if (sigma_v) PetscValidHeaderSpecific(sigma_v, VEC_CLASSID, 2);
3859566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sigma_v));
3869566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tao->res_weights_v));
3874ffbe8acSAlp Dener   tao->res_weights_v = sigma_v;
388737f463aSAlp Dener   if (vals) {
3899566063dSJacob Faibussowitsch     PetscCall(PetscFree(tao->res_weights_rows));
3909566063dSJacob Faibussowitsch     PetscCall(PetscFree(tao->res_weights_cols));
3919566063dSJacob Faibussowitsch     PetscCall(PetscFree(tao->res_weights_w));
3929566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &tao->res_weights_rows));
3939566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &tao->res_weights_cols));
3949566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &tao->res_weights_w));
395737f463aSAlp Dener     tao->res_weights_n = n;
396737f463aSAlp Dener     for (i = 0; i < n; i++) {
397737f463aSAlp Dener       tao->res_weights_rows[i] = rows[i];
398737f463aSAlp Dener       tao->res_weights_cols[i] = cols[i];
399737f463aSAlp Dener       tao->res_weights_w[i]    = vals[i];
400737f463aSAlp Dener     }
401737f463aSAlp Dener   } else {
402737f463aSAlp Dener     tao->res_weights_n    = 0;
40383c8fe1dSLisandro Dalcin     tao->res_weights_rows = NULL;
40483c8fe1dSLisandro Dalcin     tao->res_weights_cols = NULL;
405737f463aSAlp Dener   }
406a7e14dcfSSatish Balay   PetscFunctionReturn(0);
407a7e14dcfSSatish Balay }
408a7e14dcfSSatish Balay 
4098b7a9b22SJason Sarich /*@
4104a48860cSAlp Dener   TaoComputeResidual - Computes a least-squares residual vector at a given point
411a7e14dcfSSatish Balay 
41265ba42b6SBarry Smith   Collective on tao
413a7e14dcfSSatish Balay 
414a7e14dcfSSatish Balay   Input Parameters:
415441846f8SBarry Smith + tao - the Tao context
416a7e14dcfSSatish Balay - X - input vector
417a7e14dcfSSatish Balay 
418a7e14dcfSSatish Balay   Output Parameter:
419a7e14dcfSSatish Balay . f - Objective vector at X
420a7e14dcfSSatish Balay 
42195452b02SPatrick Sanan   Notes:
42265ba42b6SBarry Smith     `TaoComputeResidual()` is typically used within the implementation of the optimization algorithm,
423a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
424a7e14dcfSSatish Balay 
425a7e14dcfSSatish Balay   Level: advanced
426a7e14dcfSSatish Balay 
42765ba42b6SBarry Smith .seealso: `Tao`, `TaoSetResidualRoutine()`
428a7e14dcfSSatish Balay @*/
429*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoComputeResidual(Tao tao, Vec X, Vec F)
430*d71ae5a4SJacob Faibussowitsch {
431a7e14dcfSSatish Balay   PetscFunctionBegin;
432441846f8SBarry Smith   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
433a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
434a7e14dcfSSatish Balay   PetscValidHeaderSpecific(F, VEC_CLASSID, 3);
435a7e14dcfSSatish Balay   PetscCheckSameComm(tao, 1, X, 2);
436a7e14dcfSSatish Balay   PetscCheckSameComm(tao, 1, F, 3);
4374a48860cSAlp Dener   if (tao->ops->computeresidual) {
4389566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_ObjectiveEval, tao, X, NULL, NULL));
439792fecdfSBarry Smith     PetscCallBack("Tao callback least-squares residual", (*tao->ops->computeresidual)(tao, X, F, tao->user_lsresP));
4409566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_ObjectiveEval, tao, X, NULL, NULL));
441a7e14dcfSSatish Balay     tao->nfuncs++;
442691b26d3SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "TaoSetResidualRoutine() has not been called");
4439566063dSJacob Faibussowitsch   PetscCall(PetscInfo(tao, "TAO least-squares residual evaluation.\n"));
444a7e14dcfSSatish Balay   PetscFunctionReturn(0);
445a7e14dcfSSatish Balay }
446a7e14dcfSSatish Balay 
447a7e14dcfSSatish Balay /*@C
44865ba42b6SBarry Smith   TaoSetGradient - Sets the gradient evaluation routine for the function to be optimized
449a7e14dcfSSatish Balay 
45065ba42b6SBarry Smith   Logically collective on tao
451a7e14dcfSSatish Balay 
452d8d19677SJose E. Roman   Input Parameters:
453441846f8SBarry Smith + tao - the Tao context
454a82e8c82SStefano Zampini . g - [optional] the vector to internally hold the gradient computation
455a7e14dcfSSatish Balay . func - the gradient function
456a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the gradient evaluation
4576c23d075SBarry Smith         routine (may be NULL)
458a7e14dcfSSatish Balay 
459a7e14dcfSSatish Balay   Calling sequence of func:
460441846f8SBarry Smith $      func (Tao tao, Vec x, Vec g, void *ctx);
461a7e14dcfSSatish Balay 
462a7e14dcfSSatish Balay + x - input vector
463a7e14dcfSSatish Balay . g - gradient value (output)
464a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
465a7e14dcfSSatish Balay 
466a7e14dcfSSatish Balay   Level: beginner
467a7e14dcfSSatish Balay 
46865ba42b6SBarry Smith .seealso: `Tao`, `TaoSolve()`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoGetGradient()`
469a7e14dcfSSatish Balay @*/
470*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoSetGradient(Tao tao, Vec g, PetscErrorCode (*func)(Tao, Vec, Vec, void *), void *ctx)
471*d71ae5a4SJacob Faibussowitsch {
472a7e14dcfSSatish Balay   PetscFunctionBegin;
473441846f8SBarry Smith   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
474a82e8c82SStefano Zampini   if (g) {
475a82e8c82SStefano Zampini     PetscValidHeaderSpecific(g, VEC_CLASSID, 2);
476a82e8c82SStefano Zampini     PetscCheckSameComm(tao, 1, g, 2);
4779566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)g));
4789566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&tao->gradient));
479a82e8c82SStefano Zampini     tao->gradient = g;
480a82e8c82SStefano Zampini   }
481a82e8c82SStefano Zampini   if (func) tao->ops->computegradient = func;
482a82e8c82SStefano Zampini   if (ctx) tao->user_gradP = ctx;
483a7e14dcfSSatish Balay   PetscFunctionReturn(0);
484a7e14dcfSSatish Balay }
485a7e14dcfSSatish Balay 
486a7e14dcfSSatish Balay /*@C
48765ba42b6SBarry Smith   TaoGetGradient - Gets the gradient evaluation routine for the function being optimized
488a82e8c82SStefano Zampini 
489a82e8c82SStefano Zampini   Not collective
490a82e8c82SStefano Zampini 
491a82e8c82SStefano Zampini   Input Parameter:
492a82e8c82SStefano Zampini . tao - the Tao context
493a82e8c82SStefano Zampini 
494a82e8c82SStefano Zampini   Output Parameters:
495a82e8c82SStefano Zampini + g - the vector to internally hold the gradient computation
496a82e8c82SStefano Zampini . func - the gradient function
497a82e8c82SStefano Zampini - ctx - user-defined context for private data for the gradient evaluation routine
498a82e8c82SStefano Zampini 
499a82e8c82SStefano Zampini   Calling sequence of func:
500a82e8c82SStefano Zampini $      func (Tao tao, Vec x, Vec g, void *ctx);
501a82e8c82SStefano Zampini 
502a82e8c82SStefano Zampini + x - input vector
503a82e8c82SStefano Zampini . g - gradient value (output)
504a82e8c82SStefano Zampini - ctx - [optional] user-defined function context
505a82e8c82SStefano Zampini 
506a82e8c82SStefano Zampini   Level: beginner
507a82e8c82SStefano Zampini 
50865ba42b6SBarry Smith .seealso: `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetGradient()`
509a82e8c82SStefano Zampini @*/
510*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoGetGradient(Tao tao, Vec *g, PetscErrorCode (**func)(Tao, Vec, Vec, void *), void **ctx)
511*d71ae5a4SJacob Faibussowitsch {
512a82e8c82SStefano Zampini   PetscFunctionBegin;
513a82e8c82SStefano Zampini   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
514a82e8c82SStefano Zampini   if (g) *g = tao->gradient;
515a82e8c82SStefano Zampini   if (func) *func = tao->ops->computegradient;
516a82e8c82SStefano Zampini   if (ctx) *ctx = tao->user_gradP;
517a82e8c82SStefano Zampini   PetscFunctionReturn(0);
518a82e8c82SStefano Zampini }
519a82e8c82SStefano Zampini 
520a82e8c82SStefano Zampini /*@C
52165ba42b6SBarry Smith   TaoSetObjectiveAndGradient - Sets a combined objective function and gradient evaluation routine for the function to be optimized
522a7e14dcfSSatish Balay 
52365ba42b6SBarry Smith   Logically collective on tao
524a7e14dcfSSatish Balay 
525d8d19677SJose E. Roman   Input Parameters:
526441846f8SBarry Smith + tao - the Tao context
527a82e8c82SStefano Zampini . g - [optional] the vector to internally hold the gradient computation
528a7e14dcfSSatish Balay . func - the gradient function
529a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the gradient evaluation
5306c23d075SBarry Smith         routine (may be NULL)
531a7e14dcfSSatish Balay 
532a7e14dcfSSatish Balay   Calling sequence of func:
53317477c02SJason Sarich $      func (Tao tao, Vec x, PetscReal *f, Vec g, void *ctx);
534a7e14dcfSSatish Balay 
535a7e14dcfSSatish Balay + x - input vector
53617477c02SJason Sarich . f - objective value (output)
537a7e14dcfSSatish Balay . g - gradient value (output)
538a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
539a7e14dcfSSatish Balay 
540a7e14dcfSSatish Balay   Level: beginner
541a7e14dcfSSatish Balay 
54265ba42b6SBarry Smith   Note:
54365ba42b6SBarry Smith   For some optimization methods using a combined function can be more eifficient.
54465ba42b6SBarry Smith 
54565ba42b6SBarry Smith .seealso: `Tao`, `TaoSolve()`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetGradient()`, `TaoGetObjectiveAndGradient()`
546a7e14dcfSSatish Balay @*/
547*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoSetObjectiveAndGradient(Tao tao, Vec g, PetscErrorCode (*func)(Tao, Vec, PetscReal *, Vec, void *), void *ctx)
548*d71ae5a4SJacob Faibussowitsch {
549a82e8c82SStefano Zampini   PetscFunctionBegin;
550a82e8c82SStefano Zampini   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
551a82e8c82SStefano Zampini   if (g) {
552a82e8c82SStefano Zampini     PetscValidHeaderSpecific(g, VEC_CLASSID, 2);
553a82e8c82SStefano Zampini     PetscCheckSameComm(tao, 1, g, 2);
5549566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)g));
5559566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&tao->gradient));
556a82e8c82SStefano Zampini     tao->gradient = g;
557a82e8c82SStefano Zampini   }
558a82e8c82SStefano Zampini   if (ctx) tao->user_objgradP = ctx;
559a82e8c82SStefano Zampini   if (func) tao->ops->computeobjectiveandgradient = func;
560a82e8c82SStefano Zampini   PetscFunctionReturn(0);
561a82e8c82SStefano Zampini }
562a82e8c82SStefano Zampini 
563a82e8c82SStefano Zampini /*@C
56465ba42b6SBarry Smith   TaoGetObjectiveAndGradient - Gets the combined objective function and gradient evaluation routine for the function to be optimized
565a82e8c82SStefano Zampini 
566a82e8c82SStefano Zampini   Not collective
567a82e8c82SStefano Zampini 
568a82e8c82SStefano Zampini   Input Parameter:
569a82e8c82SStefano Zampini . tao - the Tao context
570a82e8c82SStefano Zampini 
571a82e8c82SStefano Zampini   Output Parameters:
572817da375SSatish Balay + g - the vector to internally hold the gradient computation
573a82e8c82SStefano Zampini . func - the gradient function
574a82e8c82SStefano Zampini - ctx - user-defined context for private data for the gradient evaluation routine
575a82e8c82SStefano Zampini 
576a82e8c82SStefano Zampini   Calling sequence of func:
577a82e8c82SStefano Zampini $      func (Tao tao, Vec x, PetscReal *f, Vec g, void *ctx);
578a82e8c82SStefano Zampini 
579a82e8c82SStefano Zampini + x - input vector
580a82e8c82SStefano Zampini . f - objective value (output)
581a82e8c82SStefano Zampini . g - gradient value (output)
582a82e8c82SStefano Zampini - ctx - [optional] user-defined function context
583a82e8c82SStefano Zampini 
584a82e8c82SStefano Zampini   Level: beginner
585a82e8c82SStefano Zampini 
58665ba42b6SBarry Smith .seealso: `Tao`, `TaoSolve()`, `TaoSetObjective()`, `TaoSetGradient()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`
587a82e8c82SStefano Zampini @*/
588*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoGetObjectiveAndGradient(Tao tao, Vec *g, PetscErrorCode (**func)(Tao, Vec, PetscReal *, Vec, void *), void **ctx)
589*d71ae5a4SJacob Faibussowitsch {
590a7e14dcfSSatish Balay   PetscFunctionBegin;
591441846f8SBarry Smith   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
592a82e8c82SStefano Zampini   if (g) *g = tao->gradient;
593a82e8c82SStefano Zampini   if (func) *func = tao->ops->computeobjectiveandgradient;
594a82e8c82SStefano Zampini   if (ctx) *ctx = tao->user_objgradP;
595a7e14dcfSSatish Balay   PetscFunctionReturn(0);
596a7e14dcfSSatish Balay }
597a7e14dcfSSatish Balay 
598a7e14dcfSSatish Balay /*@
599a82e8c82SStefano Zampini   TaoIsObjectiveDefined - Checks to see if the user has
600a7e14dcfSSatish Balay   declared an objective-only routine.  Useful for determining when
60165ba42b6SBarry Smith   it is appropriate to call `TaoComputeObjective()` or
60265ba42b6SBarry Smith   `TaoComputeObjectiveAndGradient()`
603a7e14dcfSSatish Balay 
604a82e8c82SStefano Zampini   Not collective
605a7e14dcfSSatish Balay 
606a82e8c82SStefano Zampini   Input Parameter:
607a82e8c82SStefano Zampini . tao - the Tao context
608a82e8c82SStefano Zampini 
609a82e8c82SStefano Zampini   Output Parameter:
61065ba42b6SBarry Smith . flg - `PETSC_TRUE` if function routine is set by user, `PETSC_FALSE` otherwise
611a82e8c82SStefano Zampini 
612a7e14dcfSSatish Balay   Level: developer
613a7e14dcfSSatish Balay 
61465ba42b6SBarry Smith .seealso: `Tao`, `TaoSetObjective()`, `TaoIsGradientDefined()`, `TaoIsObjectiveAndGradientDefined()`
615a7e14dcfSSatish Balay @*/
616*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoIsObjectiveDefined(Tao tao, PetscBool *flg)
617*d71ae5a4SJacob Faibussowitsch {
618a7e14dcfSSatish Balay   PetscFunctionBegin;
619441846f8SBarry Smith   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
62083c8fe1dSLisandro Dalcin   if (tao->ops->computeobjective == NULL) *flg = PETSC_FALSE;
62145cf516eSBarry Smith   else *flg = PETSC_TRUE;
622a7e14dcfSSatish Balay   PetscFunctionReturn(0);
623a7e14dcfSSatish Balay }
624a7e14dcfSSatish Balay 
625a7e14dcfSSatish Balay /*@
626a82e8c82SStefano Zampini   TaoIsGradientDefined - Checks to see if the user has
627a7e14dcfSSatish Balay   declared an objective-only routine.  Useful for determining when
62865ba42b6SBarry Smith   it is appropriate to call `TaoComputeGradient()` or
62965ba42b6SBarry Smith   `TaoComputeGradientAndGradient()`
630a7e14dcfSSatish Balay 
631a7e14dcfSSatish Balay   Not Collective
632a7e14dcfSSatish Balay 
633a82e8c82SStefano Zampini   Input Parameter:
634a82e8c82SStefano Zampini . tao - the Tao context
635a82e8c82SStefano Zampini 
636a82e8c82SStefano Zampini   Output Parameter:
63765ba42b6SBarry Smith . flg - `PETSC_TRUE` if function routine is set by user, `PETSC_FALSE` otherwise
638a82e8c82SStefano Zampini 
639a7e14dcfSSatish Balay   Level: developer
640a7e14dcfSSatish Balay 
641db781477SPatrick Sanan .seealso: `TaoSetGradient()`, `TaoIsObjectiveDefined()`, `TaoIsObjectiveAndGradientDefined()`
642a7e14dcfSSatish Balay @*/
643*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoIsGradientDefined(Tao tao, PetscBool *flg)
644*d71ae5a4SJacob Faibussowitsch {
645a7e14dcfSSatish Balay   PetscFunctionBegin;
646441846f8SBarry Smith   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
64783c8fe1dSLisandro Dalcin   if (tao->ops->computegradient == NULL) *flg = PETSC_FALSE;
64845cf516eSBarry Smith   else *flg = PETSC_TRUE;
649a7e14dcfSSatish Balay   PetscFunctionReturn(0);
650a7e14dcfSSatish Balay }
651a7e14dcfSSatish Balay 
652a7e14dcfSSatish Balay /*@
653a82e8c82SStefano Zampini   TaoIsObjectiveAndGradientDefined - Checks to see if the user has
654a7e14dcfSSatish Balay   declared a joint objective/gradient routine.  Useful for determining when
65565ba42b6SBarry Smith   it is appropriate to call `TaoComputeObjective()` or
65665ba42b6SBarry Smith   `TaoComputeObjectiveAndGradient()`
657a7e14dcfSSatish Balay 
658a7e14dcfSSatish Balay   Not Collective
659a7e14dcfSSatish Balay 
660a82e8c82SStefano Zampini   Input Parameter:
661a82e8c82SStefano Zampini . tao - the Tao context
662a82e8c82SStefano Zampini 
663a82e8c82SStefano Zampini   Output Parameter:
66465ba42b6SBarry Smith . flg - `PETSC_TRUE` if function routine is set by user, `PETSC_FALSE` otherwise
665a82e8c82SStefano Zampini 
666a7e14dcfSSatish Balay   Level: developer
667a7e14dcfSSatish Balay 
668db781477SPatrick Sanan .seealso: `TaoSetObjectiveAndGradient()`, `TaoIsObjectiveDefined()`, `TaoIsGradientDefined()`
669a7e14dcfSSatish Balay @*/
670*d71ae5a4SJacob Faibussowitsch PetscErrorCode TaoIsObjectiveAndGradientDefined(Tao tao, PetscBool *flg)
671*d71ae5a4SJacob Faibussowitsch {
672a7e14dcfSSatish Balay   PetscFunctionBegin;
673441846f8SBarry Smith   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
67483c8fe1dSLisandro Dalcin   if (tao->ops->computeobjectiveandgradient == NULL) *flg = PETSC_FALSE;
67545cf516eSBarry Smith   else *flg = PETSC_TRUE;
676a7e14dcfSSatish Balay   PetscFunctionReturn(0);
677a7e14dcfSSatish Balay }
678