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