xref: /petsc/src/tao/interface/taosolver_fg.c (revision 737f463ab30e8a11bf8f036b04a75b5d358c645b)
1af0996ceSBarry Smith #include <petsc/private/taoimpl.h> /*I "petsctao.h" I*/
2a7e14dcfSSatish Balay 
3a7e14dcfSSatish Balay /*@
4a7e14dcfSSatish Balay   TaoSetInitialVector - Sets the initial guess for the solve
5a7e14dcfSSatish Balay 
6441846f8SBarry 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
13a7e14dcfSSatish Balay .seealso: TaoCreate(), TaoSolve()
14a7e14dcfSSatish Balay @*/
15a7e14dcfSSatish Balay 
16441846f8SBarry Smith PetscErrorCode TaoSetInitialVector(Tao tao, Vec x0)
1745cf516eSBarry Smith {
18a7e14dcfSSatish Balay   PetscErrorCode ierr;
19a7e14dcfSSatish Balay 
20a7e14dcfSSatish Balay   PetscFunctionBegin;
21441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
22a7e14dcfSSatish Balay   if (x0) {
23a7e14dcfSSatish Balay     PetscValidHeaderSpecific(x0,VEC_CLASSID,2);
24a7e14dcfSSatish Balay     PetscObjectReference((PetscObject)x0);
25a7e14dcfSSatish Balay   }
26a7e14dcfSSatish Balay   ierr = VecDestroy(&tao->solution);CHKERRQ(ierr);
27a7e14dcfSSatish Balay   tao->solution = x0;
28a7e14dcfSSatish Balay   PetscFunctionReturn(0);
29a7e14dcfSSatish Balay }
30a7e14dcfSSatish Balay 
31412cdd55SHong Zhang PetscErrorCode TaoTestGradient(Tao tao,Vec x,Vec g1)
3209baa881SHong Zhang {
33412cdd55SHong Zhang   Vec               g2,g3;
3409baa881SHong Zhang   PetscBool         complete_print = PETSC_FALSE,test = PETSC_FALSE;
3509baa881SHong Zhang   PetscReal         hcnorm,fdnorm,hcmax,fdmax,diffmax,diffnorm;
3609baa881SHong Zhang   PetscScalar       dot;
3709baa881SHong Zhang   MPI_Comm          comm;
38913eda9aSHong Zhang   PetscViewer       viewer,mviewer;
39913eda9aSHong Zhang   PetscViewerFormat format;
4009baa881SHong Zhang   PetscInt          tabs;
4109baa881SHong Zhang   static PetscBool  directionsprinted = PETSC_FALSE;
4209baa881SHong Zhang   PetscErrorCode    ierr;
4309baa881SHong Zhang 
4409baa881SHong Zhang   PetscFunctionBegin;
4509baa881SHong Zhang   ierr = PetscObjectOptionsBegin((PetscObject)tao);CHKERRQ(ierr);
4609baa881SHong Zhang   ierr = PetscOptionsName("-tao_test_gradient","Compare hand-coded and finite difference Gradients","None",&test);CHKERRQ(ierr);
47913eda9aSHong Zhang   ierr = PetscOptionsViewer("-tao_test_gradient_view","View difference between hand-coded and finite difference Gradients element entries","None",&mviewer,&format,&complete_print);CHKERRQ(ierr);
4809baa881SHong Zhang   ierr = PetscOptionsEnd();CHKERRQ(ierr);
4909baa881SHong Zhang   if (!test) PetscFunctionReturn(0);
5009baa881SHong Zhang 
5109baa881SHong Zhang   ierr = PetscObjectGetComm((PetscObject)tao,&comm);CHKERRQ(ierr);
5209baa881SHong Zhang   ierr = PetscViewerASCIIGetStdout(comm,&viewer);CHKERRQ(ierr);
5309baa881SHong Zhang   ierr = PetscViewerASCIIGetTab(viewer, &tabs);CHKERRQ(ierr);
5409baa881SHong Zhang   ierr = PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel);CHKERRQ(ierr);
5509baa881SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  ---------- Testing Gradient -------------\n");CHKERRQ(ierr);
5609baa881SHong Zhang   if (!complete_print && !directionsprinted) {
5709baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  Run with -tao_test_gradient_view and optionally -tao_test_gradient <threshold> to show difference\n");CHKERRQ(ierr);
5809baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"    of hand-coded and finite difference gradient entries greater than <threshold>.\n");CHKERRQ(ierr);
5909baa881SHong Zhang   }
6009baa881SHong Zhang   if (!directionsprinted) {
6109baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  Testing hand-coded Gradient, if (for double precision runs) ||G - Gfd||_F/||G||_F is\n");CHKERRQ(ierr);
6209baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"    O(1.e-8), the hand-coded Hessian is probably correct.\n");CHKERRQ(ierr);
6309baa881SHong Zhang     directionsprinted = PETSC_TRUE;
6409baa881SHong Zhang   }
65913eda9aSHong Zhang   if (complete_print) {
66913eda9aSHong Zhang     ierr = PetscViewerPushFormat(mviewer,format);CHKERRQ(ierr);
67913eda9aSHong Zhang   }
6809baa881SHong Zhang 
6909baa881SHong Zhang   ierr = VecDuplicate(x,&g2);CHKERRQ(ierr);
7009baa881SHong Zhang   ierr = VecDuplicate(x,&g3);CHKERRQ(ierr);
7109baa881SHong Zhang 
7209baa881SHong Zhang   /* Compute finite difference gradient, assume the gradient is already computed by TaoComputeGradient() and put into g1 */
7309baa881SHong Zhang   ierr = TaoDefaultComputeGradient(tao,x,g2,NULL);CHKERRQ(ierr);
7409baa881SHong Zhang 
7509baa881SHong Zhang   ierr = VecNorm(g2,NORM_2,&fdnorm);CHKERRQ(ierr);
7609baa881SHong Zhang   ierr = VecNorm(g1,NORM_2,&hcnorm);CHKERRQ(ierr);
7709baa881SHong Zhang   ierr = VecNorm(g2,NORM_INFINITY,&fdmax);CHKERRQ(ierr);
7809baa881SHong Zhang   ierr = VecNorm(g1,NORM_INFINITY,&hcmax);CHKERRQ(ierr);
7909baa881SHong Zhang   ierr = VecDot(g1,g2,&dot);CHKERRQ(ierr);
8009baa881SHong Zhang   ierr = VecCopy(g1,g3);CHKERRQ(ierr);
8109baa881SHong Zhang   ierr = VecAXPY(g3,-1.0,g2);CHKERRQ(ierr);
8209baa881SHong Zhang   ierr = VecNorm(g3,NORM_2,&diffnorm);CHKERRQ(ierr);
8309baa881SHong Zhang   ierr = VecNorm(g3,NORM_INFINITY,&diffmax);CHKERRQ(ierr);
8409baa881SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  ||Gfd|| %g, ||G|| = %g, angle cosine = (Gfd'G)/||Gfd||||G|| = %g\n", (double)fdnorm, (double)hcnorm, (double)(PetscRealPart(dot)/(fdnorm*hcnorm)));CHKERRQ(ierr);
8509baa881SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  2-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n",(double)(diffnorm/PetscMax(hcnorm,fdnorm)),(double)diffnorm);CHKERRQ(ierr);
8609baa881SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  max-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n",(double)(diffmax/PetscMax(hcmax,fdmax)),(double)diffmax);CHKERRQ(ierr);
8709baa881SHong Zhang 
8809baa881SHong Zhang   if (complete_print) {
8909baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  Hand-coded gradient ----------\n");CHKERRQ(ierr);
90913eda9aSHong Zhang     ierr = VecView(g1,mviewer);CHKERRQ(ierr);
9109baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  Finite difference gradient ----------\n");CHKERRQ(ierr);
92913eda9aSHong Zhang     ierr = VecView(g2,mviewer);CHKERRQ(ierr);
9309baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  Hand-coded minus finite-difference gradient ----------\n");CHKERRQ(ierr);
94913eda9aSHong Zhang     ierr = VecView(g3,mviewer);CHKERRQ(ierr);
9509baa881SHong Zhang   }
9609baa881SHong Zhang   ierr = VecDestroy(&g2);CHKERRQ(ierr);
9709baa881SHong Zhang   ierr = VecDestroy(&g3);CHKERRQ(ierr);
98913eda9aSHong Zhang 
99913eda9aSHong Zhang   if (complete_print) {
100913eda9aSHong Zhang     ierr = PetscViewerPopFormat(mviewer);CHKERRQ(ierr);
101913eda9aSHong Zhang   }
102913eda9aSHong Zhang   ierr = PetscViewerASCIISetTab(viewer,tabs);CHKERRQ(ierr);
10309baa881SHong Zhang   PetscFunctionReturn(0);
10409baa881SHong Zhang }
10509baa881SHong Zhang 
106a7e14dcfSSatish Balay /*@
107a7e14dcfSSatish Balay   TaoComputeGradient - Computes the gradient of the objective function
108a7e14dcfSSatish Balay 
109441846f8SBarry Smith   Collective on Tao
110a7e14dcfSSatish Balay 
111a7e14dcfSSatish Balay   Input Parameters:
112441846f8SBarry Smith + tao - the Tao context
113a7e14dcfSSatish Balay - X - input vector
114a7e14dcfSSatish Balay 
115a7e14dcfSSatish Balay   Output Parameter:
116a7e14dcfSSatish Balay . G - gradient vector
117a7e14dcfSSatish Balay 
11809baa881SHong Zhang   Options Database Keys:
11909baa881SHong Zhang +    -tao_test_gradient - compare the user provided gradient with one compute via finite differences to check for errors
120dfe02fe6SHong 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
12109baa881SHong Zhang 
12295452b02SPatrick Sanan   Notes:
12395452b02SPatrick Sanan     TaoComputeGradient() is typically used within minimization implementations,
124a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
125a7e14dcfSSatish Balay 
126a7e14dcfSSatish Balay   Level: advanced
127a7e14dcfSSatish Balay 
128a7e14dcfSSatish Balay .seealso: TaoComputeObjective(), TaoComputeObjectiveAndGradient(), TaoSetGradientRoutine()
129a7e14dcfSSatish Balay @*/
130441846f8SBarry Smith PetscErrorCode TaoComputeGradient(Tao tao, Vec X, Vec G)
131a7e14dcfSSatish Balay {
132a7e14dcfSSatish Balay   PetscErrorCode ierr;
133a7e14dcfSSatish Balay   PetscReal      dummy;
13487f595a5SBarry Smith 
135a7e14dcfSSatish Balay   PetscFunctionBegin;
136441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
137a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
138a7e14dcfSSatish Balay   PetscValidHeaderSpecific(G,VEC_CLASSID,2);
139a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,X,2);
140a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,G,3);
141f4c1ad5cSStefano Zampini   ierr = VecLockPush(X);CHKERRQ(ierr);
142a7e14dcfSSatish Balay   if (tao->ops->computegradient) {
1430ebee16dSLisandro Dalcin     ierr = PetscLogEventBegin(TAO_GradientEval,tao,X,G,NULL);CHKERRQ(ierr);
144441846f8SBarry Smith     PetscStackPush("Tao user gradient evaluation routine");
145a7e14dcfSSatish Balay     ierr = (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);CHKERRQ(ierr);
146a7e14dcfSSatish Balay     PetscStackPop;
1470ebee16dSLisandro Dalcin     ierr = PetscLogEventEnd(TAO_GradientEval,tao,X,G,NULL);CHKERRQ(ierr);
148a7e14dcfSSatish Balay     tao->ngrads++;
149a7e14dcfSSatish Balay   } else if (tao->ops->computeobjectiveandgradient) {
1500ebee16dSLisandro Dalcin     ierr = PetscLogEventBegin(TAO_ObjGradEval,tao,X,G,NULL);CHKERRQ(ierr);
151a7e14dcfSSatish Balay     PetscStackPush("Tao user objective/gradient evaluation routine");
152a7e14dcfSSatish Balay     ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,&dummy,G,tao->user_objgradP);CHKERRQ(ierr);
153a7e14dcfSSatish Balay     PetscStackPop;
1540ebee16dSLisandro Dalcin     ierr = PetscLogEventEnd(TAO_ObjGradEval,tao,X,G,NULL);CHKERRQ(ierr);
155a7e14dcfSSatish Balay     tao->nfuncgrads++;
15687f595a5SBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetGradientRoutine() has not been called");
157f4c1ad5cSStefano Zampini   ierr = VecLockPop(X);CHKERRQ(ierr);
15809baa881SHong Zhang 
159412cdd55SHong Zhang   ierr = TaoTestGradient(tao,X,G);CHKERRQ(ierr);
160a7e14dcfSSatish Balay   PetscFunctionReturn(0);
161a7e14dcfSSatish Balay }
162a7e14dcfSSatish Balay 
163a7e14dcfSSatish Balay /*@
164a7e14dcfSSatish Balay   TaoComputeObjective - Computes the objective function value at a given point
165a7e14dcfSSatish Balay 
166441846f8SBarry Smith   Collective on Tao
167a7e14dcfSSatish Balay 
168a7e14dcfSSatish Balay   Input Parameters:
169441846f8SBarry Smith + tao - the Tao context
170a7e14dcfSSatish Balay - X - input vector
171a7e14dcfSSatish Balay 
172a7e14dcfSSatish Balay   Output Parameter:
173a7e14dcfSSatish Balay . f - Objective value at X
174a7e14dcfSSatish Balay 
17595452b02SPatrick Sanan   Notes:
17695452b02SPatrick Sanan     TaoComputeObjective() is typically used within minimization implementations,
177a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
178a7e14dcfSSatish Balay 
179a7e14dcfSSatish Balay   Level: advanced
180a7e14dcfSSatish Balay 
181a7e14dcfSSatish Balay .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine()
182a7e14dcfSSatish Balay @*/
183441846f8SBarry Smith PetscErrorCode TaoComputeObjective(Tao tao, Vec X, PetscReal *f)
184a7e14dcfSSatish Balay {
185a7e14dcfSSatish Balay   PetscErrorCode ierr;
186a7e14dcfSSatish Balay   Vec            temp;
18787f595a5SBarry Smith 
188a7e14dcfSSatish Balay   PetscFunctionBegin;
189441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
190a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
191a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,X,2);
192f4c1ad5cSStefano Zampini   ierr = VecLockPush(X);CHKERRQ(ierr);
193a7e14dcfSSatish Balay   if (tao->ops->computeobjective) {
1940ebee16dSLisandro Dalcin     ierr = PetscLogEventBegin(TAO_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
195441846f8SBarry Smith     PetscStackPush("Tao user objective evaluation routine");
196a7e14dcfSSatish Balay     ierr = (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);CHKERRQ(ierr);
197a7e14dcfSSatish Balay     PetscStackPop;
1980ebee16dSLisandro Dalcin     ierr = PetscLogEventEnd(TAO_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
199a7e14dcfSSatish Balay     tao->nfuncs++;
200a7e14dcfSSatish Balay   } else if (tao->ops->computeobjectiveandgradient) {
201955c1f14SBarry Smith     ierr = PetscInfo(tao,"Duplicating variable vector in order to call func/grad routine\n");CHKERRQ(ierr);
202a7e14dcfSSatish Balay     ierr = VecDuplicate(X,&temp);CHKERRQ(ierr);
2030ebee16dSLisandro Dalcin     ierr = PetscLogEventBegin(TAO_ObjGradEval,tao,X,NULL,NULL);CHKERRQ(ierr);
204441846f8SBarry Smith     PetscStackPush("Tao user objective/gradient evaluation routine");
205a7e14dcfSSatish Balay     ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,f,temp,tao->user_objgradP);CHKERRQ(ierr);
206a7e14dcfSSatish Balay     PetscStackPop;
2070ebee16dSLisandro Dalcin     ierr = PetscLogEventEnd(TAO_ObjGradEval,tao,X,NULL,NULL);CHKERRQ(ierr);
208a7e14dcfSSatish Balay     ierr = VecDestroy(&temp);CHKERRQ(ierr);
209a7e14dcfSSatish Balay     tao->nfuncgrads++;
21087f595a5SBarry Smith   }  else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() has not been called");
211e356b196STodd Munson   ierr = PetscInfo1(tao,"TAO Function evaluation: %20.19e\n",(double)(*f));CHKERRQ(ierr);
212f4c1ad5cSStefano Zampini   ierr = VecLockPop(X);CHKERRQ(ierr);
213a7e14dcfSSatish Balay   PetscFunctionReturn(0);
214a7e14dcfSSatish Balay }
215a7e14dcfSSatish Balay 
216a7e14dcfSSatish Balay /*@
217a7e14dcfSSatish Balay   TaoComputeObjectiveAndGradient - Computes the objective function value at a given point
218a7e14dcfSSatish Balay 
219441846f8SBarry Smith   Collective on Tao
220a7e14dcfSSatish Balay 
221a7e14dcfSSatish Balay   Input Parameters:
222441846f8SBarry Smith + tao - the Tao context
223a7e14dcfSSatish Balay - X - input vector
224a7e14dcfSSatish Balay 
225a7e14dcfSSatish Balay   Output Parameter:
226a7e14dcfSSatish Balay + f - Objective value at X
227a7e14dcfSSatish Balay - g - Gradient vector at X
228a7e14dcfSSatish Balay 
22995452b02SPatrick Sanan   Notes:
23095452b02SPatrick Sanan     TaoComputeObjectiveAndGradient() is typically used within minimization implementations,
231a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
232a7e14dcfSSatish Balay 
233a7e14dcfSSatish Balay   Level: advanced
234a7e14dcfSSatish Balay 
235a7e14dcfSSatish Balay .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine()
236a7e14dcfSSatish Balay @*/
237441846f8SBarry Smith PetscErrorCode TaoComputeObjectiveAndGradient(Tao tao, Vec X, PetscReal *f, Vec G)
238a7e14dcfSSatish Balay {
239a7e14dcfSSatish Balay   PetscErrorCode ierr;
24087f595a5SBarry Smith 
241a7e14dcfSSatish Balay   PetscFunctionBegin;
242441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
243a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
244a7e14dcfSSatish Balay   PetscValidHeaderSpecific(G,VEC_CLASSID,4);
245a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,X,2);
246a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,G,4);
247f4c1ad5cSStefano Zampini   ierr = VecLockPush(X);CHKERRQ(ierr);
248a7e14dcfSSatish Balay   if (tao->ops->computeobjectiveandgradient) {
2490ebee16dSLisandro Dalcin     ierr = PetscLogEventBegin(TAO_ObjGradEval,tao,X,G,NULL);CHKERRQ(ierr);
250f4c1ad5cSStefano Zampini     if (tao->ops->computegradient == TaoDefaultComputeGradient) {
251f4c1ad5cSStefano Zampini       ierr = TaoComputeObjective(tao,X,f);CHKERRQ(ierr);
252f4c1ad5cSStefano Zampini       ierr = TaoDefaultComputeGradient(tao,X,G,NULL);CHKERRQ(ierr);
253f4c1ad5cSStefano Zampini     } else {
254441846f8SBarry Smith       PetscStackPush("Tao user objective/gradient evaluation routine");
255a7e14dcfSSatish Balay       ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,f,G,tao->user_objgradP);CHKERRQ(ierr);
2560cbffdbaSBarry Smith       PetscStackPop;
257a7e14dcfSSatish Balay     }
2580ebee16dSLisandro Dalcin     ierr = PetscLogEventEnd(TAO_ObjGradEval,tao,X,G,NULL);CHKERRQ(ierr);
259a7e14dcfSSatish Balay     tao->nfuncgrads++;
260a7e14dcfSSatish Balay   } else if (tao->ops->computeobjective && tao->ops->computegradient) {
2610ebee16dSLisandro Dalcin     ierr = PetscLogEventBegin(TAO_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
262441846f8SBarry Smith     PetscStackPush("Tao user objective evaluation routine");
263a7e14dcfSSatish Balay     ierr = (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);CHKERRQ(ierr);
264a7e14dcfSSatish Balay     PetscStackPop;
2650ebee16dSLisandro Dalcin     ierr = PetscLogEventEnd(TAO_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
266a7e14dcfSSatish Balay     tao->nfuncs++;
2670ebee16dSLisandro Dalcin     ierr = PetscLogEventBegin(TAO_GradientEval,tao,X,G,NULL);CHKERRQ(ierr);
268441846f8SBarry Smith     PetscStackPush("Tao user gradient evaluation routine");
269a7e14dcfSSatish Balay     ierr = (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);CHKERRQ(ierr);
270a7e14dcfSSatish Balay     PetscStackPop;
2710ebee16dSLisandro Dalcin     ierr = PetscLogEventEnd(TAO_GradientEval,tao,X,G,NULL);CHKERRQ(ierr);
272a7e14dcfSSatish Balay     tao->ngrads++;
27387f595a5SBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() or TaoSetGradientRoutine() not set");
274e356b196STodd Munson   ierr = PetscInfo1(tao,"TAO Function evaluation: %20.19e\n",(double)(*f));CHKERRQ(ierr);
275f4c1ad5cSStefano Zampini   ierr = VecLockPop(X);CHKERRQ(ierr);
2761657496cSHong Zhang 
277412cdd55SHong Zhang   ierr = TaoTestGradient(tao,X,G);CHKERRQ(ierr);
278a7e14dcfSSatish Balay   PetscFunctionReturn(0);
279a7e14dcfSSatish Balay }
280a7e14dcfSSatish Balay 
281a7e14dcfSSatish Balay /*@C
282a7e14dcfSSatish Balay   TaoSetObjectiveRoutine - Sets the function evaluation routine for minimization
283a7e14dcfSSatish Balay 
284441846f8SBarry Smith   Logically collective on Tao
285a7e14dcfSSatish Balay 
286a7e14dcfSSatish Balay   Input Parameter:
287441846f8SBarry Smith + tao - the Tao context
288a7e14dcfSSatish Balay . func - the objective function
289a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the function evaluation
2906c23d075SBarry Smith         routine (may be NULL)
291a7e14dcfSSatish Balay 
292a7e14dcfSSatish Balay   Calling sequence of func:
293441846f8SBarry Smith $      func (Tao tao, Vec x, PetscReal *f, void *ctx);
294a7e14dcfSSatish Balay 
295a7e14dcfSSatish Balay + x - input vector
296a7e14dcfSSatish Balay . f - function value
297a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
298a7e14dcfSSatish Balay 
299a7e14dcfSSatish Balay   Level: beginner
300a7e14dcfSSatish Balay 
301a7e14dcfSSatish Balay .seealso: TaoSetGradientRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine()
302a7e14dcfSSatish Balay @*/
303441846f8SBarry Smith PetscErrorCode TaoSetObjectiveRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal*,void*),void *ctx)
304a7e14dcfSSatish Balay {
305a7e14dcfSSatish Balay   PetscFunctionBegin;
306441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
307a7e14dcfSSatish Balay   tao->user_objP = ctx;
308a7e14dcfSSatish Balay   tao->ops->computeobjective = func;
309a7e14dcfSSatish Balay   PetscFunctionReturn(0);
310a7e14dcfSSatish Balay }
311a7e14dcfSSatish Balay 
312a7e14dcfSSatish Balay /*@C
3134a48860cSAlp Dener   TaoSetResidualRoutine - Sets the residual evaluation routine for least-square applications
314a7e14dcfSSatish Balay 
315441846f8SBarry Smith   Logically collective on Tao
316a7e14dcfSSatish Balay 
317a7e14dcfSSatish Balay   Input Parameter:
318441846f8SBarry Smith + tao - the Tao context
3194a48860cSAlp Dener . func - the residual evaluation routine
320a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the function evaluation
3216c23d075SBarry Smith         routine (may be NULL)
322a7e14dcfSSatish Balay 
323a7e14dcfSSatish Balay   Calling sequence of func:
324441846f8SBarry Smith $      func (Tao tao, Vec x, Vec f, void *ctx);
325a7e14dcfSSatish Balay 
326a7e14dcfSSatish Balay + x - input vector
327a7e14dcfSSatish Balay . f - function value vector
328a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
329a7e14dcfSSatish Balay 
330a7e14dcfSSatish Balay   Level: beginner
331a7e14dcfSSatish Balay 
332a7e14dcfSSatish Balay .seealso: TaoSetObjectiveRoutine(), TaoSetJacobianRoutine()
333a7e14dcfSSatish Balay @*/
3344a48860cSAlp Dener PetscErrorCode TaoSetResidualRoutine(Tao tao, Vec res, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx)
335a7e14dcfSSatish Balay {
336*737f463aSAlp Dener   PetscErrorCode ierr;
337*737f463aSAlp Dener 
338a7e14dcfSSatish Balay   PetscFunctionBegin;
339441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
3404a48860cSAlp Dener   PetscValidHeaderSpecific(res,VEC_CLASSID,2);
3414a48860cSAlp Dener   tao->user_lsresP = ctx;
342*737f463aSAlp Dener   if (tao->ls_res) {
343*737f463aSAlp Dener     ierr = VecDestroy(&tao->ls_res);CHKERRQ(ierr);
344*737f463aSAlp Dener   }
345*737f463aSAlp Dener   ierr = PetscObjectReference((PetscObject)res);CHKERRQ(ierr);
3464a48860cSAlp Dener   tao->ls_res = res;
3474a48860cSAlp Dener   tao->ops->computeresidual = func;
348*737f463aSAlp Dener 
349*737f463aSAlp Dener   PetscFunctionReturn(0);
350*737f463aSAlp Dener }
351*737f463aSAlp Dener 
352*737f463aSAlp Dener /*@
353*737f463aSAlp Dener   TaoSetResidualWeights - Give weights for the residual values. A vector can be used if only diagonal terms are used, otherwise a matrix can be give. If this function is not used, or if sigma_v and sigma_w are both NULL, then the default identity matrix will be used for weights.
354*737f463aSAlp Dener 
355*737f463aSAlp Dener   Collective on Tao
356*737f463aSAlp Dener 
357*737f463aSAlp Dener   Input Parameters:
358*737f463aSAlp Dener + tao - the Tao context
359*737f463aSAlp Dener . sigma_v - vector of weights (diagonal terms only)
360*737f463aSAlp Dener . n       - the number of weights (if using off-diagonal)
361*737f463aSAlp Dener . rows    - index list of rows for sigma_w
362*737f463aSAlp Dener . cols    - index list of columns for sigma_w
363*737f463aSAlp Dener - vals - array of weights
364*737f463aSAlp Dener 
365*737f463aSAlp Dener 
366*737f463aSAlp Dener 
367*737f463aSAlp Dener   Note: Either sigma_v or sigma_w (or both) should be NULL
368*737f463aSAlp Dener 
369*737f463aSAlp Dener   Level: intermediate
370*737f463aSAlp Dener 
371*737f463aSAlp Dener .seealso: TaoSetResidualRoutine()
372*737f463aSAlp Dener @*/
373*737f463aSAlp Dener PetscErrorCode TaoSetResidualWeights(Tao tao, Vec sigma_v, PetscInt n, PetscInt *rows, PetscInt *cols, PetscReal *vals)
374*737f463aSAlp Dener {
375*737f463aSAlp Dener   PetscErrorCode ierr;
376*737f463aSAlp Dener   PetscInt       i;
377*737f463aSAlp Dener   PetscFunctionBegin;
378*737f463aSAlp Dener   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
379*737f463aSAlp Dener   ierr = VecDestroy(&tao->res_weights_v);CHKERRQ(ierr);
380*737f463aSAlp Dener   tao->res_weights_v=sigma_v;
381*737f463aSAlp Dener   if (sigma_v) {
382*737f463aSAlp Dener     ierr = PetscObjectReference((PetscObject)sigma_v);CHKERRQ(ierr);
383*737f463aSAlp Dener   }
384*737f463aSAlp Dener   if (vals) {
385*737f463aSAlp Dener     if (tao->res_weights_n) {
386*737f463aSAlp Dener       ierr = PetscFree(tao->res_weights_rows);CHKERRQ(ierr);
387*737f463aSAlp Dener       ierr = PetscFree(tao->res_weights_cols);CHKERRQ(ierr);
388*737f463aSAlp Dener       ierr = PetscFree(tao->res_weights_w);CHKERRQ(ierr);
389*737f463aSAlp Dener     }
390*737f463aSAlp Dener     ierr = PetscMalloc1(n,&tao->res_weights_rows);CHKERRQ(ierr);
391*737f463aSAlp Dener     ierr = PetscMalloc1(n,&tao->res_weights_cols);CHKERRQ(ierr);
392*737f463aSAlp Dener     ierr = PetscMalloc1(n,&tao->res_weights_w);CHKERRQ(ierr);
393*737f463aSAlp Dener     tao->res_weights_n=n;
394*737f463aSAlp Dener     for (i=0;i<n;i++) {
395*737f463aSAlp Dener       tao->res_weights_rows[i]=rows[i];
396*737f463aSAlp Dener       tao->res_weights_cols[i]=cols[i];
397*737f463aSAlp Dener       tao->res_weights_w[i]=vals[i];
398*737f463aSAlp Dener     }
399*737f463aSAlp Dener   } else {
400*737f463aSAlp Dener     tao->res_weights_n=0;
401*737f463aSAlp Dener     tao->res_weights_rows=0;
402*737f463aSAlp Dener     tao->res_weights_cols=0;
403*737f463aSAlp Dener   }
404a7e14dcfSSatish Balay   PetscFunctionReturn(0);
405a7e14dcfSSatish Balay }
406a7e14dcfSSatish Balay 
4078b7a9b22SJason Sarich /*@
4084a48860cSAlp Dener   TaoComputeResidual - Computes a least-squares residual vector at a given point
409a7e14dcfSSatish Balay 
410441846f8SBarry Smith   Collective on Tao
411a7e14dcfSSatish Balay 
412a7e14dcfSSatish Balay   Input Parameters:
413441846f8SBarry Smith + tao - the Tao context
414a7e14dcfSSatish Balay - X - input vector
415a7e14dcfSSatish Balay 
416a7e14dcfSSatish Balay   Output Parameter:
417a7e14dcfSSatish Balay . f - Objective vector at X
418a7e14dcfSSatish Balay 
41995452b02SPatrick Sanan   Notes:
4204a48860cSAlp Dener     TaoComputeResidual() is typically used within minimization implementations,
421a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
422a7e14dcfSSatish Balay 
423a7e14dcfSSatish Balay   Level: advanced
424a7e14dcfSSatish Balay 
4254a48860cSAlp Dener .seealso: TaoSetResidualRoutine()
426a7e14dcfSSatish Balay @*/
4274a48860cSAlp Dener PetscErrorCode TaoComputeResidual(Tao tao, Vec X, Vec F)
428a7e14dcfSSatish Balay {
429a7e14dcfSSatish Balay   PetscErrorCode ierr;
43087f595a5SBarry Smith 
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) {
4380ebee16dSLisandro Dalcin     ierr = PetscLogEventBegin(TAO_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
4394a48860cSAlp Dener     PetscStackPush("Tao user least-squares residual evaluation routine");
4404a48860cSAlp Dener     ierr = (*tao->ops->computeresidual)(tao,X,F,tao->user_lsresP);CHKERRQ(ierr);
441a7e14dcfSSatish Balay     PetscStackPop;
4420ebee16dSLisandro Dalcin     ierr = PetscLogEventEnd(TAO_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
443a7e14dcfSSatish Balay     tao->nfuncs++;
4444a48860cSAlp Dener   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetResidualRoutine() has not been called");
4454a48860cSAlp Dener   ierr = PetscInfo(tao,"TAO least-squares residual evaluation.\n");CHKERRQ(ierr);
446a7e14dcfSSatish Balay   PetscFunctionReturn(0);
447a7e14dcfSSatish Balay }
448a7e14dcfSSatish Balay 
449a7e14dcfSSatish Balay /*@C
450a7e14dcfSSatish Balay   TaoSetGradientRoutine - Sets the gradient evaluation routine for minimization
451a7e14dcfSSatish Balay 
452441846f8SBarry Smith   Logically collective on Tao
453a7e14dcfSSatish Balay 
454a7e14dcfSSatish Balay   Input Parameter:
455441846f8SBarry Smith + tao - the Tao context
456a7e14dcfSSatish Balay . func - the gradient function
457a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the gradient evaluation
4586c23d075SBarry Smith         routine (may be NULL)
459a7e14dcfSSatish Balay 
460a7e14dcfSSatish Balay   Calling sequence of func:
461441846f8SBarry Smith $      func (Tao tao, Vec x, Vec g, void *ctx);
462a7e14dcfSSatish Balay 
463a7e14dcfSSatish Balay + x - input vector
464a7e14dcfSSatish Balay . g - gradient value (output)
465a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
466a7e14dcfSSatish Balay 
467a7e14dcfSSatish Balay   Level: beginner
468a7e14dcfSSatish Balay 
469a7e14dcfSSatish Balay .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine()
470a7e14dcfSSatish Balay @*/
471441846f8SBarry Smith PetscErrorCode TaoSetGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx)
472a7e14dcfSSatish Balay {
473a7e14dcfSSatish Balay   PetscFunctionBegin;
474441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
475a7e14dcfSSatish Balay   tao->user_gradP = ctx;
476a7e14dcfSSatish Balay   tao->ops->computegradient = func;
477a7e14dcfSSatish Balay   PetscFunctionReturn(0);
478a7e14dcfSSatish Balay }
479a7e14dcfSSatish Balay 
480a7e14dcfSSatish Balay /*@C
481a7e14dcfSSatish Balay   TaoSetObjectiveAndGradientRoutine - Sets a combined objective function and gradient evaluation routine for minimization
482a7e14dcfSSatish Balay 
483441846f8SBarry Smith   Logically collective on Tao
484a7e14dcfSSatish Balay 
485a7e14dcfSSatish Balay   Input Parameter:
486441846f8SBarry Smith + tao - the Tao context
487a7e14dcfSSatish Balay . func - the gradient function
488a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the gradient evaluation
4896c23d075SBarry Smith         routine (may be NULL)
490a7e14dcfSSatish Balay 
491a7e14dcfSSatish Balay   Calling sequence of func:
49217477c02SJason Sarich $      func (Tao tao, Vec x, PetscReal *f, Vec g, void *ctx);
493a7e14dcfSSatish Balay 
494a7e14dcfSSatish Balay + x - input vector
49517477c02SJason Sarich . f - objective value (output)
496a7e14dcfSSatish Balay . g - gradient value (output)
497a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
498a7e14dcfSSatish Balay 
499a7e14dcfSSatish Balay   Level: beginner
500a7e14dcfSSatish Balay 
501a7e14dcfSSatish Balay .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine()
502a7e14dcfSSatish Balay @*/
503441846f8SBarry Smith PetscErrorCode TaoSetObjectiveAndGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal *, Vec, void*), void *ctx)
504a7e14dcfSSatish Balay {
505a7e14dcfSSatish Balay   PetscFunctionBegin;
506441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
507a7e14dcfSSatish Balay   tao->user_objgradP = ctx;
508a7e14dcfSSatish Balay   tao->ops->computeobjectiveandgradient = func;
509a7e14dcfSSatish Balay   PetscFunctionReturn(0);
510a7e14dcfSSatish Balay }
511a7e14dcfSSatish Balay 
512a7e14dcfSSatish Balay /*@
513a7e14dcfSSatish Balay   TaoIsObjectiveDefined -- Checks to see if the user has
514a7e14dcfSSatish Balay   declared an objective-only routine.  Useful for determining when
515a7e14dcfSSatish Balay   it is appropriate to call TaoComputeObjective() or
516a7e14dcfSSatish Balay   TaoComputeObjectiveAndGradient()
517a7e14dcfSSatish Balay 
518441846f8SBarry Smith   Collective on Tao
519a7e14dcfSSatish Balay 
520a7e14dcfSSatish Balay   Input Parameter:
521441846f8SBarry Smith + tao - the Tao context
522a7e14dcfSSatish Balay - ctx - PETSC_TRUE if objective function routine is set by user,
523a7e14dcfSSatish Balay         PETSC_FALSE otherwise
524a7e14dcfSSatish Balay   Level: developer
525a7e14dcfSSatish Balay 
526a7e14dcfSSatish Balay .seealso: TaoSetObjectiveRoutine(), TaoIsGradientDefined(), TaoIsObjectiveAndGradientDefined()
527a7e14dcfSSatish Balay @*/
528441846f8SBarry Smith PetscErrorCode TaoIsObjectiveDefined(Tao tao, PetscBool *flg)
529a7e14dcfSSatish Balay {
530a7e14dcfSSatish Balay   PetscFunctionBegin;
531441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
53245cf516eSBarry Smith   if (tao->ops->computeobjective == 0) *flg = PETSC_FALSE;
53345cf516eSBarry Smith   else *flg = PETSC_TRUE;
534a7e14dcfSSatish Balay   PetscFunctionReturn(0);
535a7e14dcfSSatish Balay }
536a7e14dcfSSatish Balay 
537a7e14dcfSSatish Balay /*@
538a7e14dcfSSatish Balay   TaoIsGradientDefined -- Checks to see if the user has
539a7e14dcfSSatish Balay   declared an objective-only routine.  Useful for determining when
540a7e14dcfSSatish Balay   it is appropriate to call TaoComputeGradient() or
541a7e14dcfSSatish Balay   TaoComputeGradientAndGradient()
542a7e14dcfSSatish Balay 
543a7e14dcfSSatish Balay   Not Collective
544a7e14dcfSSatish Balay 
545a7e14dcfSSatish Balay   Input Parameter:
546441846f8SBarry Smith + tao - the Tao context
547a7e14dcfSSatish Balay - ctx - PETSC_TRUE if gradient routine is set by user, PETSC_FALSE otherwise
548a7e14dcfSSatish Balay   Level: developer
549a7e14dcfSSatish Balay 
550a7e14dcfSSatish Balay .seealso: TaoSetGradientRoutine(), TaoIsObjectiveDefined(), TaoIsObjectiveAndGradientDefined()
551a7e14dcfSSatish Balay @*/
552441846f8SBarry Smith PetscErrorCode TaoIsGradientDefined(Tao tao, PetscBool *flg)
553a7e14dcfSSatish Balay {
554a7e14dcfSSatish Balay   PetscFunctionBegin;
555441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
55645cf516eSBarry Smith   if (tao->ops->computegradient == 0) *flg = PETSC_FALSE;
55745cf516eSBarry Smith   else *flg = PETSC_TRUE;
558a7e14dcfSSatish Balay   PetscFunctionReturn(0);
559a7e14dcfSSatish Balay }
560a7e14dcfSSatish Balay 
561a7e14dcfSSatish Balay /*@
562a7e14dcfSSatish Balay   TaoIsObjectiveAndGradientDefined -- Checks to see if the user has
563a7e14dcfSSatish Balay   declared a joint objective/gradient routine.  Useful for determining when
564a7e14dcfSSatish Balay   it is appropriate to call TaoComputeObjective() or
565a7e14dcfSSatish Balay   TaoComputeObjectiveAndGradient()
566a7e14dcfSSatish Balay 
567a7e14dcfSSatish Balay   Not Collective
568a7e14dcfSSatish Balay 
569a7e14dcfSSatish Balay   Input Parameter:
570441846f8SBarry Smith + tao - the Tao context
571a7e14dcfSSatish Balay - ctx - PETSC_TRUE if objective/gradient routine is set by user, PETSC_FALSE otherwise
572a7e14dcfSSatish Balay   Level: developer
573a7e14dcfSSatish Balay 
574a7e14dcfSSatish Balay .seealso: TaoSetObjectiveAndGradientRoutine(), TaoIsObjectiveDefined(), TaoIsGradientDefined()
575a7e14dcfSSatish Balay @*/
576441846f8SBarry Smith PetscErrorCode TaoIsObjectiveAndGradientDefined(Tao tao, PetscBool *flg)
577a7e14dcfSSatish Balay {
578a7e14dcfSSatish Balay   PetscFunctionBegin;
579441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
58045cf516eSBarry Smith   if (tao->ops->computeobjectiveandgradient == 0) *flg = PETSC_FALSE;
58145cf516eSBarry Smith   else *flg = PETSC_TRUE;
582a7e14dcfSSatish Balay   PetscFunctionReturn(0);
583a7e14dcfSSatish Balay }
584