xref: /petsc/src/tao/interface/taosolver_fg.c (revision 792fecdfe9134cce4d631112660ddd34f063bc17)
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 @*/
15a82e8c82SStefano Zampini PetscErrorCode TaoSetSolution(Tao tao, Vec x0)
1645cf516eSBarry Smith {
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 
26412cdd55SHong Zhang PetscErrorCode TaoTestGradient(Tao tao,Vec x,Vec g1)
2709baa881SHong Zhang {
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) {
442f4b6201SAlp Dener     if (complete_print) {
459566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&mviewer));
462f4b6201SAlp Dener     }
472f4b6201SAlp Dener     PetscFunctionReturn(0);
482f4b6201SAlp Dener   }
4909baa881SHong Zhang 
509566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)tao,&comm));
519566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm,&viewer));
529566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
539566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
549566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer,"  ---------- Testing Gradient -------------\n"));
5509baa881SHong Zhang   if (!complete_print && !directionsprinted) {
569566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Run with -tao_test_gradient_view and optionally -tao_test_gradient <threshold> to show difference\n"));
579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    of hand-coded and finite difference gradient entries greater than <threshold>.\n"));
5809baa881SHong Zhang   }
5909baa881SHong Zhang   if (!directionsprinted) {
609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Testing hand-coded Gradient, if (for double precision runs) ||G - Gfd||/||G|| is\n"));
619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"    O(1.e-8), the hand-coded Gradient is probably correct.\n"));
6209baa881SHong Zhang     directionsprinted = PETSC_TRUE;
6309baa881SHong Zhang   }
641baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer,format));
6509baa881SHong Zhang 
669566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x,&g2));
679566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x,&g3));
6809baa881SHong Zhang 
6909baa881SHong Zhang   /* Compute finite difference gradient, assume the gradient is already computed by TaoComputeGradient() and put into g1 */
709566063dSJacob Faibussowitsch   PetscCall(TaoDefaultComputeGradient(tao,x,g2,NULL));
7109baa881SHong Zhang 
729566063dSJacob Faibussowitsch   PetscCall(VecNorm(g2,NORM_2,&fdnorm));
739566063dSJacob Faibussowitsch   PetscCall(VecNorm(g1,NORM_2,&hcnorm));
749566063dSJacob Faibussowitsch   PetscCall(VecNorm(g2,NORM_INFINITY,&fdmax));
759566063dSJacob Faibussowitsch   PetscCall(VecNorm(g1,NORM_INFINITY,&hcmax));
769566063dSJacob Faibussowitsch   PetscCall(VecDot(g1,g2,&dot));
779566063dSJacob Faibussowitsch   PetscCall(VecCopy(g1,g3));
789566063dSJacob Faibussowitsch   PetscCall(VecAXPY(g3,-1.0,g2));
799566063dSJacob Faibussowitsch   PetscCall(VecNorm(g3,NORM_2,&diffnorm));
809566063dSJacob Faibussowitsch   PetscCall(VecNorm(g3,NORM_INFINITY,&diffmax));
819566063dSJacob 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))));
829566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer,"  2-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n",(double)(diffnorm/PetscMax(hcnorm,fdnorm)),(double)diffnorm));
839566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer,"  max-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n",(double)(diffmax/PetscMax(hcmax,fdmax)),(double)diffmax));
8409baa881SHong Zhang 
8509baa881SHong Zhang   if (complete_print) {
869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Hand-coded gradient ----------\n"));
879566063dSJacob Faibussowitsch     PetscCall(VecView(g1,mviewer));
889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Finite difference gradient ----------\n"));
899566063dSJacob Faibussowitsch     PetscCall(VecView(g2,mviewer));
909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Hand-coded minus finite-difference gradient ----------\n"));
919566063dSJacob Faibussowitsch     PetscCall(VecView(g3,mviewer));
9209baa881SHong Zhang   }
939566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&g2));
949566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&g3));
95913eda9aSHong Zhang 
96913eda9aSHong Zhang   if (complete_print) {
979566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(mviewer));
989566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&mviewer));
99913eda9aSHong Zhang   }
1009566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer,tabs));
10109baa881SHong Zhang   PetscFunctionReturn(0);
10209baa881SHong Zhang }
10309baa881SHong Zhang 
104a7e14dcfSSatish Balay /*@
105a7e14dcfSSatish Balay   TaoComputeGradient - Computes the gradient of the objective function
106a7e14dcfSSatish Balay 
10765ba42b6SBarry Smith   Collective on tao
108a7e14dcfSSatish Balay 
109a7e14dcfSSatish Balay   Input Parameters:
110441846f8SBarry Smith + tao - the Tao context
111a7e14dcfSSatish Balay - X - input vector
112a7e14dcfSSatish Balay 
113a7e14dcfSSatish Balay   Output Parameter:
114a7e14dcfSSatish Balay . G - gradient vector
115a7e14dcfSSatish Balay 
11609baa881SHong Zhang   Options Database Keys:
11709baa881SHong Zhang +    -tao_test_gradient - compare the user provided gradient with one compute via finite differences to check for errors
118dfe02fe6SHong 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
11909baa881SHong Zhang 
12065ba42b6SBarry Smith   Note:
12165ba42b6SBarry Smith     `TaoComputeGradient()` is typically used within the implementation of the optimization method,
122a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
123a7e14dcfSSatish Balay 
12465ba42b6SBarry Smith   Level: developer
125a7e14dcfSSatish Balay 
126db781477SPatrick Sanan .seealso: `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetGradient()`
127a7e14dcfSSatish Balay @*/
128441846f8SBarry Smith PetscErrorCode TaoComputeGradient(Tao tao, Vec X, Vec G)
129a7e14dcfSSatish Balay {
130a7e14dcfSSatish Balay   PetscReal      dummy;
13187f595a5SBarry Smith 
132a7e14dcfSSatish Balay   PetscFunctionBegin;
133441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
134a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
135064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(G,VEC_CLASSID,3);
136a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,X,2);
137a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,G,3);
1389566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
139a7e14dcfSSatish Balay   if (tao->ops->computegradient) {
1409566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_GradientEval,tao,X,G,NULL));
141*792fecdfSBarry Smith     PetscCallBack("Tao callback gradient",(*tao->ops->computegradient)(tao,X,G,tao->user_gradP));
1429566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_GradientEval,tao,X,G,NULL));
143a7e14dcfSSatish Balay     tao->ngrads++;
144a7e14dcfSSatish Balay   } else if (tao->ops->computeobjectiveandgradient) {
1459566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_ObjGradEval,tao,X,G,NULL));
146*792fecdfSBarry Smith     PetscCallBack("Tao callback objective/gradient",(*tao->ops->computeobjectiveandgradient)(tao,X,&dummy,G,tao->user_objgradP));
1479566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_ObjGradEval,tao,X,G,NULL));
148a7e14dcfSSatish Balay     tao->nfuncgrads++;
149a82e8c82SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"TaoSetGradient() has not been called");
1509566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
15109baa881SHong Zhang 
1529566063dSJacob Faibussowitsch   PetscCall(TaoTestGradient(tao,X,G));
153a7e14dcfSSatish Balay   PetscFunctionReturn(0);
154a7e14dcfSSatish Balay }
155a7e14dcfSSatish Balay 
156a7e14dcfSSatish Balay /*@
157a7e14dcfSSatish Balay   TaoComputeObjective - Computes the objective function value at a given point
158a7e14dcfSSatish Balay 
15965ba42b6SBarry Smith   Collective on tao
160a7e14dcfSSatish Balay 
161a7e14dcfSSatish Balay   Input Parameters:
162441846f8SBarry Smith + tao - the Tao context
163a7e14dcfSSatish Balay - X - input vector
164a7e14dcfSSatish Balay 
165a7e14dcfSSatish Balay   Output Parameter:
166a7e14dcfSSatish Balay . f - Objective value at X
167a7e14dcfSSatish Balay 
16865ba42b6SBarry Smith   Note:
16965ba42b6SBarry Smith     `TaoComputeObjective()` is typically used within the implementation of the optimization algorithm
170a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
171a7e14dcfSSatish Balay 
17265ba42b6SBarry Smith   Level: developer
173a7e14dcfSSatish Balay 
17465ba42b6SBarry Smith .seealso: `Tao`, `TaoComputeGradient()`, `TaoComputeObjectiveAndGradient()`, `TaoSetObjective()`
175a7e14dcfSSatish Balay @*/
176441846f8SBarry Smith PetscErrorCode TaoComputeObjective(Tao tao, Vec X, PetscReal *f)
177a7e14dcfSSatish Balay {
178a7e14dcfSSatish Balay   Vec            temp;
17987f595a5SBarry Smith 
180a7e14dcfSSatish Balay   PetscFunctionBegin;
181441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
182a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
183a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,X,2);
1849566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
185a7e14dcfSSatish Balay   if (tao->ops->computeobjective) {
1869566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_ObjectiveEval,tao,X,NULL,NULL));
187*792fecdfSBarry Smith     PetscCallBack("Tao callback objective",(*tao->ops->computeobjective)(tao,X,f,tao->user_objP));
1889566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_ObjectiveEval,tao,X,NULL,NULL));
189a7e14dcfSSatish Balay     tao->nfuncs++;
190a7e14dcfSSatish Balay   } else if (tao->ops->computeobjectiveandgradient) {
1919566063dSJacob Faibussowitsch     PetscCall(PetscInfo(tao,"Duplicating variable vector in order to call func/grad routine\n"));
1929566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(X,&temp));
1939566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_ObjGradEval,tao,X,NULL,NULL));
194*792fecdfSBarry Smith     PetscCallBack("Tao callback objective/gradient",(*tao->ops->computeobjectiveandgradient)(tao,X,f,temp,tao->user_objgradP));
1959566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_ObjGradEval,tao,X,NULL,NULL));
1969566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&temp));
197a7e14dcfSSatish Balay     tao->nfuncgrads++;
198a82e8c82SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjective() has not been called");
1999566063dSJacob Faibussowitsch   PetscCall(PetscInfo(tao,"TAO Function evaluation: %20.19e\n",(double)(*f)));
2009566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
201a7e14dcfSSatish Balay   PetscFunctionReturn(0);
202a7e14dcfSSatish Balay }
203a7e14dcfSSatish Balay 
204a7e14dcfSSatish Balay /*@
205a7e14dcfSSatish Balay   TaoComputeObjectiveAndGradient - Computes the objective function value at a given point
206a7e14dcfSSatish Balay 
20765ba42b6SBarry Smith   Collective on tao
208a7e14dcfSSatish Balay 
209a7e14dcfSSatish Balay   Input Parameters:
210441846f8SBarry Smith + tao - the Tao context
211a7e14dcfSSatish Balay - X - input vector
212a7e14dcfSSatish Balay 
213d8d19677SJose E. Roman   Output Parameters:
214a7e14dcfSSatish Balay + f - Objective value at X
215a7e14dcfSSatish Balay - g - Gradient vector at X
216a7e14dcfSSatish Balay 
21765ba42b6SBarry Smith   Note:
21865ba42b6SBarry Smith     `TaoComputeObjectiveAndGradient()` is typically used within the implementation of the optimization algorithm,
219a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
220a7e14dcfSSatish Balay 
22165ba42b6SBarry Smith   Level: developer
222a7e14dcfSSatish Balay 
223db781477SPatrick Sanan .seealso: `TaoComputeGradient()`, `TaoComputeObjectiveAndGradient()`, `TaoSetObjective()`
224a7e14dcfSSatish Balay @*/
225441846f8SBarry Smith PetscErrorCode TaoComputeObjectiveAndGradient(Tao tao, Vec X, PetscReal *f, Vec G)
226a7e14dcfSSatish Balay {
227a7e14dcfSSatish Balay   PetscFunctionBegin;
228441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
229a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
230a7e14dcfSSatish Balay   PetscValidHeaderSpecific(G,VEC_CLASSID,4);
231a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,X,2);
232a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,G,4);
2339566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
234a7e14dcfSSatish Balay   if (tao->ops->computeobjectiveandgradient) {
2359566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_ObjGradEval,tao,X,G,NULL));
236f4c1ad5cSStefano Zampini     if (tao->ops->computegradient == TaoDefaultComputeGradient) {
2379566063dSJacob Faibussowitsch       PetscCall(TaoComputeObjective(tao,X,f));
2389566063dSJacob Faibussowitsch       PetscCall(TaoDefaultComputeGradient(tao,X,G,NULL));
239f4c1ad5cSStefano Zampini     } else {
240*792fecdfSBarry Smith       PetscCallBack("Tao callback objective/gradient",(*tao->ops->computeobjectiveandgradient)(tao,X,f,G,tao->user_objgradP));
241a7e14dcfSSatish Balay     }
2429566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_ObjGradEval,tao,X,G,NULL));
243a7e14dcfSSatish Balay     tao->nfuncgrads++;
244a7e14dcfSSatish Balay   } else if (tao->ops->computeobjective && tao->ops->computegradient) {
2459566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_ObjectiveEval,tao,X,NULL,NULL));
246*792fecdfSBarry Smith     PetscCallBack("Tao callback objective",(*tao->ops->computeobjective)(tao,X,f,tao->user_objP));
2479566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_ObjectiveEval,tao,X,NULL,NULL));
248a7e14dcfSSatish Balay     tao->nfuncs++;
2499566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_GradientEval,tao,X,G,NULL));
250*792fecdfSBarry Smith     PetscCallBack("Tao callback gradient",(*tao->ops->computegradient)(tao,X,G,tao->user_gradP));
2519566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_GradientEval,tao,X,G,NULL));
252a7e14dcfSSatish Balay     tao->ngrads++;
253a82e8c82SStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjective() or TaoSetGradient() not set");
2549566063dSJacob Faibussowitsch   PetscCall(PetscInfo(tao,"TAO Function evaluation: %20.19e\n",(double)(*f)));
2559566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
2561657496cSHong Zhang 
2579566063dSJacob Faibussowitsch   PetscCall(TaoTestGradient(tao,X,G));
258a7e14dcfSSatish Balay   PetscFunctionReturn(0);
259a7e14dcfSSatish Balay }
260a7e14dcfSSatish Balay 
261a7e14dcfSSatish Balay /*@C
262a82e8c82SStefano Zampini   TaoSetObjective - Sets the function evaluation routine for minimization
263a7e14dcfSSatish Balay 
26465ba42b6SBarry Smith   Logically collective on tao
265a7e14dcfSSatish Balay 
266d8d19677SJose E. Roman   Input Parameters:
267441846f8SBarry Smith + tao - the Tao context
268a7e14dcfSSatish Balay . func - the objective function
269a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the function evaluation
2706c23d075SBarry Smith         routine (may be NULL)
271a7e14dcfSSatish Balay 
272a7e14dcfSSatish Balay   Calling sequence of func:
273441846f8SBarry Smith $      func (Tao tao, Vec x, PetscReal *f, void *ctx);
274a7e14dcfSSatish Balay 
275a7e14dcfSSatish Balay + x - input vector
276a7e14dcfSSatish Balay . f - function value
277a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
278a7e14dcfSSatish Balay 
279a7e14dcfSSatish Balay   Level: beginner
280a7e14dcfSSatish Balay 
281db781477SPatrick Sanan .seealso: `TaoSetGradient()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoGetObjective()`
282a7e14dcfSSatish Balay @*/
283a82e8c82SStefano Zampini PetscErrorCode TaoSetObjective(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal*,void*),void *ctx)
284a7e14dcfSSatish Balay {
285a7e14dcfSSatish Balay   PetscFunctionBegin;
286441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
287a82e8c82SStefano Zampini   if (ctx) tao->user_objP = ctx;
288a82e8c82SStefano Zampini   if (func) tao->ops->computeobjective = func;
289a82e8c82SStefano Zampini   PetscFunctionReturn(0);
290a82e8c82SStefano Zampini }
291a82e8c82SStefano Zampini 
292a82e8c82SStefano Zampini /*@C
29365ba42b6SBarry Smith   TaoGetObjective - Gets the function evaluation routine for the function to be minimized
294a82e8c82SStefano Zampini 
295a82e8c82SStefano Zampini   Not collective
296a82e8c82SStefano Zampini 
297a82e8c82SStefano Zampini   Input Parameter:
298a82e8c82SStefano Zampini . tao - the Tao context
299a82e8c82SStefano Zampini 
300a82e8c82SStefano Zampini   Output Parameters
301a82e8c82SStefano Zampini + func - the objective function
302a82e8c82SStefano Zampini - ctx - the user-defined context for private data for the function evaluation
303a82e8c82SStefano Zampini 
304a82e8c82SStefano Zampini   Calling sequence of func:
305a82e8c82SStefano Zampini $      func (Tao tao, Vec x, PetscReal *f, void *ctx);
306a82e8c82SStefano Zampini 
307a82e8c82SStefano Zampini + x - input vector
308a82e8c82SStefano Zampini . f - function value
309a82e8c82SStefano Zampini - ctx - [optional] user-defined function context
310a82e8c82SStefano Zampini 
311a82e8c82SStefano Zampini   Level: beginner
312a82e8c82SStefano Zampini 
31365ba42b6SBarry Smith .seealso: `Tao`, `TaoSetGradient()`, `TaoSetHessian()`, `TaoSetObjective()`
314a82e8c82SStefano Zampini @*/
315a82e8c82SStefano Zampini PetscErrorCode TaoGetObjective(Tao tao, PetscErrorCode (**func)(Tao, Vec, PetscReal*,void*),void **ctx)
316a82e8c82SStefano Zampini {
317a82e8c82SStefano Zampini   PetscFunctionBegin;
318a82e8c82SStefano Zampini   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
319a82e8c82SStefano Zampini   if (func) *func = tao->ops->computeobjective;
320a82e8c82SStefano Zampini   if (ctx) *ctx = tao->user_objP;
321a7e14dcfSSatish Balay   PetscFunctionReturn(0);
322a7e14dcfSSatish Balay }
323a7e14dcfSSatish Balay 
324a7e14dcfSSatish Balay /*@C
3254a48860cSAlp Dener   TaoSetResidualRoutine - Sets the residual evaluation routine for least-square applications
326a7e14dcfSSatish Balay 
32765ba42b6SBarry Smith   Logically collective on tao
328a7e14dcfSSatish Balay 
329d8d19677SJose E. Roman   Input Parameters:
330441846f8SBarry Smith + tao - the Tao context
3314a48860cSAlp Dener . func - the residual evaluation routine
332a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the function evaluation
3336c23d075SBarry Smith         routine (may be NULL)
334a7e14dcfSSatish Balay 
335a7e14dcfSSatish Balay   Calling sequence of func:
336441846f8SBarry Smith $      func (Tao tao, Vec x, Vec f, void *ctx);
337a7e14dcfSSatish Balay 
338a7e14dcfSSatish Balay + x - input vector
339a7e14dcfSSatish Balay . f - function value vector
340a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
341a7e14dcfSSatish Balay 
342a7e14dcfSSatish Balay   Level: beginner
343a7e14dcfSSatish Balay 
34465ba42b6SBarry Smith .seealso: `Tao`, `TaoSetObjective()`, `TaoSetJacobianRoutine()`
345a7e14dcfSSatish Balay @*/
3464a48860cSAlp Dener PetscErrorCode TaoSetResidualRoutine(Tao tao, Vec res, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx)
347a7e14dcfSSatish Balay {
348a7e14dcfSSatish Balay   PetscFunctionBegin;
349441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
3504a48860cSAlp Dener   PetscValidHeaderSpecific(res,VEC_CLASSID,2);
3519566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)res));
352737f463aSAlp Dener   if (tao->ls_res) {
3539566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&tao->ls_res));
354737f463aSAlp Dener   }
3554a48860cSAlp Dener   tao->ls_res = res;
3564ffbe8acSAlp Dener   tao->user_lsresP = ctx;
3574a48860cSAlp Dener   tao->ops->computeresidual = func;
358737f463aSAlp Dener 
359737f463aSAlp Dener   PetscFunctionReturn(0);
360737f463aSAlp Dener }
361737f463aSAlp Dener 
362737f463aSAlp Dener /*@
36365ba42b6SBarry 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.
36465ba42b6SBarry 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.
365737f463aSAlp Dener 
36665ba42b6SBarry Smith   Collective on tao
367737f463aSAlp Dener 
368737f463aSAlp Dener   Input Parameters:
369737f463aSAlp Dener + tao - the Tao context
370737f463aSAlp Dener . sigma_v - vector of weights (diagonal terms only)
371737f463aSAlp Dener . n       - the number of weights (if using off-diagonal)
372737f463aSAlp Dener . rows    - index list of rows for sigma_w
373737f463aSAlp Dener . cols    - index list of columns for sigma_w
374737f463aSAlp Dener - vals - array of weights
375737f463aSAlp Dener 
376737f463aSAlp Dener   Note: Either sigma_v or sigma_w (or both) should be NULL
377737f463aSAlp Dener 
378737f463aSAlp Dener   Level: intermediate
379737f463aSAlp Dener 
38065ba42b6SBarry Smith .seealso: `Tao`, `TaoSetResidualRoutine()`
381737f463aSAlp Dener @*/
382737f463aSAlp Dener PetscErrorCode TaoSetResidualWeights(Tao tao, Vec sigma_v, PetscInt n, PetscInt *rows, PetscInt *cols, PetscReal *vals)
383737f463aSAlp Dener {
384737f463aSAlp Dener   PetscInt       i;
385a82e8c82SStefano Zampini 
386737f463aSAlp Dener   PetscFunctionBegin;
387737f463aSAlp Dener   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
388a82e8c82SStefano Zampini   if (sigma_v) PetscValidHeaderSpecific(sigma_v,VEC_CLASSID,2);
3899566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sigma_v));
3909566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&tao->res_weights_v));
3914ffbe8acSAlp Dener   tao->res_weights_v = sigma_v;
392737f463aSAlp Dener   if (vals) {
3939566063dSJacob Faibussowitsch     PetscCall(PetscFree(tao->res_weights_rows));
3949566063dSJacob Faibussowitsch     PetscCall(PetscFree(tao->res_weights_cols));
3959566063dSJacob Faibussowitsch     PetscCall(PetscFree(tao->res_weights_w));
3969566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n,&tao->res_weights_rows));
3979566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n,&tao->res_weights_cols));
3989566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n,&tao->res_weights_w));
399737f463aSAlp Dener     tao->res_weights_n = n;
400737f463aSAlp Dener     for (i=0;i<n;i++) {
401737f463aSAlp Dener       tao->res_weights_rows[i] = rows[i];
402737f463aSAlp Dener       tao->res_weights_cols[i] = cols[i];
403737f463aSAlp Dener       tao->res_weights_w[i] = vals[i];
404737f463aSAlp Dener     }
405737f463aSAlp Dener   } else {
406737f463aSAlp Dener     tao->res_weights_n = 0;
40783c8fe1dSLisandro Dalcin     tao->res_weights_rows = NULL;
40883c8fe1dSLisandro Dalcin     tao->res_weights_cols = NULL;
409737f463aSAlp Dener   }
410a7e14dcfSSatish Balay   PetscFunctionReturn(0);
411a7e14dcfSSatish Balay }
412a7e14dcfSSatish Balay 
4138b7a9b22SJason Sarich /*@
4144a48860cSAlp Dener   TaoComputeResidual - Computes a least-squares residual vector at a given point
415a7e14dcfSSatish Balay 
41665ba42b6SBarry Smith   Collective on tao
417a7e14dcfSSatish Balay 
418a7e14dcfSSatish Balay   Input Parameters:
419441846f8SBarry Smith + tao - the Tao context
420a7e14dcfSSatish Balay - X - input vector
421a7e14dcfSSatish Balay 
422a7e14dcfSSatish Balay   Output Parameter:
423a7e14dcfSSatish Balay . f - Objective vector at X
424a7e14dcfSSatish Balay 
42595452b02SPatrick Sanan   Notes:
42665ba42b6SBarry Smith     `TaoComputeResidual()` is typically used within the implementation of the optimization algorithm,
427a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
428a7e14dcfSSatish Balay 
429a7e14dcfSSatish Balay   Level: advanced
430a7e14dcfSSatish Balay 
43165ba42b6SBarry Smith .seealso: `Tao`, `TaoSetResidualRoutine()`
432a7e14dcfSSatish Balay @*/
4334a48860cSAlp Dener PetscErrorCode TaoComputeResidual(Tao tao, Vec X, Vec F)
434a7e14dcfSSatish Balay {
435a7e14dcfSSatish Balay   PetscFunctionBegin;
436441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
437a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
438a7e14dcfSSatish Balay   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
439a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,X,2);
440a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,F,3);
4414a48860cSAlp Dener   if (tao->ops->computeresidual) {
4429566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(TAO_ObjectiveEval,tao,X,NULL,NULL));
443*792fecdfSBarry Smith     PetscCallBack("Tao callback least-squares residual",(*tao->ops->computeresidual)(tao,X,F,tao->user_lsresP));
4449566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(TAO_ObjectiveEval,tao,X,NULL,NULL));
445a7e14dcfSSatish Balay     tao->nfuncs++;
446691b26d3SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)tao),PETSC_ERR_ARG_WRONGSTATE,"TaoSetResidualRoutine() has not been called");
4479566063dSJacob Faibussowitsch   PetscCall(PetscInfo(tao,"TAO least-squares residual evaluation.\n"));
448a7e14dcfSSatish Balay   PetscFunctionReturn(0);
449a7e14dcfSSatish Balay }
450a7e14dcfSSatish Balay 
451a7e14dcfSSatish Balay /*@C
45265ba42b6SBarry Smith   TaoSetGradient - Sets the gradient evaluation routine for the function to be optimized
453a7e14dcfSSatish Balay 
45465ba42b6SBarry Smith   Logically collective on tao
455a7e14dcfSSatish Balay 
456d8d19677SJose E. Roman   Input Parameters:
457441846f8SBarry Smith + tao - the Tao context
458a82e8c82SStefano Zampini . g - [optional] the vector to internally hold the gradient computation
459a7e14dcfSSatish Balay . func - the gradient function
460a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the gradient evaluation
4616c23d075SBarry Smith         routine (may be NULL)
462a7e14dcfSSatish Balay 
463a7e14dcfSSatish Balay   Calling sequence of func:
464441846f8SBarry Smith $      func (Tao tao, Vec x, Vec g, void *ctx);
465a7e14dcfSSatish Balay 
466a7e14dcfSSatish Balay + x - input vector
467a7e14dcfSSatish Balay . g - gradient value (output)
468a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
469a7e14dcfSSatish Balay 
470a7e14dcfSSatish Balay   Level: beginner
471a7e14dcfSSatish Balay 
47265ba42b6SBarry Smith .seealso: `Tao`, `TaoSolve()`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoGetGradient()`
473a7e14dcfSSatish Balay @*/
474a82e8c82SStefano Zampini PetscErrorCode TaoSetGradient(Tao tao, Vec g, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx)
475a7e14dcfSSatish Balay {
476a7e14dcfSSatish Balay   PetscFunctionBegin;
477441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
478a82e8c82SStefano Zampini   if (g) {
479a82e8c82SStefano Zampini     PetscValidHeaderSpecific(g,VEC_CLASSID,2);
480a82e8c82SStefano Zampini     PetscCheckSameComm(tao,1,g,2);
4819566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)g));
4829566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&tao->gradient));
483a82e8c82SStefano Zampini     tao->gradient = g;
484a82e8c82SStefano Zampini   }
485a82e8c82SStefano Zampini   if (func) tao->ops->computegradient = func;
486a82e8c82SStefano Zampini   if (ctx) tao->user_gradP = ctx;
487a7e14dcfSSatish Balay   PetscFunctionReturn(0);
488a7e14dcfSSatish Balay }
489a7e14dcfSSatish Balay 
490a7e14dcfSSatish Balay /*@C
49165ba42b6SBarry Smith   TaoGetGradient - Gets the gradient evaluation routine for the function being optimized
492a82e8c82SStefano Zampini 
493a82e8c82SStefano Zampini   Not collective
494a82e8c82SStefano Zampini 
495a82e8c82SStefano Zampini   Input Parameter:
496a82e8c82SStefano Zampini . tao - the Tao context
497a82e8c82SStefano Zampini 
498a82e8c82SStefano Zampini   Output Parameters:
499a82e8c82SStefano Zampini + g - the vector to internally hold the gradient computation
500a82e8c82SStefano Zampini . func - the gradient function
501a82e8c82SStefano Zampini - ctx - user-defined context for private data for the gradient evaluation routine
502a82e8c82SStefano Zampini 
503a82e8c82SStefano Zampini   Calling sequence of func:
504a82e8c82SStefano Zampini $      func (Tao tao, Vec x, Vec g, void *ctx);
505a82e8c82SStefano Zampini 
506a82e8c82SStefano Zampini + x - input vector
507a82e8c82SStefano Zampini . g - gradient value (output)
508a82e8c82SStefano Zampini - ctx - [optional] user-defined function context
509a82e8c82SStefano Zampini 
510a82e8c82SStefano Zampini   Level: beginner
511a82e8c82SStefano Zampini 
51265ba42b6SBarry Smith .seealso: `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetGradient()`
513a82e8c82SStefano Zampini @*/
514a82e8c82SStefano Zampini PetscErrorCode TaoGetGradient(Tao tao, Vec *g, PetscErrorCode (**func)(Tao, Vec, Vec, void*),void **ctx)
515a82e8c82SStefano Zampini {
516a82e8c82SStefano Zampini   PetscFunctionBegin;
517a82e8c82SStefano Zampini   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
518a82e8c82SStefano Zampini   if (g) *g = tao->gradient;
519a82e8c82SStefano Zampini   if (func) *func = tao->ops->computegradient;
520a82e8c82SStefano Zampini   if (ctx) *ctx = tao->user_gradP;
521a82e8c82SStefano Zampini   PetscFunctionReturn(0);
522a82e8c82SStefano Zampini }
523a82e8c82SStefano Zampini 
524a82e8c82SStefano Zampini /*@C
52565ba42b6SBarry Smith   TaoSetObjectiveAndGradient - Sets a combined objective function and gradient evaluation routine for the function to be optimized
526a7e14dcfSSatish Balay 
52765ba42b6SBarry Smith   Logically collective on tao
528a7e14dcfSSatish Balay 
529d8d19677SJose E. Roman   Input Parameters:
530441846f8SBarry Smith + tao - the Tao context
531a82e8c82SStefano Zampini . g - [optional] the vector to internally hold the gradient computation
532a7e14dcfSSatish Balay . func - the gradient function
533a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the gradient evaluation
5346c23d075SBarry Smith         routine (may be NULL)
535a7e14dcfSSatish Balay 
536a7e14dcfSSatish Balay   Calling sequence of func:
53717477c02SJason Sarich $      func (Tao tao, Vec x, PetscReal *f, Vec g, void *ctx);
538a7e14dcfSSatish Balay 
539a7e14dcfSSatish Balay + x - input vector
54017477c02SJason Sarich . f - objective value (output)
541a7e14dcfSSatish Balay . g - gradient value (output)
542a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
543a7e14dcfSSatish Balay 
544a7e14dcfSSatish Balay   Level: beginner
545a7e14dcfSSatish Balay 
54665ba42b6SBarry Smith   Note:
54765ba42b6SBarry Smith   For some optimization methods using a combined function can be more eifficient.
54865ba42b6SBarry Smith 
54965ba42b6SBarry Smith .seealso: `Tao`, `TaoSolve()`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetGradient()`, `TaoGetObjectiveAndGradient()`
550a7e14dcfSSatish Balay @*/
551a82e8c82SStefano Zampini PetscErrorCode TaoSetObjectiveAndGradient(Tao tao, Vec g, PetscErrorCode (*func)(Tao, Vec, PetscReal*, Vec, void*), void *ctx)
552a82e8c82SStefano Zampini {
553a82e8c82SStefano Zampini   PetscFunctionBegin;
554a82e8c82SStefano Zampini   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
555a82e8c82SStefano Zampini   if (g) {
556a82e8c82SStefano Zampini     PetscValidHeaderSpecific(g,VEC_CLASSID,2);
557a82e8c82SStefano Zampini     PetscCheckSameComm(tao,1,g,2);
5589566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)g));
5599566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&tao->gradient));
560a82e8c82SStefano Zampini     tao->gradient = g;
561a82e8c82SStefano Zampini   }
562a82e8c82SStefano Zampini   if (ctx) tao->user_objgradP = ctx;
563a82e8c82SStefano Zampini   if (func) tao->ops->computeobjectiveandgradient = func;
564a82e8c82SStefano Zampini   PetscFunctionReturn(0);
565a82e8c82SStefano Zampini }
566a82e8c82SStefano Zampini 
567a82e8c82SStefano Zampini /*@C
56865ba42b6SBarry Smith   TaoGetObjectiveAndGradient - Gets the combined objective function and gradient evaluation routine for the function to be optimized
569a82e8c82SStefano Zampini 
570a82e8c82SStefano Zampini   Not collective
571a82e8c82SStefano Zampini 
572a82e8c82SStefano Zampini   Input Parameter:
573a82e8c82SStefano Zampini . tao - the Tao context
574a82e8c82SStefano Zampini 
575a82e8c82SStefano Zampini   Output Parameters:
576817da375SSatish Balay + g - the vector to internally hold the gradient computation
577a82e8c82SStefano Zampini . func - the gradient function
578a82e8c82SStefano Zampini - ctx - user-defined context for private data for the gradient evaluation routine
579a82e8c82SStefano Zampini 
580a82e8c82SStefano Zampini   Calling sequence of func:
581a82e8c82SStefano Zampini $      func (Tao tao, Vec x, PetscReal *f, Vec g, void *ctx);
582a82e8c82SStefano Zampini 
583a82e8c82SStefano Zampini + x - input vector
584a82e8c82SStefano Zampini . f - objective value (output)
585a82e8c82SStefano Zampini . g - gradient value (output)
586a82e8c82SStefano Zampini - ctx - [optional] user-defined function context
587a82e8c82SStefano Zampini 
588a82e8c82SStefano Zampini   Level: beginner
589a82e8c82SStefano Zampini 
59065ba42b6SBarry Smith .seealso: `Tao`, `TaoSolve()`, `TaoSetObjective()`, `TaoSetGradient()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`
591a82e8c82SStefano Zampini @*/
592a82e8c82SStefano Zampini PetscErrorCode TaoGetObjectiveAndGradient(Tao tao, Vec *g, PetscErrorCode (**func)(Tao, Vec, PetscReal*, Vec, void*), void **ctx)
593a7e14dcfSSatish Balay {
594a7e14dcfSSatish Balay   PetscFunctionBegin;
595441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
596a82e8c82SStefano Zampini   if (g) *g = tao->gradient;
597a82e8c82SStefano Zampini   if (func) *func = tao->ops->computeobjectiveandgradient;
598a82e8c82SStefano Zampini   if (ctx) *ctx = tao->user_objgradP;
599a7e14dcfSSatish Balay   PetscFunctionReturn(0);
600a7e14dcfSSatish Balay }
601a7e14dcfSSatish Balay 
602a7e14dcfSSatish Balay /*@
603a82e8c82SStefano Zampini   TaoIsObjectiveDefined - Checks to see if the user has
604a7e14dcfSSatish Balay   declared an objective-only routine.  Useful for determining when
60565ba42b6SBarry Smith   it is appropriate to call `TaoComputeObjective()` or
60665ba42b6SBarry Smith   `TaoComputeObjectiveAndGradient()`
607a7e14dcfSSatish Balay 
608a82e8c82SStefano Zampini   Not collective
609a7e14dcfSSatish Balay 
610a82e8c82SStefano Zampini   Input Parameter:
611a82e8c82SStefano Zampini . tao - the Tao context
612a82e8c82SStefano Zampini 
613a82e8c82SStefano Zampini   Output Parameter:
61465ba42b6SBarry Smith . flg - `PETSC_TRUE` if function routine is set by user, `PETSC_FALSE` otherwise
615a82e8c82SStefano Zampini 
616a7e14dcfSSatish Balay   Level: developer
617a7e14dcfSSatish Balay 
61865ba42b6SBarry Smith .seealso: `Tao`, `TaoSetObjective()`, `TaoIsGradientDefined()`, `TaoIsObjectiveAndGradientDefined()`
619a7e14dcfSSatish Balay @*/
620441846f8SBarry Smith PetscErrorCode TaoIsObjectiveDefined(Tao tao, PetscBool *flg)
621a7e14dcfSSatish Balay {
622a7e14dcfSSatish Balay   PetscFunctionBegin;
623441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
62483c8fe1dSLisandro Dalcin   if (tao->ops->computeobjective == NULL) *flg = PETSC_FALSE;
62545cf516eSBarry Smith   else *flg = PETSC_TRUE;
626a7e14dcfSSatish Balay   PetscFunctionReturn(0);
627a7e14dcfSSatish Balay }
628a7e14dcfSSatish Balay 
629a7e14dcfSSatish Balay /*@
630a82e8c82SStefano Zampini   TaoIsGradientDefined - Checks to see if the user has
631a7e14dcfSSatish Balay   declared an objective-only routine.  Useful for determining when
63265ba42b6SBarry Smith   it is appropriate to call `TaoComputeGradient()` or
63365ba42b6SBarry Smith   `TaoComputeGradientAndGradient()`
634a7e14dcfSSatish Balay 
635a7e14dcfSSatish Balay   Not Collective
636a7e14dcfSSatish Balay 
637a82e8c82SStefano Zampini   Input Parameter:
638a82e8c82SStefano Zampini . tao - the Tao context
639a82e8c82SStefano Zampini 
640a82e8c82SStefano Zampini   Output Parameter:
64165ba42b6SBarry Smith . flg - `PETSC_TRUE` if function routine is set by user, `PETSC_FALSE` otherwise
642a82e8c82SStefano Zampini 
643a7e14dcfSSatish Balay   Level: developer
644a7e14dcfSSatish Balay 
645db781477SPatrick Sanan .seealso: `TaoSetGradient()`, `TaoIsObjectiveDefined()`, `TaoIsObjectiveAndGradientDefined()`
646a7e14dcfSSatish Balay @*/
647441846f8SBarry Smith PetscErrorCode TaoIsGradientDefined(Tao tao, PetscBool *flg)
648a7e14dcfSSatish Balay {
649a7e14dcfSSatish Balay   PetscFunctionBegin;
650441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
65183c8fe1dSLisandro Dalcin   if (tao->ops->computegradient == NULL) *flg = PETSC_FALSE;
65245cf516eSBarry Smith   else *flg = PETSC_TRUE;
653a7e14dcfSSatish Balay   PetscFunctionReturn(0);
654a7e14dcfSSatish Balay }
655a7e14dcfSSatish Balay 
656a7e14dcfSSatish Balay /*@
657a82e8c82SStefano Zampini   TaoIsObjectiveAndGradientDefined - Checks to see if the user has
658a7e14dcfSSatish Balay   declared a joint objective/gradient routine.  Useful for determining when
65965ba42b6SBarry Smith   it is appropriate to call `TaoComputeObjective()` or
66065ba42b6SBarry Smith   `TaoComputeObjectiveAndGradient()`
661a7e14dcfSSatish Balay 
662a7e14dcfSSatish Balay   Not Collective
663a7e14dcfSSatish Balay 
664a82e8c82SStefano Zampini   Input Parameter:
665a82e8c82SStefano Zampini . tao - the Tao context
666a82e8c82SStefano Zampini 
667a82e8c82SStefano Zampini   Output Parameter:
66865ba42b6SBarry Smith . flg - `PETSC_TRUE` if function routine is set by user, `PETSC_FALSE` otherwise
669a82e8c82SStefano Zampini 
670a7e14dcfSSatish Balay   Level: developer
671a7e14dcfSSatish Balay 
672db781477SPatrick Sanan .seealso: `TaoSetObjectiveAndGradient()`, `TaoIsObjectiveDefined()`, `TaoIsGradientDefined()`
673a7e14dcfSSatish Balay @*/
674441846f8SBarry Smith PetscErrorCode TaoIsObjectiveAndGradientDefined(Tao tao, PetscBool *flg)
675a7e14dcfSSatish Balay {
676a7e14dcfSSatish Balay   PetscFunctionBegin;
677441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
67883c8fe1dSLisandro Dalcin   if (tao->ops->computeobjectiveandgradient == NULL) *flg = PETSC_FALSE;
67945cf516eSBarry Smith   else *flg = PETSC_TRUE;
680a7e14dcfSSatish Balay   PetscFunctionReturn(0);
681a7e14dcfSSatish Balay }
682