Actual source code: tao_app_fg.c
1: #include "tao_app_impl.h" /*I "tao.h" I*/
2: #include "src/petsctao/include/taopetsc.h"
9: /*@C
10: TaoAppSetObjectiveRoutine - Sets a routine that evaluates the function at
11: the specified point.
13: Collective on TAO_APPLICATION
15: Input Parameters:
16: + taoapp - the TAO_APPLICATION context
17: . func - function evaluation routine
18: - ctx - [optional] user-defined context for private data for the
19: function and gradient evaluation routine (may be TAO_NULL)
21: Calling sequence of func:
22: $ func (TAO_APPLICATION taoapp, Vec x,double *f,void *ctx);
24: + taoapp - the TAO_APPLICATION context
25: . x - input vector
26: . f - objective function value
27: - ctx - [optional] user-defined function context
29: Note:
30: Most applications do not need this routine. The routine
31: TaoAppSetObjectiveFunctionGradient() is sufficient.
33: Level: intermediate
35: .keywords: TAO_APPLICATION, set, minimization, function
37: .seealso: TaoAppSetHessianRoutine(), TaoAppSetObjectiveAndGradientRoutine(), TaoAppSetInitialSolutionVec()
38: @*/
39: int TaoAppSetObjectiveRoutine(TAO_APPLICATION taoapp, int (*func)(TAO_APPLICATION,Vec,double*,void*),void *ctx){
42: taoapp->computeumfunction=func;
43: taoapp->usrfctx=ctx;
44: return(0);
45: }
49: /*@
50: TaoAppComputeObjective - Compute the objective function that has been
51: set with TaoAppSetObjectiveRoutine().
53: Collective on TAO_APPLICATION
55: Input Parameters:
56: + taopp - the TAO_APPLICATION context
57: - X - the point where the objective should be evaluated
59: Output Parameter:
60: . f - function value
62: Level: developer
64: .keywords: TAO_APPLICATION, objective
66: .seealso: TaoAppComputeGradient(), TaoAppComputeObjectiveAndGradient()
67: @*/
68: int TaoAppComputeObjective(TAO_APPLICATION taoapp, Vec X, double *f){
69: int info;
70: Vec G;
71:
75: PetscStackPush("TAO User minimization function");
76: info = PetscLogEventBegin(Tao_ObjectiveEval,taoapp,X,0,0);
77: if (taoapp->computeumfunction){
78: info = (*taoapp->computeumfunction)(taoapp,X,f,taoapp->usrfctx); CHKERRQ(info);
79: } else if (taoapp->computefunctiongradient){
80: info = VecDuplicate(X,&G);CHKERRQ(info);
81: info = (*taoapp->computefunctiongradient)(taoapp,X,f,G,taoapp->usrfgctx);
82: CHKERRQ(info);
83: info=VecDestroy(G);CHKERRQ(info);
84: taoapp->ngeval++;
85: } else {
86: SETERRQ(1,"TAO ERROR: Must set Objective function");
87: }
88: taoapp->nfeval++;
89: info = PetscLogEventEnd(Tao_ObjectiveEval,taoapp,X,0,0);
90: PetscStackPop;
91: info = PetscInfo1(taoapp,"TAO Function evaluation: %14.12e\n",*f);CHKERRQ(info);
92: return(0);
93: }
98: /*@C
99: TaoAppSetGradientRoutine - Sets the gradient evaluation routine
100: for use by the TAO_APPLICATION routines.
102: Collective on TAO_APPLICATION
104: Input Parameters:
105: + taoapp - the TAO_APPLICATION context
106: . grad - gradient evaluation routine
107: - ctx - [optional] user-defined function context
109: Calling sequence of func:
110: $ grad (TAO_APPLICATION taoapp,Vec x,Vec g,void *ctx);
112: + taoapp - the TAO_APPLICATION context
113: . x - input vector
114: . g - gradient vector
115: - ctx - user-defined function gradient context set from TaoAppSetGradientRoutine()
117: Level: intermediate
119: Options Database Keys:
120: . -tao_view_gradient - view the gradient after each evaluation using PETSC_VIEWER_STDOUT_WORLD
122: Note:
123: In most cases, the routine TaoAppSetObjectiveAndGradientRoutine() is more appropriate. However,
124: when using finite differences to compute the Hessian, setting this routine can be
125: beneficial.
127: .keywords: TAO_APPLICATION, set, gradient
129: .seealso: TaoAppGetGradientVec(), TaoAppSetObjectiveAndGradientRoutine(), TaoAppSetHessianRoutine()
131: @*/
132: int TaoAppSetGradientRoutine(TAO_APPLICATION taoapp, int (*grad)(TAO_APPLICATION,Vec,Vec,void*),void *ctx){
135: taoapp->computegradient=grad;
136: taoapp->usrgctx=ctx;
137: return(0);
138: }
143: /*@
144: TaoAppComputeGradient - Compute the gradient of the objective function using the
145: routine set by TaoApplicationSetGradientRoutine().
147: Collective on TAO_APPLICATION
149: Input Parameters:
150: + taopp - the TAO_APPLICATION context
151: - X - the point where the objective should be evaluated
153: Output Parameter:
154: . f - function value
156: Level: developer
158: .keywords: TAO_APPLICATION, objective
160: .seealso: TaoAppComputeGradient(), TaoAppComputeObjectiveAndGradient()
161: @*/
162: int TaoAppComputeGradient(TAO_APPLICATION taoapp, Vec X, Vec G){
163: int info;
164: double ff;
170: PetscStackPush("TAO User Gradient Evaluation");
171: info = PetscLogEventBegin(Tao_GradientEval,taoapp,X,G,0);
172: if (taoapp->computegradient){
173: info = (*taoapp->computegradient)(taoapp,X,G,taoapp->usrgctx);
174: CHKERRQ(info);
175: } else if ( taoapp->computefunctiongradient ) {
176: info = (*taoapp->computefunctiongradient)(taoapp,X,&ff,G,taoapp->usrfgctx);
177: CHKERRQ(info);
178: taoapp->nfeval++;
179: } else {
180: SETERRQ(1,"TAO ERROR: Must set gradient");
181: }
182: taoapp->ngeval++;
183: info = PetscLogEventEnd(Tao_GradientEval,taoapp,X,G,0);
184: PetscStackPop;
185: return(0);
186: }
192: /*@
193: TaoAppComputeObjectiveAndGradient - Compute the gradient of the objective function using the
194: routine set by TaoApplicationSetGradientRoutine().
196: Collective on TAO_APPLICATION
198: Input Parameters:
199: + taopp - the TAO_APPLICATION context
200: - X - the point where the objective should be evaluated
202: Output Parameter:
203: + f - function value
204: - G - the gradient vector.
206: Level: developer
208: .keywords: TAO_APPLICATION, objective
210: .seealso: TaoAppComputeGradient(), TaoAppSetObjectiveAndGradientRoutine()
211: @*/
212: int TaoAppComputeObjectiveAndGradient(TAO_APPLICATION taoapp, Vec X, double *f, Vec G){
213: int info;
218: PetscStackPush("TAO User Objective and gradient function");
219: if (taoapp->computefunctiongradient){
220: info = PetscLogEventBegin(Tao_GradientEval,taoapp,X,G,0);CHKERRQ(info);
221: info = PetscLogEventBegin(Tao_ObjectiveEval,taoapp,X,G,0);
222: info = (*taoapp->computefunctiongradient)(taoapp,X,f,G,taoapp->usrfgctx);
223: CHKERRQ(info);
224: info = PetscLogEventEnd(Tao_ObjectiveEval,taoapp,X,G,0);CHKERRQ(info);
226: if (taoapp->computegradient) {
227: info = PetscInfo(taoapp,"Computing gradient routine separately, ignoring gradient calculated in function/gradient evaluation routine."); CHKERRQ(info);
228: info = (*taoapp->computegradient)(taoapp,X,G,taoapp->usrfgctx);
229: CHKERRQ(info);
230: }
231: info = PetscLogEventEnd(Tao_GradientEval,taoapp,X,G,0);CHKERRQ(info);
232: } else if ( taoapp->computeumfunction && taoapp->computegradient ) {
233: info = PetscLogEventBegin(Tao_ObjectiveEval,taoapp,X,G,0);
234: info = (*taoapp->computeumfunction)(taoapp,X,f,taoapp->usrfctx);
235: CHKERRQ(info);
236: info = PetscLogEventEnd(Tao_ObjectiveEval,taoapp,X,G,0);CHKERRQ(info);
237: info = PetscLogEventBegin(Tao_GradientEval,taoapp,X,G,0);CHKERRQ(info);
238: info = (*taoapp->computegradient)(taoapp,X,G,taoapp->usrgctx);
239: CHKERRQ(info);
240: info = PetscLogEventEnd(Tao_GradientEval,taoapp,X,G,0);CHKERRQ(info);
241: } else {
242: SETERRQ(1,"TAO ERROR: Must set objective function and gradient.");
243: }
244: info = PetscInfo1(taoapp,"TAO Function evaluation: %14.12e\n",*f);CHKERRQ(info);
245: taoapp->nfeval++;
246: taoapp->ngeval++;
248: PetscStackPop;
249: return(0);
250: }
252:
256: /*@C
257: TaoAppSetObjectiveAndGradientRoutine - Sets a routine for function and gradient evaluation.
259: Collective on TAO_APPLICATION
261: Input Parameters:
262: + taoapp - the TAO_APPLICATION context
263: . funcgrad - routine for evaluating the function and gradient
264: - ctx - optional user-defined context for private data for the
265: function and gradient evaluation routine (may be TAO_NULL)
267: Calling sequence of funcgrad:
268: $ funcgrad (TAO_APPLICATION tao,Vec x,double *f,Vec g,void *ctx);
270: + tao - TAO_APPLICATION context
271: . x - input vector
272: . f - function value
273: . g - gradient vector
274: - ctx - optional user-defined context
276: Notes:
277: The user may call TaoAppSetObjectiveAndGradientRoutine() to set a routine
278: that evaluates both the function and gradient. Alternatively, the
279: user may call both TaoAppSetObjectiveRoutine() and TaoAppSetGradientRoutine() to set
280: separate routines for function and gradient evaluation.
282: Using a single routine to compute the function and gradient, as
283: specified via TaoAppSetObjectiveAndGradientRoutine(), may enable better performance
284: for applications in which many of the function and gradient computations
285: are identical.
287: Fortran Note:
288: If your Fortran compiler does not recognize symbols over 31 characters in length, then
289: use the identical routine with the shortened name TaoAppSetObjectiveAndGradientRo()
292: Level: beginner
294: Options Database Keys:
295: . -tao_view_gradient - view the gradient after each iteration using PETSC_VIEWER_STDOUT_WORLD
297: .keywords: TAO_APPLICATION, set, objective, gradient
299: .seealso: TaoAppComputeObjectiveAndGradient()
301: @*/
302: int TaoAppSetObjectiveAndGradientRoutine(TAO_APPLICATION taoapp, int (*funcgrad)(TAO_APPLICATION,Vec,double*,Vec, void*),void *ctx){
305: taoapp->computefunctiongradient=funcgrad;
306: taoapp->usrfgctx=ctx;
307: return(0);
308: }
314: /*@C
315: TaoAppComputeHessian - Compute the Hessian of the objective function using the
316: routine set by TaoApplicationSetGradientRoutine().
318: Collective on TAO_APPLICATION
320: Input Parameters:
321: + taopp - the TAO_APPLICATION context
322: . X - the variable vector
323: . H - the Hessian matrix
324: . HP - the preconditioner for the Hessian matrix.
325: - flag - flag used in KSPSetOperators()
327: Output Parameter:
328: + H - the Hessian matrix
329: . HP - the preconditioner for the Hessian matrix.
330: - flag - flag used in KSPSetOperators()
332: Level: developer
334: .keywords: TAO_APPLICATION, objective
336: .seealso: TaoAppComputeObjectiveAndGradient()
337: @*/
338: int TaoAppComputeHessian(TAO_APPLICATION taoapp, Vec X, Mat *HH, Mat *HHPre, MatStructure *flag){
339: int info;
340: Mat H=*HH,HPre=*HHPre;
341: MatStructure pflag=*flag;
348: info = PetscLogEventBegin(Tao_HessianEval,X,H,0,0);CHKERRQ(info);
349: PetscStackPush("TAO User Hessian Routine");
350: if (taoapp->computehessian){
351: info = (*taoapp->computehessian)(taoapp,X,&H,&HPre,&pflag,taoapp->usrhctx);
352: CHKERRQ(info);
353: } else {
354: SETERRQ(1,"TAO Error: No Hessian Routine Available");
355: }
356: *HH=H;*HHPre=HPre;*flag=pflag;
357: taoapp->nheval++;
358: info = PetscLogEventEnd(Tao_HessianEval,X,H,0,0);CHKERRQ(info);
359: PetscStackPop;
360: return(0);
361: }
366: /*@C
367: TaoAppSetHessianRoutine - Sets the function to compute the Hessian as well as the
368: location to store the matrix.
370: Collective on TAO_APPLICATION and Mat
372: Input Parameters:
373: + taoapp - the TAO_APPLICATION context
374: . hess - Hessian evaluation routine
375: - ctx - [optional] user-defined context for private data for the
376: Hessian evaluation routine (may be TAO_NULL)
378: Calling sequence of hess:
379: $ hess (TAO_APPLICATION taoapp,Vec x,Mat *H,Mat *Hpre,int *flag,void *ctx);
381: + taoapp - the TAO_APPLICATION context
382: . x - input vector
383: . H - Hessian matrix
384: . Hpre - preconditioner matrix, usually the same as A
385: . flag - flag indicating information about the preconditioner matrix
386: structure (see below)
387: - ctx - [optional] user-defined Hessian context
389: Options Database Keys:
390: . -tao_view_hessian - view the hessian after each evaluation using PETSC_VIEWER_STDOUT_WORLD
392: Notes:
394: The function hess() takes Mat * as the matrix arguments rather than Mat.
395: This allows the Hessian evaluation routine to replace A and/or B with a
396: completely new new matrix structure (not just different matrix elements)
397: when appropriate, for instance, if the nonzero structure is changing
398: throughout the global iterations.
400: The flag can be used to eliminate unnecessary work in the preconditioner
401: during the repeated solution of linear systems of the same size. The
402: available options are
403: $ SAME_PRECONDITIONER -
404: $ B is identical during successive linear solves.
405: $ This option is intended for folks who are using
406: $ different Amat and Pmat matrices and want to reuse the
407: $ same preconditioner matrix. For example, this option
408: $ saves work by not recomputing incomplete factorization
409: $ for ILU/ICC preconditioners.
410: $ SAME_NONZERO_PATTERN -
411: $ B has the same nonzero structure during
412: $ successive linear solves.
413: $ DIFFERENT_NONZERO_PATTERN -
414: $ B does not have the same nonzero structure.
416: Caution:
417: If you specify SAME_NONZERO_PATTERN, the software believes your assertion
418: and does not check the structure of the matrix. If you erroneously
419: claim that the structure is the same when it actually is not, the new
420: preconditioner will not function correctly. Thus, use this optimization
421: feature carefully!
423: If in doubt about whether your preconditioner matrix has changed
424: structure or not, use the flag DIFFERENT_NONZERO_PATTERN.
426: Level: beginner
428: .keywords: TAO_APPLICATION, Hessian
430: .seealso: TaoAppSetObjectiveAndGradientRoutine(), TaoAppSetHessianMat(), KSPSetOperators()
431: @*/
432: int TaoAppSetHessianRoutine(TAO_APPLICATION taoapp, int (*hess)(TAO_APPLICATION,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx){
435: taoapp->computehessian=hess;
436: taoapp->usrhctx=ctx;
437: return(0);
438: }
443: /*@
444: TaoAppSetHessianMat - Sets the matrix representing the Hessian
445: and the matrix used to precondition it.
447: Collective on TAO_APPLICATION
449: Input Parameters:
450: + taoapp - the TAO_APPLICATION context
451: . H - the matrix used for the Hessian
452: - HP - the matrix used to precondition the Hessian matrix.
454: Note:
455: Usually H and HP are the same matrix
457: Level: beginner
459: .seealso: TaoAppSetHessianRoutine()
460: @*/
461: int TaoAppSetHessianMat(TAO_APPLICATION taoapp, Mat H, Mat HP ){
462: int info;
466: if (H) {
469: PetscObjectReference((PetscObject)H);
470: PetscObjectReference((PetscObject)HP);
471: }
472: if (taoapp->H) {
473: info=MatDestroy(taoapp->H);CHKERRQ(info);
474: info=MatDestroy(taoapp->HP);CHKERRQ(info);
475: }
477: taoapp->H=H;
478: taoapp->HP=HP;
479: return(0);
480: }
484: /*@
485: TaoAppGetHessianMat - Sets the matrix representing the Hessian
486: and the matrix used to precondition it.
488: Collective on TAO_APPLICATION
490: Input Parameters:
491: + taoapp - the TAO_APPLICATION context
492: . H - the matrix used for the Hessian
493: - HP - the matrix used to precondition the Hessian matrix.
495: Note:
496: Usually H and HP are the same matrix
498: Level: developer
500: .seealso: TaoAppSetHessianMat()
501: @*/
502: int TaoAppGetHessianMat(TAO_APPLICATION taoapp, Mat *H, Mat *HP ){
505: if (H) { *H=taoapp->H;}
506: if (HP){ *HP=taoapp->HP;}
507: return(0);
508: }
513: /*@C
514: TaoAppSetHessianSolveRoutine - Sets the routine that solves a linear
515: system involving the Hessian operator, (or approximate Hessian).
517: Collective on TAO_APPLICATION
519: Input Parameters:
520: + taoapp - the TAO_APPLICATION context
521: . ah - gradient evaluation routine
522: - ctx - [optional] user-defined function context
524: Calling sequence of func:
525: $ ah (TAO_APPLICATION taoapp,Vec vin,Vec vout, PetscTruth* success, void *ctx);
527: + taoapp - the TAO_APPLICATION context
528: . v - input vector
529: - ctx - user-defined function gradient context set from TaoAppSetGradientRoutine()
531: Level: intermediate
533: Note:
534: This routine is to be used only with the LMVM and BLMVM solvers. These solvers do not use Hessian information, but can incorporate very approximate Hessian information into the routine.
536: .keywords: TAO_APPLICATION, set, hessian
538: .seealso: TaoAppSetHessianRoutine()
540: @*/
541: int TaoAppSetHessianSolveRoutine(TAO_APPLICATION taoapp, int (*ah)(TAO_APPLICATION,Vec,Vec,PetscTruth*,void*),void *ctx){
544: taoapp->hessiansolve=ah;
545: taoapp->usrhhhctx=ctx;
546: return(0);
547: }
552: /*@
553: TaoAppHessianSolve - Apply an
554: inverse Hessian operator to the vector, or solve a linear
555: system involving the Hessian. It uses the
556: routine set by TaoApplicationSetHessianSolveRoutine().
558: Collective on TAO_APPLICATION
560: Input Parameters:
561: + taopp - the TAO_APPLICATION context
562: - Vin - the vector to be applied to the approximate inverse Hessian operator.
564: Output Parameter:
565: + Vout - the inverse Hessian times the input vector.
566: - success - flag indicating whether a solution was found.
568: Level: developer
570: .keywords: TAO_APPLICATION, objective
572: .seealso: TaoAppComputeHessian(), TaoLMVMSetSize()
573: @*/
574: int TaoAppHessianSolve(TAO_APPLICATION taoapp, Vec Vin, Vec Vout, PetscTruth *success){
575: int info;
581: PetscStackPush("TAO Apply User Approximate Hessian");
582: info = PetscLogEventBegin(Tao_HessianEval,taoapp,Vin,Vout,0);
583: if (taoapp->hessiansolve){
584: info = (*taoapp->hessiansolve)(taoapp,Vin,Vout,success,taoapp->usrhhhctx);
585: CHKERRQ(info);
586: }
587: info = PetscLogEventEnd(Tao_HessianEval,taoapp,Vin,Vout,0);
588: taoapp->nlsolve++;
589: PetscStackPop;
590: return(0);
591: }
595: /*@
596: TaoAppResetCounters - Resent function evaluations counters to zero.
598: Collective on TAO_APPLICATION
600: Input Parameters:
601: . taopp - the TAO_APPLICATION context
603: Level: developer
605: .keywords: TAO_APPLICATION, objective
607: .seealso: TaoAppComputeHessian
608: @*/
609: int TaoAppResetCounters(TAO_APPLICATION taoapp){
612: taoapp->nfeval=0;
613: taoapp->ngeval=0;
614: taoapp->nheval=0;
615: taoapp->nlsolve=0;
616: return(0);
617: }
621: /*@
622: TaoAppCounters - Count the number of function, gradient, and
623: Hessian evaluations, and the number of linear solves.
625: Collective on TAO_APPLICATION
627: Input Parameters:
628: . taopp - the TAO_APPLICATION context
630: Output Parameters:
631: stat[4] ,the number of function, gradient, and Hessian evaluations. And
632: the number of linear solves.
634: Level: developer
636: .keywords: TAO_APPLICATION, objective
638: .seealso: TaoAppComputeHessian
639: @*/
640: int TaoAppCounters(TAO_APPLICATION taoapp,int stats[4]){
643: stats[0]=taoapp->nfeval;
644: stats[1]=taoapp->ngeval;
645: stats[2]=taoapp->nheval;
646: stats[3]=taoapp->nlsolve;
647: return(0);
648: }