xref: /petsc/src/tao/interface/taosolver_fg.c (revision 09baa8818311ab57ae2421c1358031095c8360c0)
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 
31*09baa881SHong Zhang PetscErrorCode TaoTestGradient(Tao tao,Vec g1)
32*09baa881SHong Zhang {
33*09baa881SHong Zhang   Vec             x = tao->solution,g2,g3;
34*09baa881SHong Zhang   PetscBool       complete_print = PETSC_FALSE,test = PETSC_FALSE;
35*09baa881SHong Zhang   PetscReal       hcnorm,fdnorm,hcmax,fdmax,diffmax,diffnorm;
36*09baa881SHong Zhang   PetscScalar     dot;
37*09baa881SHong Zhang   MPI_Comm        comm;
38*09baa881SHong Zhang   PetscViewer     viewer;
39*09baa881SHong Zhang   PetscInt        tabs;
40*09baa881SHong Zhang   static PetscBool directionsprinted = PETSC_FALSE;
41*09baa881SHong Zhang   PetscErrorCode ierr;
42*09baa881SHong Zhang 
43*09baa881SHong Zhang   PetscFunctionBegin;
44*09baa881SHong Zhang   ierr = PetscObjectOptionsBegin((PetscObject)tao);CHKERRQ(ierr);
45*09baa881SHong Zhang   ierr = PetscOptionsName("-tao_test_gradient","Compare hand-coded and finite difference Gradients","None",&test);CHKERRQ(ierr);
46*09baa881SHong Zhang   ierr = PetscOptionsBool("-tao_test_gradient_view","View difference between hand-coded and finite difference Gradients element entries","None",complete_print,&complete_print,NULL);CHKERRQ(ierr);
47*09baa881SHong Zhang   ierr = PetscOptionsEnd();CHKERRQ(ierr);
48*09baa881SHong Zhang   if (!test) PetscFunctionReturn(0);
49*09baa881SHong Zhang 
50*09baa881SHong Zhang   ierr = PetscObjectGetComm((PetscObject)tao,&comm);CHKERRQ(ierr);
51*09baa881SHong Zhang   ierr = PetscViewerASCIIGetStdout(comm,&viewer);CHKERRQ(ierr);
52*09baa881SHong Zhang   ierr = PetscViewerASCIIGetTab(viewer, &tabs);CHKERRQ(ierr);
53*09baa881SHong Zhang   ierr = PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel);CHKERRQ(ierr);
54*09baa881SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  ---------- Testing Gradient -------------\n");CHKERRQ(ierr);
55*09baa881SHong Zhang   if (!complete_print && !directionsprinted) {
56*09baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  Run with -tao_test_gradient_view and optionally -tao_test_gradient <threshold> to show difference\n");CHKERRQ(ierr);
57*09baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"    of hand-coded and finite difference gradient entries greater than <threshold>.\n");CHKERRQ(ierr);
58*09baa881SHong Zhang   }
59*09baa881SHong Zhang   if (!directionsprinted) {
60*09baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  Testing hand-coded Gradient, if (for double precision runs) ||G - Gfd||_F/||G||_F is\n");CHKERRQ(ierr);
61*09baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"    O(1.e-8), the hand-coded Hessian is probably correct.\n");CHKERRQ(ierr);
62*09baa881SHong Zhang     directionsprinted = PETSC_TRUE;
63*09baa881SHong Zhang   }
64*09baa881SHong Zhang 
65*09baa881SHong Zhang   ierr = VecDuplicate(x,&g2);CHKERRQ(ierr);
66*09baa881SHong Zhang   ierr = VecDuplicate(x,&g3);CHKERRQ(ierr);
67*09baa881SHong Zhang 
68*09baa881SHong Zhang   /* Compute finite difference gradient, assume the gradient is already computed by TaoComputeGradient() and put into g1 */
69*09baa881SHong Zhang   ierr = TaoDefaultComputeGradient(tao,x,g2,NULL);CHKERRQ(ierr);
70*09baa881SHong Zhang 
71*09baa881SHong Zhang   ierr = VecNorm(g2,NORM_2,&fdnorm);CHKERRQ(ierr);
72*09baa881SHong Zhang   ierr = VecNorm(g1,NORM_2,&hcnorm);CHKERRQ(ierr);
73*09baa881SHong Zhang   ierr = VecNorm(g2,NORM_INFINITY,&fdmax);CHKERRQ(ierr);
74*09baa881SHong Zhang   ierr = VecNorm(g1,NORM_INFINITY,&hcmax);CHKERRQ(ierr);
75*09baa881SHong Zhang   ierr = VecDot(g1,g2,&dot);CHKERRQ(ierr);
76*09baa881SHong Zhang   ierr = VecCopy(g1,g3);CHKERRQ(ierr);
77*09baa881SHong Zhang   ierr = VecAXPY(g3,-1.0,g2);CHKERRQ(ierr);
78*09baa881SHong Zhang   ierr = VecNorm(g3,NORM_2,&diffnorm);CHKERRQ(ierr);
79*09baa881SHong Zhang   ierr = VecNorm(g3,NORM_INFINITY,&diffmax);CHKERRQ(ierr);
80*09baa881SHong 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);
81*09baa881SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  2-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n",(double)(diffnorm/PetscMax(hcnorm,fdnorm)),(double)diffnorm);CHKERRQ(ierr);
82*09baa881SHong Zhang   ierr = PetscViewerASCIIPrintf(viewer,"  max-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n",(double)(diffmax/PetscMax(hcmax,fdmax)),(double)diffmax);CHKERRQ(ierr);
83*09baa881SHong Zhang 
84*09baa881SHong Zhang   if (complete_print) {
85*09baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  Hand-coded gradient ----------\n");CHKERRQ(ierr);
86*09baa881SHong Zhang     ierr = VecView(g1,viewer);CHKERRQ(ierr);
87*09baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  Finite difference gradient ----------\n");CHKERRQ(ierr);
88*09baa881SHong Zhang     ierr = VecView(g2,viewer);CHKERRQ(ierr);
89*09baa881SHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"  Hand-coded minus finite-difference gradient ----------\n");CHKERRQ(ierr);
90*09baa881SHong Zhang     ierr = VecView(g3,viewer);CHKERRQ(ierr);
91*09baa881SHong Zhang   }
92*09baa881SHong Zhang   ierr = VecDestroy(&g2);CHKERRQ(ierr);
93*09baa881SHong Zhang   ierr = VecDestroy(&g3);CHKERRQ(ierr);
94*09baa881SHong Zhang   PetscFunctionReturn(0);
95*09baa881SHong Zhang }
96*09baa881SHong Zhang 
97a7e14dcfSSatish Balay /*@
98a7e14dcfSSatish Balay   TaoComputeGradient - Computes the gradient of the objective function
99a7e14dcfSSatish Balay 
100441846f8SBarry Smith   Collective on Tao
101a7e14dcfSSatish Balay 
102a7e14dcfSSatish Balay   Input Parameters:
103441846f8SBarry Smith + tao - the Tao context
104a7e14dcfSSatish Balay - X - input vector
105a7e14dcfSSatish Balay 
106a7e14dcfSSatish Balay   Output Parameter:
107a7e14dcfSSatish Balay . G - gradient vector
108a7e14dcfSSatish Balay 
109*09baa881SHong Zhang   Options Database Keys:
110*09baa881SHong Zhang +    -tao_test_gradient - compare the user provided gradient with one compute via finite differences to check for errors
111*09baa881SHong Zhang -    -tao_test_gradient_display - 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
112*09baa881SHong Zhang 
11395452b02SPatrick Sanan   Notes:
11495452b02SPatrick Sanan     TaoComputeGradient() is typically used within minimization implementations,
115a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
116a7e14dcfSSatish Balay 
117a7e14dcfSSatish Balay   Level: advanced
118a7e14dcfSSatish Balay 
119a7e14dcfSSatish Balay .seealso: TaoComputeObjective(), TaoComputeObjectiveAndGradient(), TaoSetGradientRoutine()
120a7e14dcfSSatish Balay @*/
121441846f8SBarry Smith PetscErrorCode TaoComputeGradient(Tao tao, Vec X, Vec G)
122a7e14dcfSSatish Balay {
123a7e14dcfSSatish Balay   PetscErrorCode ierr;
124a7e14dcfSSatish Balay   PetscReal      dummy;
12587f595a5SBarry Smith 
126a7e14dcfSSatish Balay   PetscFunctionBegin;
127441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
128a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
129a7e14dcfSSatish Balay   PetscValidHeaderSpecific(G,VEC_CLASSID,2);
130a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,X,2);
131a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,G,3);
132f4c1ad5cSStefano Zampini   ierr = VecLockPush(X);CHKERRQ(ierr);
133a7e14dcfSSatish Balay   if (tao->ops->computegradient) {
134441846f8SBarry Smith     ierr = PetscLogEventBegin(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr);
135441846f8SBarry Smith     PetscStackPush("Tao user gradient evaluation routine");
136a7e14dcfSSatish Balay     ierr = (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);CHKERRQ(ierr);
137a7e14dcfSSatish Balay     PetscStackPop;
138441846f8SBarry Smith     ierr = PetscLogEventEnd(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr);
139a7e14dcfSSatish Balay     tao->ngrads++;
140a7e14dcfSSatish Balay   } else if (tao->ops->computeobjectiveandgradient) {
141441846f8SBarry Smith     ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr);
142a7e14dcfSSatish Balay     PetscStackPush("Tao user objective/gradient evaluation routine");
143a7e14dcfSSatish Balay     ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,&dummy,G,tao->user_objgradP);CHKERRQ(ierr);
144a7e14dcfSSatish Balay     PetscStackPop;
145441846f8SBarry Smith     ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr);
146a7e14dcfSSatish Balay     tao->nfuncgrads++;
14787f595a5SBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetGradientRoutine() has not been called");
148f4c1ad5cSStefano Zampini   ierr = VecLockPop(X);CHKERRQ(ierr);
149*09baa881SHong Zhang 
150*09baa881SHong Zhang   ierr = TaoTestGradient(tao,G);CHKERRQ(ierr);
151a7e14dcfSSatish Balay   PetscFunctionReturn(0);
152a7e14dcfSSatish Balay }
153a7e14dcfSSatish Balay 
154a7e14dcfSSatish Balay /*@
155a7e14dcfSSatish Balay   TaoComputeObjective - Computes the objective function value at a given point
156a7e14dcfSSatish Balay 
157441846f8SBarry 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 
16695452b02SPatrick Sanan   Notes:
16795452b02SPatrick Sanan     TaoComputeObjective() is typically used within minimization implementations,
168a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
169a7e14dcfSSatish Balay 
170a7e14dcfSSatish Balay   Level: advanced
171a7e14dcfSSatish Balay 
172a7e14dcfSSatish Balay .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine()
173a7e14dcfSSatish Balay @*/
174441846f8SBarry Smith PetscErrorCode TaoComputeObjective(Tao tao, Vec X, PetscReal *f)
175a7e14dcfSSatish Balay {
176a7e14dcfSSatish Balay   PetscErrorCode ierr;
177a7e14dcfSSatish Balay   Vec            temp;
17887f595a5SBarry Smith 
179a7e14dcfSSatish Balay   PetscFunctionBegin;
180441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
181a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
182a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,X,2);
183f4c1ad5cSStefano Zampini   ierr = VecLockPush(X);CHKERRQ(ierr);
184a7e14dcfSSatish Balay   if (tao->ops->computeobjective) {
185441846f8SBarry Smith     ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
186441846f8SBarry Smith     PetscStackPush("Tao user objective evaluation routine");
187a7e14dcfSSatish Balay     ierr = (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);CHKERRQ(ierr);
188a7e14dcfSSatish Balay     PetscStackPop;
189441846f8SBarry Smith     ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
190a7e14dcfSSatish Balay     tao->nfuncs++;
191a7e14dcfSSatish Balay   } else if (tao->ops->computeobjectiveandgradient) {
192955c1f14SBarry Smith     ierr = PetscInfo(tao,"Duplicating variable vector in order to call func/grad routine\n");CHKERRQ(ierr);
193a7e14dcfSSatish Balay     ierr = VecDuplicate(X,&temp);CHKERRQ(ierr);
194441846f8SBarry Smith     ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,NULL,NULL);CHKERRQ(ierr);
195441846f8SBarry Smith     PetscStackPush("Tao user objective/gradient evaluation routine");
196a7e14dcfSSatish Balay     ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,f,temp,tao->user_objgradP);CHKERRQ(ierr);
197a7e14dcfSSatish Balay     PetscStackPop;
198441846f8SBarry Smith     ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,NULL,NULL);CHKERRQ(ierr);
199a7e14dcfSSatish Balay     ierr = VecDestroy(&temp);CHKERRQ(ierr);
200a7e14dcfSSatish Balay     tao->nfuncgrads++;
20187f595a5SBarry Smith   }  else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() has not been called");
202e356b196STodd Munson   ierr = PetscInfo1(tao,"TAO Function evaluation: %20.19e\n",(double)(*f));CHKERRQ(ierr);
203f4c1ad5cSStefano Zampini   ierr = VecLockPop(X);CHKERRQ(ierr);
204a7e14dcfSSatish Balay   PetscFunctionReturn(0);
205a7e14dcfSSatish Balay }
206a7e14dcfSSatish Balay 
207a7e14dcfSSatish Balay /*@
208a7e14dcfSSatish Balay   TaoComputeObjectiveAndGradient - Computes the objective function value at a given point
209a7e14dcfSSatish Balay 
210441846f8SBarry Smith   Collective on Tao
211a7e14dcfSSatish Balay 
212a7e14dcfSSatish Balay   Input Parameters:
213441846f8SBarry Smith + tao - the Tao context
214a7e14dcfSSatish Balay - X - input vector
215a7e14dcfSSatish Balay 
216a7e14dcfSSatish Balay   Output Parameter:
217a7e14dcfSSatish Balay + f - Objective value at X
218a7e14dcfSSatish Balay - g - Gradient vector at X
219a7e14dcfSSatish Balay 
22095452b02SPatrick Sanan   Notes:
22195452b02SPatrick Sanan     TaoComputeObjectiveAndGradient() is typically used within minimization implementations,
222a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
223a7e14dcfSSatish Balay 
224a7e14dcfSSatish Balay   Level: advanced
225a7e14dcfSSatish Balay 
226a7e14dcfSSatish Balay .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine()
227a7e14dcfSSatish Balay @*/
228441846f8SBarry Smith PetscErrorCode TaoComputeObjectiveAndGradient(Tao tao, Vec X, PetscReal *f, Vec G)
229a7e14dcfSSatish Balay {
230a7e14dcfSSatish Balay   PetscErrorCode ierr;
23187f595a5SBarry Smith 
232a7e14dcfSSatish Balay   PetscFunctionBegin;
233441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
234a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
235a7e14dcfSSatish Balay   PetscValidHeaderSpecific(G,VEC_CLASSID,4);
236a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,X,2);
237a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,G,4);
238f4c1ad5cSStefano Zampini   ierr = VecLockPush(X);CHKERRQ(ierr);
239a7e14dcfSSatish Balay   if (tao->ops->computeobjectiveandgradient) {
240441846f8SBarry Smith     ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr);
241f4c1ad5cSStefano Zampini     if (tao->ops->computegradient == TaoDefaultComputeGradient) {
242f4c1ad5cSStefano Zampini       ierr = TaoComputeObjective(tao,X,f);CHKERRQ(ierr);
243f4c1ad5cSStefano Zampini       ierr = TaoDefaultComputeGradient(tao,X,G,NULL);CHKERRQ(ierr);
244f4c1ad5cSStefano Zampini     } else {
245441846f8SBarry Smith       PetscStackPush("Tao user objective/gradient evaluation routine");
246a7e14dcfSSatish Balay       ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,f,G,tao->user_objgradP);CHKERRQ(ierr);
2470cbffdbaSBarry Smith       PetscStackPop;
248a7e14dcfSSatish Balay     }
249441846f8SBarry Smith     ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr);
250a7e14dcfSSatish Balay     tao->nfuncgrads++;
251a7e14dcfSSatish Balay   } else if (tao->ops->computeobjective && tao->ops->computegradient) {
252441846f8SBarry Smith     ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
253441846f8SBarry Smith     PetscStackPush("Tao user objective evaluation routine");
254a7e14dcfSSatish Balay     ierr = (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);CHKERRQ(ierr);
255a7e14dcfSSatish Balay     PetscStackPop;
256441846f8SBarry Smith     ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
257a7e14dcfSSatish Balay     tao->nfuncs++;
258441846f8SBarry Smith     ierr = PetscLogEventBegin(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr);
259441846f8SBarry Smith     PetscStackPush("Tao user gradient evaluation routine");
260a7e14dcfSSatish Balay     ierr = (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);CHKERRQ(ierr);
261a7e14dcfSSatish Balay     PetscStackPop;
262441846f8SBarry Smith     ierr = PetscLogEventEnd(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr);
263a7e14dcfSSatish Balay     tao->ngrads++;
26487f595a5SBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() or TaoSetGradientRoutine() not set");
265e356b196STodd Munson   ierr = PetscInfo1(tao,"TAO Function evaluation: %20.19e\n",(double)(*f));CHKERRQ(ierr);
266f4c1ad5cSStefano Zampini   ierr = VecLockPop(X);CHKERRQ(ierr);
267a7e14dcfSSatish Balay   PetscFunctionReturn(0);
268a7e14dcfSSatish Balay }
269a7e14dcfSSatish Balay 
270a7e14dcfSSatish Balay /*@C
271a7e14dcfSSatish Balay   TaoSetObjectiveRoutine - Sets the function evaluation routine for minimization
272a7e14dcfSSatish Balay 
273441846f8SBarry Smith   Logically collective on Tao
274a7e14dcfSSatish Balay 
275a7e14dcfSSatish Balay   Input Parameter:
276441846f8SBarry Smith + tao - the Tao context
277a7e14dcfSSatish Balay . func - the objective function
278a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the function evaluation
2796c23d075SBarry Smith         routine (may be NULL)
280a7e14dcfSSatish Balay 
281a7e14dcfSSatish Balay   Calling sequence of func:
282441846f8SBarry Smith $      func (Tao tao, Vec x, PetscReal *f, void *ctx);
283a7e14dcfSSatish Balay 
284a7e14dcfSSatish Balay + x - input vector
285a7e14dcfSSatish Balay . f - function value
286a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
287a7e14dcfSSatish Balay 
288a7e14dcfSSatish Balay   Level: beginner
289a7e14dcfSSatish Balay 
290a7e14dcfSSatish Balay .seealso: TaoSetGradientRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine()
291a7e14dcfSSatish Balay @*/
292441846f8SBarry Smith PetscErrorCode TaoSetObjectiveRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal*,void*),void *ctx)
293a7e14dcfSSatish Balay {
294a7e14dcfSSatish Balay   PetscFunctionBegin;
295441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
296a7e14dcfSSatish Balay   tao->user_objP = ctx;
297a7e14dcfSSatish Balay   tao->ops->computeobjective = func;
298a7e14dcfSSatish Balay   PetscFunctionReturn(0);
299a7e14dcfSSatish Balay }
300a7e14dcfSSatish Balay 
301a7e14dcfSSatish Balay /*@C
302a7e14dcfSSatish Balay   TaoSetSeparableObjectiveRoutine - Sets the function evaluation routine for least-square applications
303a7e14dcfSSatish Balay 
304441846f8SBarry Smith   Logically collective on Tao
305a7e14dcfSSatish Balay 
306a7e14dcfSSatish Balay   Input Parameter:
307441846f8SBarry Smith + tao - the Tao context
308a7e14dcfSSatish Balay . func - the objective function evaluation routine
309a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the function evaluation
3106c23d075SBarry Smith         routine (may be NULL)
311a7e14dcfSSatish Balay 
312a7e14dcfSSatish Balay   Calling sequence of func:
313441846f8SBarry Smith $      func (Tao tao, Vec x, Vec f, void *ctx);
314a7e14dcfSSatish Balay 
315a7e14dcfSSatish Balay + x - input vector
316a7e14dcfSSatish Balay . f - function value vector
317a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
318a7e14dcfSSatish Balay 
319a7e14dcfSSatish Balay   Level: beginner
320a7e14dcfSSatish Balay 
321a7e14dcfSSatish Balay .seealso: TaoSetObjectiveRoutine(), TaoSetJacobianRoutine()
322a7e14dcfSSatish Balay @*/
323441846f8SBarry Smith PetscErrorCode TaoSetSeparableObjectiveRoutine(Tao tao, Vec sepobj, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx)
324a7e14dcfSSatish Balay {
325a7e14dcfSSatish Balay   PetscFunctionBegin;
326441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
327a7e14dcfSSatish Balay   PetscValidHeaderSpecific(sepobj, VEC_CLASSID,2);
328a7e14dcfSSatish Balay   tao->user_sepobjP = ctx;
329a7e14dcfSSatish Balay   tao->sep_objective = sepobj;
330a7e14dcfSSatish Balay   tao->ops->computeseparableobjective = func;
331a7e14dcfSSatish Balay   PetscFunctionReturn(0);
332a7e14dcfSSatish Balay }
333a7e14dcfSSatish Balay 
3348b7a9b22SJason Sarich /*@
3358b7a9b22SJason Sarich   TaoSetSeparableObjectiveWeights - Give weights for the separable objective 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.
3368b7a9b22SJason Sarich 
3378b7a9b22SJason Sarich   Collective on Tao
3388b7a9b22SJason Sarich 
3398b7a9b22SJason Sarich   Input Parameters:
3408b7a9b22SJason Sarich + tao - the Tao context
3418b7a9b22SJason Sarich . sigma_v - vector of weights (diagonal terms only)
3428b7a9b22SJason Sarich . n       - the number of weights (if using off-diagonal)
3438b7a9b22SJason Sarich . rows    - index list of rows for sigma_w
3448b7a9b22SJason Sarich . cols    - index list of columns for sigma_w
3458b7a9b22SJason Sarich - vals - array of weights
3468b7a9b22SJason Sarich 
3478b7a9b22SJason Sarich 
3488b7a9b22SJason Sarich 
3498b7a9b22SJason Sarich   Note: Either sigma_v or sigma_w (or both) should be NULL
3508b7a9b22SJason Sarich 
3518b7a9b22SJason Sarich   Level: intermediate
3528b7a9b22SJason Sarich 
3538b7a9b22SJason Sarich .seealso: TaoSetSeparableObjectiveRoutine()
3548b7a9b22SJason Sarich @*/
3558b7a9b22SJason Sarich PetscErrorCode TaoSetSeparableObjectiveWeights(Tao tao, Vec sigma_v, PetscInt n, PetscInt *rows, PetscInt *cols, PetscReal *vals)
3568b7a9b22SJason Sarich {
3578b7a9b22SJason Sarich   PetscErrorCode ierr;
3588b7a9b22SJason Sarich   PetscInt       i;
3598b7a9b22SJason Sarich   PetscFunctionBegin;
3608b7a9b22SJason Sarich   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
3618b7a9b22SJason Sarich   ierr = VecDestroy(&tao->sep_weights_v);CHKERRQ(ierr);
3628b7a9b22SJason Sarich   tao->sep_weights_v=sigma_v;
3638b7a9b22SJason Sarich   if (sigma_v) {
3648b7a9b22SJason Sarich     ierr = PetscObjectReference((PetscObject)sigma_v);CHKERRQ(ierr);
3658b7a9b22SJason Sarich   }
3668b7a9b22SJason Sarich   if (vals) {
3678b7a9b22SJason Sarich     if (tao->sep_weights_n) {
3688b7a9b22SJason Sarich       ierr = PetscFree(tao->sep_weights_rows);CHKERRQ(ierr);
3698b7a9b22SJason Sarich       ierr = PetscFree(tao->sep_weights_cols);CHKERRQ(ierr);
3708b7a9b22SJason Sarich       ierr = PetscFree(tao->sep_weights_w);CHKERRQ(ierr);
3718b7a9b22SJason Sarich     }
3728b7a9b22SJason Sarich     ierr = PetscMalloc1(n,&tao->sep_weights_rows);CHKERRQ(ierr);
3738b7a9b22SJason Sarich     ierr = PetscMalloc1(n,&tao->sep_weights_cols);CHKERRQ(ierr);
3748b7a9b22SJason Sarich     ierr = PetscMalloc1(n,&tao->sep_weights_w);CHKERRQ(ierr);
3758b7a9b22SJason Sarich     tao->sep_weights_n=n;
3768b7a9b22SJason Sarich     for (i=0;i<n;i++) {
3778b7a9b22SJason Sarich       tao->sep_weights_rows[i]=rows[i];
3788b7a9b22SJason Sarich       tao->sep_weights_cols[i]=cols[i];
3798b7a9b22SJason Sarich       tao->sep_weights_w[i]=vals[i];
3808b7a9b22SJason Sarich     }
3818b7a9b22SJason Sarich   } else {
3828b7a9b22SJason Sarich     tao->sep_weights_n=0;
3838b7a9b22SJason Sarich     tao->sep_weights_rows=0;
3848b7a9b22SJason Sarich     tao->sep_weights_cols=0;
3858b7a9b22SJason Sarich   }
3868b7a9b22SJason Sarich   PetscFunctionReturn(0);
3878b7a9b22SJason Sarich }
388a7e14dcfSSatish Balay /*@
389a7e14dcfSSatish Balay   TaoComputeSeparableObjective - Computes a separable objective function vector at a given point (for least-square applications)
390a7e14dcfSSatish Balay 
391441846f8SBarry Smith   Collective on Tao
392a7e14dcfSSatish Balay 
393a7e14dcfSSatish Balay   Input Parameters:
394441846f8SBarry Smith + tao - the Tao context
395a7e14dcfSSatish Balay - X - input vector
396a7e14dcfSSatish Balay 
397a7e14dcfSSatish Balay   Output Parameter:
398a7e14dcfSSatish Balay . f - Objective vector at X
399a7e14dcfSSatish Balay 
40095452b02SPatrick Sanan   Notes:
40195452b02SPatrick Sanan     TaoComputeSeparableObjective() is typically used within minimization implementations,
402a7e14dcfSSatish Balay   so most users would not generally call this routine themselves.
403a7e14dcfSSatish Balay 
404a7e14dcfSSatish Balay   Level: advanced
405a7e14dcfSSatish Balay 
406a7e14dcfSSatish Balay .seealso: TaoSetSeparableObjectiveRoutine()
407a7e14dcfSSatish Balay @*/
408441846f8SBarry Smith PetscErrorCode TaoComputeSeparableObjective(Tao tao, Vec X, Vec F)
409a7e14dcfSSatish Balay {
410a7e14dcfSSatish Balay   PetscErrorCode ierr;
41187f595a5SBarry Smith 
412a7e14dcfSSatish Balay   PetscFunctionBegin;
413441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
414a7e14dcfSSatish Balay   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
415a7e14dcfSSatish Balay   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
416a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,X,2);
417a7e14dcfSSatish Balay   PetscCheckSameComm(tao,1,F,3);
418a7e14dcfSSatish Balay   if (tao->ops->computeseparableobjective) {
419441846f8SBarry Smith     ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
420441846f8SBarry Smith     PetscStackPush("Tao user separable objective evaluation routine");
421a7e14dcfSSatish Balay     ierr = (*tao->ops->computeseparableobjective)(tao,X,F,tao->user_sepobjP);CHKERRQ(ierr);
422a7e14dcfSSatish Balay     PetscStackPop;
423441846f8SBarry Smith     ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
424a7e14dcfSSatish Balay     tao->nfuncs++;
42587f595a5SBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetSeparableObjectiveRoutine() has not been called");
426a7e14dcfSSatish Balay   ierr = PetscInfo(tao,"TAO separable function evaluation.\n");CHKERRQ(ierr);
427a7e14dcfSSatish Balay   PetscFunctionReturn(0);
428a7e14dcfSSatish Balay }
429a7e14dcfSSatish Balay 
430a7e14dcfSSatish Balay /*@C
431a7e14dcfSSatish Balay   TaoSetGradientRoutine - Sets the gradient evaluation routine for minimization
432a7e14dcfSSatish Balay 
433441846f8SBarry Smith   Logically collective on Tao
434a7e14dcfSSatish Balay 
435a7e14dcfSSatish Balay   Input Parameter:
436441846f8SBarry Smith + tao - the Tao context
437a7e14dcfSSatish Balay . func - the gradient function
438a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the gradient evaluation
4396c23d075SBarry Smith         routine (may be NULL)
440a7e14dcfSSatish Balay 
441a7e14dcfSSatish Balay   Calling sequence of func:
442441846f8SBarry Smith $      func (Tao tao, Vec x, Vec g, void *ctx);
443a7e14dcfSSatish Balay 
444a7e14dcfSSatish Balay + x - input vector
445a7e14dcfSSatish Balay . g - gradient value (output)
446a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
447a7e14dcfSSatish Balay 
448a7e14dcfSSatish Balay   Level: beginner
449a7e14dcfSSatish Balay 
450a7e14dcfSSatish Balay .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine()
451a7e14dcfSSatish Balay @*/
452441846f8SBarry Smith PetscErrorCode TaoSetGradientRoutine(Tao tao,  PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx)
453a7e14dcfSSatish Balay {
454a7e14dcfSSatish Balay   PetscFunctionBegin;
455441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
456a7e14dcfSSatish Balay   tao->user_gradP = ctx;
457a7e14dcfSSatish Balay   tao->ops->computegradient = func;
458a7e14dcfSSatish Balay   PetscFunctionReturn(0);
459a7e14dcfSSatish Balay }
460a7e14dcfSSatish Balay 
461a7e14dcfSSatish Balay /*@C
462a7e14dcfSSatish Balay   TaoSetObjectiveAndGradientRoutine - Sets a combined objective function and gradient evaluation routine for minimization
463a7e14dcfSSatish Balay 
464441846f8SBarry Smith   Logically collective on Tao
465a7e14dcfSSatish Balay 
466a7e14dcfSSatish Balay   Input Parameter:
467441846f8SBarry Smith + tao - the Tao context
468a7e14dcfSSatish Balay . func - the gradient function
469a7e14dcfSSatish Balay - ctx - [optional] user-defined context for private data for the gradient evaluation
4706c23d075SBarry Smith         routine (may be NULL)
471a7e14dcfSSatish Balay 
472a7e14dcfSSatish Balay   Calling sequence of func:
47317477c02SJason Sarich $      func (Tao tao, Vec x, PetscReal *f, Vec g, void *ctx);
474a7e14dcfSSatish Balay 
475a7e14dcfSSatish Balay + x - input vector
47617477c02SJason Sarich . f - objective value (output)
477a7e14dcfSSatish Balay . g - gradient value (output)
478a7e14dcfSSatish Balay - ctx - [optional] user-defined function context
479a7e14dcfSSatish Balay 
480a7e14dcfSSatish Balay   Level: beginner
481a7e14dcfSSatish Balay 
482a7e14dcfSSatish Balay .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine()
483a7e14dcfSSatish Balay @*/
484441846f8SBarry Smith PetscErrorCode TaoSetObjectiveAndGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal *, Vec, void*), void *ctx)
485a7e14dcfSSatish Balay {
486a7e14dcfSSatish Balay   PetscFunctionBegin;
487441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
488a7e14dcfSSatish Balay   tao->user_objgradP = ctx;
489a7e14dcfSSatish Balay   tao->ops->computeobjectiveandgradient = func;
490a7e14dcfSSatish Balay   PetscFunctionReturn(0);
491a7e14dcfSSatish Balay }
492a7e14dcfSSatish Balay 
493a7e14dcfSSatish Balay /*@
494a7e14dcfSSatish Balay   TaoIsObjectiveDefined -- Checks to see if the user has
495a7e14dcfSSatish Balay   declared an objective-only routine.  Useful for determining when
496a7e14dcfSSatish Balay   it is appropriate to call TaoComputeObjective() or
497a7e14dcfSSatish Balay   TaoComputeObjectiveAndGradient()
498a7e14dcfSSatish Balay 
499441846f8SBarry Smith   Collective on Tao
500a7e14dcfSSatish Balay 
501a7e14dcfSSatish Balay   Input Parameter:
502441846f8SBarry Smith + tao - the Tao context
503a7e14dcfSSatish Balay - ctx - PETSC_TRUE if objective function routine is set by user,
504a7e14dcfSSatish Balay         PETSC_FALSE otherwise
505a7e14dcfSSatish Balay   Level: developer
506a7e14dcfSSatish Balay 
507a7e14dcfSSatish Balay .seealso: TaoSetObjectiveRoutine(), TaoIsGradientDefined(), TaoIsObjectiveAndGradientDefined()
508a7e14dcfSSatish Balay @*/
509441846f8SBarry Smith PetscErrorCode TaoIsObjectiveDefined(Tao tao, PetscBool *flg)
510a7e14dcfSSatish Balay {
511a7e14dcfSSatish Balay   PetscFunctionBegin;
512441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
51345cf516eSBarry Smith   if (tao->ops->computeobjective == 0) *flg = PETSC_FALSE;
51445cf516eSBarry Smith   else *flg = PETSC_TRUE;
515a7e14dcfSSatish Balay   PetscFunctionReturn(0);
516a7e14dcfSSatish Balay }
517a7e14dcfSSatish Balay 
518a7e14dcfSSatish Balay /*@
519a7e14dcfSSatish Balay   TaoIsGradientDefined -- Checks to see if the user has
520a7e14dcfSSatish Balay   declared an objective-only routine.  Useful for determining when
521a7e14dcfSSatish Balay   it is appropriate to call TaoComputeGradient() or
522a7e14dcfSSatish Balay   TaoComputeGradientAndGradient()
523a7e14dcfSSatish Balay 
524a7e14dcfSSatish Balay   Not Collective
525a7e14dcfSSatish Balay 
526a7e14dcfSSatish Balay   Input Parameter:
527441846f8SBarry Smith + tao - the Tao context
528a7e14dcfSSatish Balay - ctx - PETSC_TRUE if gradient routine is set by user, PETSC_FALSE otherwise
529a7e14dcfSSatish Balay   Level: developer
530a7e14dcfSSatish Balay 
531a7e14dcfSSatish Balay .seealso: TaoSetGradientRoutine(), TaoIsObjectiveDefined(), TaoIsObjectiveAndGradientDefined()
532a7e14dcfSSatish Balay @*/
533441846f8SBarry Smith PetscErrorCode TaoIsGradientDefined(Tao tao, PetscBool *flg)
534a7e14dcfSSatish Balay {
535a7e14dcfSSatish Balay   PetscFunctionBegin;
536441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
53745cf516eSBarry Smith   if (tao->ops->computegradient == 0) *flg = PETSC_FALSE;
53845cf516eSBarry Smith   else *flg = PETSC_TRUE;
539a7e14dcfSSatish Balay   PetscFunctionReturn(0);
540a7e14dcfSSatish Balay }
541a7e14dcfSSatish Balay 
542a7e14dcfSSatish Balay /*@
543a7e14dcfSSatish Balay   TaoIsObjectiveAndGradientDefined -- Checks to see if the user has
544a7e14dcfSSatish Balay   declared a joint objective/gradient routine.  Useful for determining when
545a7e14dcfSSatish Balay   it is appropriate to call TaoComputeObjective() or
546a7e14dcfSSatish Balay   TaoComputeObjectiveAndGradient()
547a7e14dcfSSatish Balay 
548a7e14dcfSSatish Balay   Not Collective
549a7e14dcfSSatish Balay 
550a7e14dcfSSatish Balay   Input Parameter:
551441846f8SBarry Smith + tao - the Tao context
552a7e14dcfSSatish Balay - ctx - PETSC_TRUE if objective/gradient routine is set by user, PETSC_FALSE otherwise
553a7e14dcfSSatish Balay   Level: developer
554a7e14dcfSSatish Balay 
555a7e14dcfSSatish Balay .seealso: TaoSetObjectiveAndGradientRoutine(), TaoIsObjectiveDefined(), TaoIsGradientDefined()
556a7e14dcfSSatish Balay @*/
557441846f8SBarry Smith PetscErrorCode TaoIsObjectiveAndGradientDefined(Tao tao, PetscBool *flg)
558a7e14dcfSSatish Balay {
559a7e14dcfSSatish Balay   PetscFunctionBegin;
560441846f8SBarry Smith   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
56145cf516eSBarry Smith   if (tao->ops->computeobjectiveandgradient == 0) *flg = PETSC_FALSE;
56245cf516eSBarry Smith   else *flg = PETSC_TRUE;
563a7e14dcfSSatish Balay   PetscFunctionReturn(0);
564a7e14dcfSSatish Balay }
565