Actual source code: tao_app_fg.c
1: #include "tao_general.h"
2: #include "tao_app_impl.h" /*I "tao.h" I*/
3: #include "src/petsctao/include/taopetsc.h"
10: /*@C
11: TaoAppSetObjectiveRoutine - Sets a routine that evaluates the function at
12: the specified point.
14: Collective on TAO_APPLICATION
16: Input Parameters:
17: + taoapp - the TAO_APPLICATION context
18: . func - function evaluation routine
19: - ctx - [optional] user-defined context for private data for the
20: function and gradient evaluation routine (may be TAO_NULL)
22: Calling sequence of func:
23: $ func (TAO_APPLICATION taoapp, Vec x,double *f,void *ctx);
25: + taoapp - the TAO_APPLICATION context
26: . x - input vector
27: . f - objective function value
28: - ctx - [optional] user-defined function context
30: Note:
31: Most applications do not need this routine. The routine
32: TaoAppSetObjectiveFunctionGradient() is sufficient.
34: Level: intermediate
36: .keywords: TAO_APPLICATION, set, minimization, function
38: .seealso: TaoAppSetHessianRoutine(), TaoAppSetObjectiveAndGradientRoutine(), TaoAppSetInitialSolutionVec()
39: @*/
40: int TaoAppSetObjectiveRoutine(TAO_APPLICATION taoapp, int (*func)(TAO_APPLICATION,Vec,double*,void*),void *ctx){
43: taoapp->computeumfunction=func;
44: taoapp->usrfctx=ctx;
45: return(0);
46: }
50: /*@
51: TaoAppComputeObjective - Compute the objective function that has been
52: set with TaoAppSetObjectiveRoutine().
54: Collective on TAO_APPLICATION
56: Input Parameters:
57: + taopp - the TAO_APPLICATION context
58: - X - the point where the objective should be evaluated
60: Output Parameter:
61: . f - function value
63: Level: developer
65: .keywords: TAO_APPLICATION, objective
67: .seealso: TaoAppComputeGradient(), TaoAppComputeObjectiveAndGradient()
68: @*/
69: int TaoAppComputeObjective(TAO_APPLICATION taoapp, Vec X, double *f){
70: int info;
71: Vec G;
72:
76: PetscStackPush("TAO User minimization function");
77: info = PetscLogEventBegin(Tao_ObjectiveEval,taoapp,X,0,0);
78: if (taoapp->computeumfunction){
79: info = (*taoapp->computeumfunction)(taoapp,X,f,taoapp->usrfctx); CHKERRQ(info);
80: } else if (taoapp->computefunctiongradient){
81: info = VecDuplicate(X,&G);CHKERRQ(info);
82: info = (*taoapp->computefunctiongradient)(taoapp,X,f,G,taoapp->usrfgctx);
83: CHKERRQ(info);
84: info=VecDestroy(G);CHKERRQ(info);
85: taoapp->ngeval++;
86: } else {
87: SETERRQ(1,"TAO ERROR: Must set Objective function");
88: }
89: taoapp->nfeval++;
90: info = PetscLogEventEnd(Tao_ObjectiveEval,taoapp,X,0,0);
91: PetscStackPop;
92: info = PetscInfo1(taoapp,"TAO Function evaluation: %14.12e\n",*f);CHKERRQ(info);
93: return(0);
94: }
99: /*@C
100: TaoAppSetGradientRoutine - Sets the gradient evaluation routine
101: for use by the TAO_APPLICATION routines.
103: Collective on TAO_APPLICATION
105: Input Parameters:
106: + taoapp - the TAO_APPLICATION context
107: . grad - gradient evaluation routine
108: - ctx - [optional] user-defined function context
110: Calling sequence of func:
111: $ grad (TAO_APPLICATION taoapp,Vec x,Vec g,void *ctx);
113: + taoapp - the TAO_APPLICATION context
114: . x - input vector
115: . g - gradient vector
116: - ctx - user-defined function gradient context set from TaoAppSetGradientRoutine()
118: Level: intermediate
120: Options Database Keys:
121: . -tao_view_gradient - view the gradient after each evaluation using PETSC_VIEWER_STDOUT_WORLD
123: Note:
124: In most cases, the routine TaoAppSetObjectiveAndGradientRoutine() is more appropriate. However,
125: when using finite differences to compute the Hessian, setting this routine can be
126: beneficial.
128: .keywords: TAO_APPLICATION, set, gradient
130: .seealso: TaoAppGetGradientVec(), TaoAppSetObjectiveAndGradientRoutine(), TaoAppSetHessianRoutine()
132: @*/
133: int TaoAppSetGradientRoutine(TAO_APPLICATION taoapp, int (*grad)(TAO_APPLICATION,Vec,Vec,void*),void *ctx){
136: taoapp->computegradient=grad;
137: taoapp->usrgctx=ctx;
138: return(0);
139: }
144: /*@
145: TaoAppComputeGradient - Compute the gradient of the objective function using the
146: routine set by TaoApplicationSetGradientRoutine().
148: Collective on TAO_APPLICATION
150: Input Parameters:
151: + taopp - the TAO_APPLICATION context
152: - X - the point where the objective should be evaluated
154: Output Parameter:
155: . f - function value
157: Level: developer
159: .keywords: TAO_APPLICATION, objective
161: .seealso: TaoAppComputeGradient(), TaoAppComputeObjectiveAndGradient()
162: @*/
163: int TaoAppComputeGradient(TAO_APPLICATION taoapp, Vec X, Vec G){
164: int info;
165: double ff;
171: PetscStackPush("TAO User Gradient Evaluation");
172: info = PetscLogEventBegin(Tao_GradientEval,taoapp,X,G,0);
173: if (taoapp->computegradient){
174: info = (*taoapp->computegradient)(taoapp,X,G,taoapp->usrgctx);
175: CHKERRQ(info);
176: } else if ( taoapp->computefunctiongradient ) {
177: info = (*taoapp->computefunctiongradient)(taoapp,X,&ff,G,taoapp->usrfgctx);
178: CHKERRQ(info);
179: taoapp->nfeval++;
180: } else {
181: SETERRQ(1,"TAO ERROR: Must set gradient");
182: }
183: taoapp->ngeval++;
184: info = PetscLogEventEnd(Tao_GradientEval,taoapp,X,G,0);
185: PetscStackPop;
186: return(0);
187: }
193: /*@
194: TaoAppComputeObjectiveAndGradient - Compute the gradient of the objective function using the
195: routine set by TaoApplicationSetGradientRoutine().
197: Collective on TAO_APPLICATION
199: Input Parameters:
200: + taopp - the TAO_APPLICATION context
201: - X - the point where the objective should be evaluated
203: Output Parameter:
204: + f - function value
205: - G - the gradient vector.
207: Level: developer
209: .keywords: TAO_APPLICATION, objective
211: .seealso: TaoAppComputeGradient(), TaoAppSetObjectiveAndGradientRoutine()
212: @*/
213: int TaoAppComputeObjectiveAndGradient(TAO_APPLICATION taoapp, Vec X, double *f, Vec G){
214: int info;
219: PetscStackPush("TAO User Objective and gradient function");
220: if (taoapp->computefunctiongradient){
221: info = PetscLogEventBegin(Tao_GradientEval,taoapp,X,G,0);CHKERRQ(info);
222: info = PetscLogEventBegin(Tao_ObjectiveEval,taoapp,X,G,0);
223: info = (*taoapp->computefunctiongradient)(taoapp,X,f,G,taoapp->usrfgctx);
224: CHKERRQ(info);
225: info = PetscLogEventEnd(Tao_ObjectiveEval,taoapp,X,G,0);CHKERRQ(info);
227: if (taoapp->computegradient) {
228: info = PetscInfo(taoapp,"Computing gradient routine separately, ignoring gradient calculated in function/gradient evaluation routine."); CHKERRQ(info);
229: info = (*taoapp->computegradient)(taoapp,X,G,taoapp->usrfgctx);
230: CHKERRQ(info);
231: }
232: info = PetscLogEventEnd(Tao_GradientEval,taoapp,X,G,0);CHKERRQ(info);
233: } else if ( taoapp->computeumfunction && taoapp->computegradient ) {
234: info = PetscLogEventBegin(Tao_ObjectiveEval,taoapp,X,G,0);
235: info = (*taoapp->computeumfunction)(taoapp,X,f,taoapp->usrfctx);
236: CHKERRQ(info);
237: info = PetscLogEventEnd(Tao_ObjectiveEval,taoapp,X,G,0);CHKERRQ(info);
238: info = PetscLogEventBegin(Tao_GradientEval,taoapp,X,G,0);CHKERRQ(info);
239: info = (*taoapp->computegradient)(taoapp,X,G,taoapp->usrgctx);
240: CHKERRQ(info);
241: info = PetscLogEventEnd(Tao_GradientEval,taoapp,X,G,0);CHKERRQ(info);
242: } else {
243: SETERRQ(1,"TAO ERROR: Must set objective function and gradient.");
244: }
245: info = PetscInfo1(taoapp,"TAO Function evaluation: %14.12e\n",*f);CHKERRQ(info);
246: taoapp->nfeval++;
247: taoapp->ngeval++;
249: PetscStackPop;
250: return(0);
251: }
253:
257: /*@C
258: TaoAppSetObjectiveAndGradientRoutine - Sets a routine for function and gradient evaluation.
260: Collective on TAO_APPLICATION
262: Input Parameters:
263: + taoapp - the TAO_APPLICATION context
264: . funcgrad - routine for evaluating the function and gradient
265: - ctx - optional user-defined context for private data for the
266: function and gradient evaluation routine (may be TAO_NULL)
268: Calling sequence of funcgrad:
269: $ funcgrad (TAO_APPLICATION tao,Vec x,double *f,Vec g,void *ctx);
271: + tao - TAO_APPLICATION context
272: . x - input vector
273: . f - function value
274: . g - gradient vector
275: - ctx - optional user-defined context
277: Notes:
278: The user may call TaoAppSetObjectiveAndGradientRoutine() to set a routine
279: that evaluates both the function and gradient. Alternatively, the
280: user may call both TaoAppSetObjectiveRoutine() and TaoAppSetGradientRoutine() to set
281: separate routines for function and gradient evaluation.
283: Using a single routine to compute the function and gradient, as
284: specified via TaoAppSetObjectiveAndGradientRoutine(), may enable better performance
285: for applications in which many of the function and gradient computations
286: are identical.
288: Fortran Note:
289: If your Fortran compiler does not recognize symbols over 31 characters in length, then
290: use the identical routine with the shortened name TaoAppSetObjectiveAndGradientRo()
293: Level: beginner
295: Options Database Keys:
296: . -tao_view_gradient - view the gradient after each iteration using PETSC_VIEWER_STDOUT_WORLD
298: .keywords: TAO_APPLICATION, set, objective, gradient
300: .seealso: TaoAppComputeObjectiveAndGradient()
302: @*/
303: int TaoAppSetObjectiveAndGradientRoutine(TAO_APPLICATION taoapp, int (*funcgrad)(TAO_APPLICATION,Vec,double*,Vec, void*),void *ctx){
306: taoapp->computefunctiongradient=funcgrad;
307: taoapp->usrfgctx=ctx;
308: return(0);
309: }
315: /*@C
316: TaoAppComputeHessian - Compute the Hessian of the objective function using the
317: routine set by TaoApplicationSetGradientRoutine().
319: Collective on TAO_APPLICATION
321: Input Parameters:
322: + taopp - the TAO_APPLICATION context
323: . X - the variable vector
324: . H - the Hessian matrix
325: . HP - the preconditioner for the Hessian matrix.
326: - flag - flag used in KSPSetOperators()
328: Output Parameter:
329: + H - the Hessian matrix
330: . HP - the preconditioner for the Hessian matrix.
331: - flag - flag used in KSPSetOperators()
333: Level: developer
335: .keywords: TAO_APPLICATION, objective
337: .seealso: TaoAppComputeObjectiveAndGradient()
338: @*/
339: int TaoAppComputeHessian(TAO_APPLICATION taoapp, Vec X, Mat *HH, Mat *HHPre, MatStructure *flag){
340: int info;
341: Mat H=*HH,HPre=*HHPre;
342: MatStructure pflag=*flag;
349: info = PetscLogEventBegin(Tao_HessianEval,X,H,0,0);CHKERRQ(info);
350: PetscStackPush("TAO User Hessian Routine");
351: if (taoapp->computehessian){
352: info = (*taoapp->computehessian)(taoapp,X,&H,&HPre,&pflag,taoapp->usrhctx);
353: CHKERRQ(info);
354: } else {
355: SETERRQ(1,"TAO Error: No Hessian Routine Available");
356: }
357: *HH=H;*HHPre=HPre;*flag=pflag;
358: taoapp->nheval++;
359: info = PetscLogEventEnd(Tao_HessianEval,X,H,0,0);CHKERRQ(info);
360: PetscStackPop;
361: return(0);
362: }
367: /*@C
368: TaoAppSetHessianRoutine - Sets the function to compute the Hessian as well as the
369: location to store the matrix.
371: Collective on TAO_APPLICATION and Mat
373: Input Parameters:
374: + taoapp - the TAO_APPLICATION context
375: . hess - Hessian evaluation routine
376: - ctx - [optional] user-defined context for private data for the
377: Hessian evaluation routine (may be TAO_NULL)
379: Calling sequence of hess:
380: $ hess (TAO_APPLICATION taoapp,Vec x,Mat *H,Mat *Hpre,int *flag,void *ctx);
382: + taoapp - the TAO_APPLICATION context
383: . x - input vector
384: . H - Hessian matrix
385: . Hpre - preconditioner matrix, usually the same as A
386: . flag - flag indicating information about the preconditioner matrix
387: structure (see below)
388: - ctx - [optional] user-defined Hessian context
390: Options Database Keys:
391: . -tao_view_hessian - view the hessian after each evaluation using PETSC_VIEWER_STDOUT_WORLD
393: Notes:
395: The function hess() takes Mat * as the matrix arguments rather than Mat.
396: This allows the Hessian evaluation routine to replace A and/or B with a
397: completely new new matrix structure (not just different matrix elements)
398: when appropriate, for instance, if the nonzero structure is changing
399: throughout the global iterations.
401: The flag can be used to eliminate unnecessary work in the preconditioner
402: during the repeated solution of linear systems of the same size. The
403: available options are
404: $ SAME_PRECONDITIONER -
405: $ B is identical during successive linear solves.
406: $ This option is intended for folks who are using
407: $ different Amat and Pmat matrices and want to reuse the
408: $ same preconditioner matrix. For example, this option
409: $ saves work by not recomputing incomplete factorization
410: $ for ILU/ICC preconditioners.
411: $ SAME_NONZERO_PATTERN -
412: $ B has the same nonzero structure during
413: $ successive linear solves.
414: $ DIFFERENT_NONZERO_PATTERN -
415: $ B does not have the same nonzero structure.
417: Caution:
418: If you specify SAME_NONZERO_PATTERN, the software believes your assertion
419: and does not check the structure of the matrix. If you erroneously
420: claim that the structure is the same when it actually is not, the new
421: preconditioner will not function correctly. Thus, use this optimization
422: feature carefully!
424: If in doubt about whether your preconditioner matrix has changed
425: structure or not, use the flag DIFFERENT_NONZERO_PATTERN.
427: Level: beginner
429: .keywords: TAO_APPLICATION, Hessian
431: .seealso: TaoAppSetObjectiveAndGradientRoutine(), TaoAppSetHessianMat(), KSPSetOperators()
432: @*/
433: int TaoAppSetHessianRoutine(TAO_APPLICATION taoapp, int (*hess)(TAO_APPLICATION,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx){
436: taoapp->computehessian=hess;
437: taoapp->usrhctx=ctx;
438: return(0);
439: }
444: /*@
445: TaoAppSetHessianMat - Sets the matrix representing the Hessian
446: and the matrix used to precondition it.
448: Collective on TAO_APPLICATION
450: Input Parameters:
451: + taoapp - the TAO_APPLICATION context
452: . H - the matrix used for the Hessian
453: - HP - the matrix used to precondition the Hessian matrix.
455: Note:
456: Usually H and HP are the same matrix
458: Level: beginner
460: .seealso: TaoAppSetHessianRoutine()
461: @*/
462: int TaoAppSetHessianMat(TAO_APPLICATION taoapp, Mat H, Mat HP ){
463: int info;
467: if (H) {
470: PetscObjectReference((PetscObject)H);
471: PetscObjectReference((PetscObject)HP);
472: }
473: if (taoapp->H) {
474: info=MatDestroy(taoapp->H);CHKERRQ(info);
475: info=MatDestroy(taoapp->HP);CHKERRQ(info);
476: }
478: taoapp->H=H;
479: taoapp->HP=HP;
480: return(0);
481: }
485: /*@
486: TaoAppGetHessianMat - Sets the matrix representing the Hessian
487: and the matrix used to precondition it.
489: Collective on TAO_APPLICATION
491: Input Parameters:
492: + taoapp - the TAO_APPLICATION context
493: . H - the matrix used for the Hessian
494: - HP - the matrix used to precondition the Hessian matrix.
496: Note:
497: Usually H and HP are the same matrix
499: Level: developer
501: .seealso: TaoAppSetHessianMat()
502: @*/
503: int TaoAppGetHessianMat(TAO_APPLICATION taoapp, Mat *H, Mat *HP ){
506: if (H) { *H=taoapp->H;}
507: if (HP){ *HP=taoapp->HP;}
508: return(0);
509: }
514: /*@C
515: TaoAppSetHessianSolveRoutine - Sets the routine that solves a linear
516: system involving the Hessian operator, (or approximate Hessian).
518: Collective on TAO_APPLICATION
520: Input Parameters:
521: + taoapp - the TAO_APPLICATION context
522: . ah - gradient evaluation routine
523: - ctx - [optional] user-defined function context
525: Calling sequence of func:
526: $ ah (TAO_APPLICATION taoapp,Vec vin,Vec vout, PetscTruth* success, void *ctx);
528: + taoapp - the TAO_APPLICATION context
529: . v - input vector
530: - ctx - user-defined function gradient context set from TaoAppSetGradientRoutine()
532: Level: intermediate
534: Note:
535: 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.
537: .keywords: TAO_APPLICATION, set, hessian
539: .seealso: TaoAppSetHessianRoutine()
541: @*/
542: int TaoAppSetHessianSolveRoutine(TAO_APPLICATION taoapp, int (*ah)(TAO_APPLICATION,Vec,Vec,PetscTruth*,void*),void *ctx){
545: taoapp->hessiansolve=ah;
546: taoapp->usrhhhctx=ctx;
547: return(0);
548: }
553: /*@
554: TaoAppHessianSolve - Apply an
555: inverse Hessian operator to the vector, or solve a linear
556: system involving the Hessian. It uses the
557: routine set by TaoApplicationSetHessianSolveRoutine().
559: Collective on TAO_APPLICATION
561: Input Parameters:
562: + taopp - the TAO_APPLICATION context
563: - Vin - the vector to be applied to the approximate inverse Hessian operator.
565: Output Parameter:
566: + Vout - the inverse Hessian times the input vector.
567: - success - flag indicating whether a solution was found.
569: Level: developer
571: .keywords: TAO_APPLICATION, objective
573: .seealso: TaoAppComputeHessian(), TaoLMVMSetSize()
574: @*/
575: int TaoAppHessianSolve(TAO_APPLICATION taoapp, Vec Vin, Vec Vout, PetscTruth *success){
576: int info;
582: PetscStackPush("TAO Apply User Approximate Hessian");
583: info = PetscLogEventBegin(Tao_HessianEval,taoapp,Vin,Vout,0);
584: if (taoapp->hessiansolve){
585: info = (*taoapp->hessiansolve)(taoapp,Vin,Vout,success,taoapp->usrhhhctx);
586: CHKERRQ(info);
587: }
588: info = PetscLogEventEnd(Tao_HessianEval,taoapp,Vin,Vout,0);
589: taoapp->nlsolve++;
590: PetscStackPop;
591: return(0);
592: }
596: /*@
597: TaoAppResetCounters - Resent function evaluations counters to zero.
599: Collective on TAO_APPLICATION
601: Input Parameters:
602: . taopp - the TAO_APPLICATION context
604: Level: developer
606: .keywords: TAO_APPLICATION, objective
608: .seealso: TaoAppComputeHessian
609: @*/
610: int TaoAppResetCounters(TAO_APPLICATION taoapp){
613: taoapp->nfeval=0;
614: taoapp->ngeval=0;
615: taoapp->nheval=0;
616: taoapp->nlsolve=0;
617: return(0);
618: }
622: /*@
623: TaoAppCounters - Count the number of function, gradient, and
624: Hessian evaluations, and the number of linear solves.
626: Collective on TAO_APPLICATION
628: Input Parameters:
629: . taopp - the TAO_APPLICATION context
631: Output Parameters:
632: stat[4] ,the number of function, gradient, and Hessian evaluations. And
633: the number of linear solves.
635: Level: developer
637: .keywords: TAO_APPLICATION, objective
639: .seealso: TaoAppComputeHessian
640: @*/
641: int TaoAppCounters(TAO_APPLICATION taoapp,TaoInt stats[4]){
644: stats[0]=taoapp->nfeval;
645: stats[1]=taoapp->ngeval;
646: stats[2]=taoapp->nheval;
647: stats[3]=taoapp->nlsolve;
648: return(0);
649: }