Actual source code: tao_app_fg.c

  1: #include "tao_app_impl.h"     /*I  "tao.h"  I*/


  8: /*@C
  9:    TaoAppSetObjectiveRoutine - Sets a routine that evaluates the function at
 10: the specified point.

 12:    Collective on TAO_APPLICATION

 14:    Input Parameters:
 15: +  taoapp - the TAO_APPLICATION context
 16: .  func - function evaluation routine
 17: -  ctx - [optional] user-defined context for private data for the 
 18:          function and gradient evaluation routine (may be TAO_NULL)

 20:    Calling sequence of func:
 21: $     func (TAO_APPLICATION taoapp, Vec x,double *f,void *ctx);

 23: +  taoapp - the TAO_APPLICATION context
 24: .  x - input vector
 25: .  f - objective function value
 26: -  ctx - [optional] user-defined function context 

 28:    Note:  
 29:    Most applications do not need this routine.  The routine
 30:    TaoAppSetObjectiveFunctionGradient() is sufficient.

 32:    Level: intermediate

 34: .keywords: TAO_APPLICATION, set, minimization, function

 36: .seealso:  TaoAppSetHessianRoutine(), TaoAppSetObjectiveAndGradientRoutine(), TaoAppSetInitialSolutionVec()
 37: @*/
 38: int TaoAppSetObjectiveRoutine(TAO_APPLICATION taoapp, int (*func)(TAO_APPLICATION,Vec,double*,void*),void *ctx){
 41:   taoapp->computeumfunction=func;
 42:   taoapp->usrfctx=ctx;
 43:   return(0);
 44: }

 48: /*@
 49:    TaoAppComputeObjective - Compute the objective function that has been
 50:    set with TaoAppSetObjectiveRoutine().

 52:    Collective on TAO_APPLICATION

 54:    Input Parameters:
 55: +  taopp - the TAO_APPLICATION context
 56: -  X - the point where the objective should be evaluated

 58:    Output Parameter:
 59: .  f - function value

 61:    Level: developer

 63: .keywords: TAO_APPLICATION, objective

 65: .seealso: TaoAppComputeGradient(), TaoAppComputeObjectiveAndGradient()
 66: @*/
 67: int TaoAppComputeObjective(TAO_APPLICATION taoapp, Vec X, double *f){
 68:   int     info;
 69:   Vec G;
 70: 
 74:   PetscStackPush("TAO User minimzation function");
 75:   info = PetscLogEventBegin(Tao_ObjectiveEval,taoapp,X,0,0);
 76:   if (taoapp->computeumfunction){
 77:     info = (*taoapp->computeumfunction)(taoapp,X,f,taoapp->usrfctx);
 78:     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 = PetscLogInfo((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);
225:     info = PetscLogEventEnd(Tao_GradientEval,taoapp,X,G,0);CHKERRQ(info);
226:   } else if ( taoapp->computeumfunction && taoapp->computegradient ) {
227:     info = PetscLogEventBegin(Tao_ObjectiveEval,taoapp,X,G,0);
228:     info = (*taoapp->computeumfunction)(taoapp,X,f,taoapp->usrfctx);
229:     CHKERRQ(info);
230:     info = PetscLogEventEnd(Tao_ObjectiveEval,taoapp,X,G,0);CHKERRQ(info);
231:     info = PetscLogEventBegin(Tao_GradientEval,taoapp,X,G,0);CHKERRQ(info);
232:     info = (*taoapp->computegradient)(taoapp,X,G,taoapp->usrgctx);
233:     CHKERRQ(info);
234:     info = PetscLogEventEnd(Tao_GradientEval,taoapp,X,G,0);CHKERRQ(info);
235:   } else {
236:     SETERRQ(1,"TAO ERROR: Must set objective function and gradient.");
237:   }
238:   info = PetscLogInfo((taoapp,"TAO Function evaluation: %14.12e\n",*f));CHKERRQ(info);
239:   taoapp->nfeval++;
240:   taoapp->ngeval++;

242:   PetscStackPop;
243:   return(0);
244: }

246: 

250: /*@C
251:    TaoAppSetObjectiveAndGradientRoutine - Sets a routine for function and gradient evaluation.

253:    Collective on TAO_APPLICATION

255:    Input Parameters:
256: +  taoapp - the TAO_APPLICATION context
257: .  funcgrad - routine for evaluating the function and gradient
258: -  ctx - optional user-defined context for private data for the 
259:          function and gradient evaluation routine (may be TAO_NULL)

261:    Calling sequence of funcgrad:
262: $     funcgrad (TAO_APPLICATION tao,Vec x,double *f,Vec g,void *ctx);

264: +  tao - TAO_APPLICATION  context
265: .  x - input vector
266: .  f - function value
267: .  g - gradient vector
268: -  ctx - optional user-defined context 

270:    Notes:
271:    The user may call TaoAppSetObjectiveAndGradientRoutine() to set a routine
272:    that evaluates both the function and gradient.  Alternatively, the
273:    user may call both TaoAppSetObjectiveRoutine() and TaoAppSetGradientRoutine() to set
274:    separate routines for function and gradient evaluation.  

276:    Using a single routine to compute the function and gradient, as
277:    specified via TaoAppSetObjectiveAndGradientRoutine(), may enable better performance
278:    for applications in which many of the function and gradient computations
279:    are identical.

281:    Fortran Note:
282:    If your Fortran compiler does not recognize symbols over 31 characters in length, then
283:    use the identical routine with the shortened name TaoAppSetObjectiveAndGradientRo()


286:    Level: beginner

288:    Options Database Keys:
289: .   -tao_view_gradient - view the gradient after each iteration using PETSC_VIEWER_STDOUT_WORLD

291: .keywords: TAO_APPLICATION, set, objective, gradient

293: .seealso: TaoAppComputeObjectiveAndGradient()

295: @*/
296: int TaoAppSetObjectiveAndGradientRoutine(TAO_APPLICATION taoapp, int (*funcgrad)(TAO_APPLICATION,Vec,double*,Vec, void*),void *ctx){
299:   taoapp->computefunctiongradient=funcgrad;
300:   taoapp->usrfgctx=ctx;
301:   return(0);
302: }



308: /*@C
309:    TaoAppComputeHessian - Compute the Hessian of the objective function using the
310:    routine set by TaoApplicationSetGradientRoutine().

312:    Collective on TAO_APPLICATION

314:    Input Parameters:
315: +  taopp - the TAO_APPLICATION context
316: .  X - the variable vector
317: .  H - the Hessian matrix
318: .  HP - the preconditioner for the Hessian matrix.
319: -  flag - flag used in KSPSetOperators()

321:    Output Parameter:
322: +  H - the Hessian matrix
323: .  HP - the preconditioner for the Hessian matrix.
324: -  flag - flag used in KSPSetOperators()

326:    Level: developer

328: .keywords: TAO_APPLICATION, objective

330: .seealso: TaoAppComputeObjectiveAndGradient()
331: @*/
332: int TaoAppComputeHessian(TAO_APPLICATION taoapp, Vec X, Mat *HH, Mat *HHPre, MatStructure *flag){
333:   int     info;
334:   Mat H=*HH,HPre=*HHPre;
335:   MatStructure pflag=*flag;

342:   info = PetscLogEventBegin(Tao_HessianEval,X,H,0,0);CHKERRQ(info);
343:   PetscStackPush("TAO User Hessian Routine");
344:   if (taoapp->computehessian){
345:     info = (*taoapp->computehessian)(taoapp,X,&H,&HPre,&pflag,taoapp->usrhctx);
346:     CHKERRQ(info);
347:   } else {
348:     SETERRQ(1,"TAO Error: No Hessian Routine Available");
349:   }
350:   *HH=H;*HHPre=HPre;*flag=pflag;
351:   taoapp->nheval++;
352:   info = PetscLogEventEnd(Tao_HessianEval,X,H,0,0);CHKERRQ(info);
353:   PetscStackPop;
354:   return(0);
355: }


360: /*@C
361:    TaoAppSetHessianRoutine - Sets the function to compute the Hessian as well as the
362:    location to store the matrix.

364:    Collective on TAO_APPLICATION and Mat

366:    Input Parameters:
367: +  taoapp - the TAO_APPLICATION context
368: .  hess - Hessian evaluation routine
369: -  ctx - [optional] user-defined context for private data for the 
370:          Hessian evaluation routine (may be TAO_NULL)

372:    Calling sequence of hess:
373: $    hess (TAO_APPLICATION taoapp,Vec x,Mat *H,Mat *Hpre,int *flag,void *ctx);

375: +  taoapp - the TAO_APPLICATION  context
376: .  x - input vector
377: .  H - Hessian matrix
378: .  Hpre - preconditioner matrix, usually the same as A
379: .  flag - flag indicating information about the preconditioner matrix
380:    structure (see below)
381: -  ctx - [optional] user-defined Hessian context

383:    Options Database Keys:
384: .  -tao_view_hessian - view the hessian after each evaluation using PETSC_VIEWER_STDOUT_WORLD

386:    Notes: 

388:    The function hess() takes Mat * as the matrix arguments rather than Mat.  
389:    This allows the Hessian evaluation routine to replace A and/or B with a 
390:    completely new new matrix structure (not just different matrix elements)
391:    when appropriate, for instance, if the nonzero structure is changing
392:    throughout the global iterations.

394:    The flag can be used to eliminate unnecessary work in the preconditioner 
395:    during the repeated solution of linear systems of the same size.  The
396:    available options are
397: $    SAME_PRECONDITIONER -
398: $      B is identical during successive linear solves.
399: $      This option is intended for folks who are using
400: $      different Amat and Pmat matrices and want to reuse the
401: $      same preconditioner matrix.  For example, this option
402: $      saves work by not recomputing incomplete factorization
403: $      for ILU/ICC preconditioners.
404: $    SAME_NONZERO_PATTERN -
405: $      B has the same nonzero structure during
406: $      successive linear solves. 
407: $    DIFFERENT_NONZERO_PATTERN -
408: $      B does not have the same nonzero structure.

410:    Caution:
411:    If you specify SAME_NONZERO_PATTERN, the software believes your assertion
412:    and does not check the structure of the matrix.  If you erroneously
413:    claim that the structure is the same when it actually is not, the new
414:    preconditioner will not function correctly.  Thus, use this optimization
415:    feature carefully!

417:    If in doubt about whether your preconditioner matrix has changed
418:    structure or not, use the flag DIFFERENT_NONZERO_PATTERN.

420:    Level: beginner

422: .keywords: TAO_APPLICATION, Hessian

424: .seealso: TaoAppSetObjectiveAndGradientRoutine(), TaoAppSetHessianMat(), KSPSetOperators()
425: @*/
426: int TaoAppSetHessianRoutine(TAO_APPLICATION taoapp, int (*hess)(TAO_APPLICATION,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx){
429:   taoapp->computehessian=hess;
430:   taoapp->usrhctx=ctx;
431:   return(0);
432: }


437: /*@
438:    TaoAppSetHessianMat - Sets the matrix representing the Hessian
439:    and the matrix used to precondition it.

441:    Collective on TAO_APPLICATION

443:    Input Parameters:
444: +  taoapp - the TAO_APPLICATION context
445: .  H - the matrix used for the Hessian
446: -  HP - the matrix used to precondition the Hessian matrix.

448:    Note:
449:    Usually H and HP are the same matrix

451:    Level: beginner

453: .seealso:  TaoAppSetHessianRoutine()
454: @*/
455: int TaoAppSetHessianMat(TAO_APPLICATION taoapp, Mat H, Mat HP ){
456:   int info;
459:   if (H){
462:     PetscObjectReference((PetscObject)H);
463:     PetscObjectReference((PetscObject)HP);
464:   }
465:   if (taoapp->H){
466:     info=MatDestroy(taoapp->H);CHKERRQ(info);
467:     info=MatDestroy(taoapp->HP);CHKERRQ(info);
468:   }
469:   taoapp->H=H;
470:   taoapp->HP=HP;
471:   return(0);
472: }

476: /*@
477:    TaoAppGetHessianMat - Sets the matrix representing the Hessian
478:    and the matrix used to precondition it.

480:    Collective on TAO_APPLICATION

482:    Input Parameters:
483: +  taoapp - the TAO_APPLICATION context
484: .  H - the matrix used for the Hessian
485: -  HP - the matrix used to precondition the Hessian matrix.

487:    Note:
488:    Usually H and HP are the same matrix

490:    Level: developer

492: .seealso:  TaoAppSetHessianMat()
493: @*/
494: int TaoAppGetHessianMat(TAO_APPLICATION taoapp, Mat *H, Mat *HP ){
497:   if (H) { *H=taoapp->H;}
498:   if (HP){ *HP=taoapp->HP;}
499:   return(0);
500: }


505: /*@C
506:    TaoAppSetHessianSolveRoutine - Sets the routine that solves a linear
507: system involving the Hessian operator, (or approximate Hessian).

509:    Collective on TAO_APPLICATION

511:    Input Parameters:
512: +  taoapp - the TAO_APPLICATION context
513: .  ah - gradient evaluation routine
514: -  ctx - [optional] user-defined function context 

516:    Calling sequence of func:
517: $     ah (TAO_APPLICATION taoapp,Vec vin,Vec vout, PetscTruth* success, void *ctx);

519: +  taoapp - the TAO_APPLICATION  context
520: .  v - input vector
521: -  ctx - user-defined function gradient context set from TaoAppSetGradientRoutine()

523:    Level: intermediate

525:    Note:
526:    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.

528: .keywords: TAO_APPLICATION, set, hessian

530: .seealso: TaoAppSetHessianRoutine()

532: @*/
533: int TaoAppSetHessianSolveRoutine(TAO_APPLICATION taoapp, int (*ah)(TAO_APPLICATION,Vec,Vec,PetscTruth*,void*),void *ctx){
536:   taoapp->hessiansolve=ah;
537:   taoapp->usrhhhctx=ctx;
538:   return(0);
539: }


544: /*@
545:    TaoAppHessianSolve - Apply an
546:    inverse Hessian operator to the vector, or solve a linear
547:    system involving the Hessian.   It uses the
548:    routine set by TaoApplicationSetHessianSolveRoutine().

550:    Collective on TAO_APPLICATION

552:    Input Parameters:
553: +  taopp - the TAO_APPLICATION context
554: -  Vin - the vector to be applied to the approximate inverse Hessian operator.

556:    Output Parameter:
557: +  Vout - the inverse Hessian times the input vector.
558: -  success - flag indicating whether a solution was found.

560:    Level: developer

562: .keywords: TAO_APPLICATION, objective

564: .seealso: TaoAppComputeHessian(), TaoLMVMSetSize()
565: @*/
566: int TaoAppHessianSolve(TAO_APPLICATION taoapp, Vec Vin, Vec Vout, PetscTruth *success){
567:   int     info;

573:   PetscStackPush("TAO Apply User Approximate Hessian");
574:   info = PetscLogEventBegin(Tao_HessianEval,taoapp,Vin,Vout,0);
575:   if (taoapp->hessiansolve){
576:     info = (*taoapp->hessiansolve)(taoapp,Vin,Vout,success,taoapp->usrhhhctx);
577:     CHKERRQ(info);
578:   }
579:   info = PetscLogEventEnd(Tao_HessianEval,taoapp,Vin,Vout,0);
580:   taoapp->nlsolve++;
581:   PetscStackPop;
582:   return(0);
583: }

587: /*@
588:    TaoAppResetCounters - Resent function evaluations counters to zero.

590:    Collective on TAO_APPLICATION

592:    Input Parameters:
593: .  taopp - the TAO_APPLICATION context

595:    Level: developer

597: .keywords: TAO_APPLICATION, objective

599: .seealso: TaoAppComputeHessian
600: @*/
601: int TaoAppResetCounters(TAO_APPLICATION taoapp){
604:   taoapp->nfeval=0;
605:   taoapp->ngeval=0;
606:   taoapp->nheval=0;
607:   taoapp->nlsolve=0;
608:   return(0);
609: }

613: /*@
614:    TaoAppCounters - Count the number of function, gradient, and
615:    Hessian evaluations, and the number of linear solves.

617:    Collective on TAO_APPLICATION

619:    Input Parameters:
620: .  taopp - the TAO_APPLICATION context

622:    Output Parameters:
623:    stat[4] ,the number of function, gradient, and Hessian evaluations. And
624:     the number of linear solves.

626:    Level: developer

628: .keywords: TAO_APPLICATION, objective

630: .seealso: TaoAppComputeHessian
631: @*/
632: int TaoAppCounters(TAO_APPLICATION taoapp,int stats[4]){
635:   stats[0]=taoapp->nfeval;
636:   stats[1]=taoapp->ngeval;
637:   stats[2]=taoapp->nheval;
638:   stats[3]=taoapp->nlsolve;
639:   return(0);
640: }