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: }