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