Actual source code: tao.c

      1: /*$Id: tao.c 1.211 05/05/10 15:21:38-05:00 sarich@zorak.(none) $*/

      3: #include "src/tao_impl.h"      /*I "tao_solver.h"  I*/

      8: /*@C
      9:   TaoMonitor - Monitor the solver and the current solution.  This
     10:   routine will calls the records the iteration number and residual statistics,
     11:   monitors specified by the user, and calls the termaination routine.

     13:    Input Parameters:
     14: +  tao - the TAO_SOLVER context
     15: .  f - the current objective function value
     16: .  iterate - the current iterate number (>=0)
     17: .  fnorm - the gradient norm, square root of the duality gap, or other measure
     18: indicating distince from optimality.  This measure will be recorded and
     19: used for some termination tests.
     20: .  cnorm - the infeasibility of the current solution with regard to the constraints.
     21: -  step - multiple of the step direction added to the previous iterate.

     23:    Output Parameters:
     24: .  reason - The termination reason, which can equal TAO_CONTINUE_ITERATING

     26:    Options Database Key:
     27: .  -tao_monitor - The default monitor, which prints statistics to standard output is used.

     29: .seealso TaoGetTerminationReason(),TaoGetSolutionStatus()

     31:    Level: developer

     33: .keywords: Monitor, convergence
     34: @*/
     35: int TaoMonitor(TAO_SOLVER tao, int iterate, double f, double fnorm, double cnorm, double step, TaoTerminateReason *reason)
     36: {
     37:   int        i,info;
     38:   TaoTruth cstop;
     39:   TaoFunctionBegin;
     40:   if (iterate>=tao->iter){
     41:     TaoLogConvHistory(tao,fnorm,tao->iter);
     42:     tao->norm=fnorm; tao->cnorm=cnorm; tao->fc=f;
     43:     tao->iter=TaoMax(tao->iter,iterate);
     44:     tao->step=step;
     45:   }
     46:   if (iterate==0){
     47:     tao->norm0=fnorm; tao->cnorm0=cnorm;
     48:   }
     49:   info=TaoCheckConvergence(tao,&tao->reason);CHKERRQ(info);
     50:   if (iterate>0){
     51:     info=tao->taoappl->Monitor2(tao->vec_sol,tao->vec_grad,tao->vec_sol_update,&cstop);CHKERRQ(info);
     52:     if (cstop==TAO_TRUE) tao->reason=TAO_CONVERGED_USER;
     53:   }
     54:   for ( i=0; i<tao->numbermonitors; i++ ) {
     55:     info = (*tao->monitor[i])(tao,tao->monitorcontext[i]);CHKERRQ(info);
     56:   }
     57:   info=tao->taoappl->Monitor();CHKERRQ(info);
     58:   *reason = tao->reason;

     60:   TaoFunctionReturn(0);
     61: }

     66: /*@C
     67:   TaoGetSolutionStatus - Get the current iterate, objective value, residual,
     68:   infeasibility, and termination

     70:    Input Parameters:
     71: .  tao - the TAO_SOLVER context

     73:    Output Parameters:
     74: +  iterate - the current iterate number (>=0)
     75: .  f - the current function value
     76: .  gnorm - the square of the gradient norm, duality gap, or other measure
     77: indicating distince from optimality.
     78: .  cnorm - the infeasibility of the current solution with regard to the constraints.
     79: .  xdiff - the step length or trust region radius of the most recent iterate.
     80: -  reason - The termination reason, which can equal TAO_CONTINUE_ITERATING

     82:    Level: intermediate

     84:    Note:
     85:    TAO returns the values set by the solvers in the routine TaoMonitor().

     87:    Note:
     88:    If any of the output arguments are set to TAO_NULL, no value will be
     89:    returned.

     92: .seealso: TaoMonitor(), TaoGetTerminationReason()

     94: .keywords: convergence, monitor
     95: @*/
     96: int TaoGetSolutionStatus(TAO_SOLVER tao, int* iterate, double* f, double* gnorm, double *cnorm, double *xdiff, TaoTerminateReason *reason)
     97: {

     99:   TaoFunctionBegin;
    100:   if (iterate) *iterate=tao->iter;
    101:   if (f) *f=tao->fc;
    102:   if (gnorm) *gnorm=tao->norm;
    103:   if (cnorm) *cnorm=tao->cnorm;
    104:   if (reason) *reason=tao->reason;
    105:   if (xdiff) *xdiff=tao->step;

    107:   TaoFunctionReturn(0);
    108: }

    113: /*@C

    115:    TaoCheckConvergence - Checks the convergence of the solver

    117:    Collective on TAO_SOLVER

    119:    Input Parameters:
    120: .  tao - the TAO_SOLVER context

    122:    Output Parameters:
    123: .  reason - one of

    125: $    TAO_CONVERGED_ATOL (2),        (res <= atol)
    126: $    TAO_CONVERGED_RTOL (3),        (res/res0 <= rtol)
    127: $    TAO_CONVERGED_TRTOL (4),       (xdiff <= trtol)
    128: $    TAO_CONVERGED_MINF (5),        (f <= fmin)
    129: $    TAO_CONVERGED_USER (6),        (user defined)

    131: $    TAO_DIVERGED_MAXITS (-2),      (its>maxits)
    132: $    TAO_DIVERGED_NAN (-4),         (Numerical problems)
    133: $    TAO_DIVERGED_MAXFCN (-5),      (nfunc > maxnfuncts)
    134: $    TAO_DIVERGED_LS_FAILURE (-6),  (line search failure)
    135: $    TAO_DIVERGED_TR_REDUCTION (-7),
    136: $    TAO_DIVERGED_USER (-8),        (user defined)

    138: $    TAO_CONTINUE_ITERATING  (0)

    140:    where
    141: +  res - residual of optimality conditions
    142: .  res0 - initial residual of optimality conditions
    143: .  xdiff - current trust region size
    144: .  f - function value
    145: .  atol - absolute tolerance
    146: .  rtol - relative tolerance
    147: .  its - current iterate number
    148: .  maxits - maximum number of iterates
    149: .  nfunc - number of function evaluations
    150: -  maxnfuncts - maximum number of function evaluations

    153:    Level: advanced

    155: .seealso: TaoGetTerminationReason()

    157: .keywords: Convergence

    159: @*/
    160: int TaoCheckConvergence(TAO_SOLVER tao, TaoTerminateReason *reason)
    161: {
    162:   int        info;

    164:   TaoFunctionBegin;
    165:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    166:   if (tao->converged){
    167:     info = (*tao->converged)(tao,tao->cnvP);CHKERRQ(info);
    168:   }
    169:   if (reason) *reason=tao->reason;

    171:   TaoFunctionReturn(0);
    172: }

    176: /*@
    177:    TaoView - Prints the TAO_SOLVER data structure.

    179:    Collective on TAO_SOLVER

    181:    Input Parameters:
    182: .  tao - the TAO_SOLVER context

    184:    Options Database Key:
    185: .  -tao_view - Calls TaoView() at end of TaoSolve()

    187:    Level: beginner

    189: .seealso: TaoGetTerminationReason(), TaoGetSolutionStatus(), TaoViewLinearSolver()

    191: .keywords: View

    193: @*/
    194: int TaoView(TAO_SOLVER tao)
    195: {
    196:   int        info;
    197:   TaoMethod  type;

    199:   TaoFunctionBegin;
    200:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);

    202:   info = TaoPrintStatement(tao,"TAO_SOLVER:\n");CHKERRQ(info);
    203:   info = TaoGetMethod(tao,&type);CHKERRQ(info);
    204:   if (type) {
    205:     info = TaoPrintString(tao,"  method: %s\n",type);CHKERRQ(info);
    206:   } else {
    207:     info = TaoPrintStatement(tao,"  method: not set yet\n");CHKERRQ(info);
    208:   }
    209:   if (tao->view) {
    210:     info = (*tao->view)(tao,tao->data);CHKERRQ(info);
    211:   }
    212:   if (tao->lm>0){
    213:     info = TaoPrintInt(tao,"  Limited memory variable metric vectors =%d\n",tao->lm);CHKERRQ(info);
    214:   }
    215:
    216:   info=TaoPrintDouble(tao,"  convergence tolerances: fatol=%g,",tao->fatol);CHKERRQ(info);
    217:   info=TaoPrintDouble(tao," frtol=%g\n",tao->frtol);CHKERRQ(info);

    219:   info=TaoPrintDouble(tao,"  convergence tolerances: gatol=%g,",tao->gatol);CHKERRQ(info);
    220:   info=TaoPrintDouble(tao," trtol=%g,",tao->trtol);CHKERRQ(info);
    221:   info=TaoPrintDouble(tao," gttol=%g\n",tao->gttol);CHKERRQ(info);

    223:   info = TaoPrintDouble(tao,"  Residual in Function/Gradient:=%e\n",tao->norm);CHKERRQ(info);

    225:   if (tao->cnorm>0 || tao->catol>0 || tao->crtol>0){
    226:     info=TaoPrintStatement(tao,"  convergence tolerances:");CHKERRQ(info);
    227:     info=TaoPrintDouble(tao," catol=%g,",tao->catol);CHKERRQ(info);
    228:     info=TaoPrintDouble(tao," crtol=%g\n",tao->crtol);CHKERRQ(info);
    229:     info = TaoPrintDouble(tao,"  Residual in Constraints:=%e\n",tao->cnorm);CHKERRQ(info);
    230:   }

    232:   if (tao->trtol>0){
    233:     info=TaoPrintDouble(tao,"  convergence tolerances: trtol=%g\n",tao->trtol);CHKERRQ(info);
    234:     info=TaoPrintDouble(tao,"  Final step size/trust region radius:=%g\n",tao->step);CHKERRQ(info);
    235:   }

    237:   if (tao->fmin>-1.e25){
    238:     info=TaoPrintDouble(tao,"  convergence tolerances: function minimum=%g\n",tao->fmin);CHKERRQ(info);
    239:   }
    240:   info = TaoPrintDouble(tao,"  Objective value=%e\n",tao->fc);CHKERRQ(info);

    242:   info = TaoPrintInt(tao,"  total number of iterations=%d,          ",tao->iter);CHKERRQ(info);
    243:   info = TaoPrintInt(tao,"              (max: %d)\n",tao->max_its);CHKERRQ(info);

    245:   if (tao->nfuncs>0){
    246:     info = TaoPrintInt(tao,"  total number of function evaluations=%d,",tao->nfuncs);CHKERRQ(info);
    247:     info = TaoPrintInt(tao,"                max: %d\n",tao->max_funcs);CHKERRQ(info);
    248:   }
    249:   if (tao->ngrads>0){
    250:     info = TaoPrintInt(tao,"  total number of function/gradient evaluations=%d,",tao->ngrads);CHKERRQ(info);
    251:     info = TaoPrintInt(tao,"    (max: %d)\n",tao->max_funcs);CHKERRQ(info);
    252:   }
    253:   if (tao->linear_its>0){
    254:     info = TaoPrintInt(tao,"  total Krylov method iterations=%d\n",tao->linear_its);CHKERRQ(info);
    255:   }
    256:   if (tao->nhesss>0){
    257:     info = TaoPrintInt(tao,"  total number of Hessian evaluations=%d\n",tao->nhesss);CHKERRQ(info);
    258:   }
    259:   if (tao->nvfunc>0){
    260:     info = TaoPrintInt(tao,"  total number of constraint function evaluations=%d\n",tao->nvfunc);CHKERRQ(info);
    261:   }
    262:   if (tao->njac>0){
    263:     info = TaoPrintInt(tao,"  total number of Jacobian evaluations=%d\n",tao->njac);CHKERRQ(info);
    264:   }

    266:   if (tao->reason>0){
    267:     info = TaoPrintStatement(tao,"  Solution found\n");CHKERRQ(info);
    268:   } else {
    269:     info = TaoPrintInt(tao,"  Solver terminated: %d\n",tao->reason);CHKERRQ(info);
    270:   }

    272:   TaoFunctionReturn(0);
    273: }

    277: /* ----------- Routines to set solver parameters ---------- */

    281: /*@
    282:    TaoSetGradientTolerances - Sets the stopping criteria in terms of the norm
    283:    of the Lagrangian function.  The algorithm will terminate when the norm
    284:    of the gradient is less that the absolute tolerance, or when the norm
    285:    of the gradient has been reduced by a factor of the reduction tolerance,
    286:    or when the norm of the gradient divided by the absolute value of the
    287:    objective function is less than the relative tolerance.

    289:    Collective on TAO_SOLVER

    291:    Input Parameters:
    292: +  tao - the TAO_SOLVER solver context
    293: .  gatol - stop if norm of gradient is less than
    294: .  grtol - stop if relative norm of gradient is less than
    295: -  gttol - stop if norm of gradient is reduced by a factor of

    297:    Options Database Keys:
    298: +  -tao_gatol <gatol> - sets gatol
    299: .  -tao_grtol <grtol> - sets grtol
    300: -  -tao_gttol <gttol> - sets gttol

    302:    Level: intermediate

    304: .keywords: Gradient, options, convergence

    306: .seealso: TaoSetTolerances(), TaoGetGradientTolerances()
    307: @*/
    308: int TaoSetGradientTolerances(TAO_SOLVER tao,double gatol, double grtol, double gttol)
    309: {
    310:   int info;
    311:   double zero=0.0;
    312:   TaoFunctionBegin;
    313:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);

    315:   if (gatol==TAO_DEFAULT){}
    316:   else if (gatol<0){
    317:     info=PetscLogInfo((tao,"Absolute Gradient tolerance < 0 and ignored")); CHKERRQ(info);
    318:     CHKERRQ(info); }
    319:   else{
    320:     tao->gatol      = TaoMax(zero,gatol);
    321:   }

    323:   if (grtol==TAO_DEFAULT){}
    324:   else if (grtol<0){
    325:     info=PetscLogInfo((tao,"Relative Gradient tolerance < 0 and ignored"));
    326:     CHKERRQ(info); }
    327:   else{
    328:     tao->grtol      = TaoMax(zero,grtol);
    329:   }

    331:   if (gttol==TAO_DEFAULT){}
    332:   else if (gttol<0){
    333:     info=PetscLogInfo((tao,"Gradient reduction tolerance < 0 and ignored"));
    334:     CHKERRQ(info); }
    335:   else{
    336:     tao->gttol      = TaoMax(zero,gttol);
    337:   }

    340:   TaoFunctionReturn(0);
    341: }

    343: /* ----------- Routines to set solver parameters ---------- */

    347: /*@C
    348:    TaoGetGradientTolerances - Returns the gradient termination tolerances.

    350:    Collective on TAO_SOLVER

    352:    Input Parameters:
    353: .  tao - the TAO_SOLVER tao context

    355:    Output Parameters:
    356: +  gatol - the absolute gradient tolerance
    357: .  grtol - the relative gradient tolerance
    358: -  gttol - the gradient reduction tolerance

    360:    Level: intermediate

    362: .keywords: options, convergence, View

    364: .seealso: TaoSetGradientTolerances()
    365: @*/
    366: int TaoGetGradientTolerances(TAO_SOLVER tao,double *gatol, double *grtol, double *gttol)
    367: {
    368:   TaoFunctionBegin;
    369:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    370:   if (gatol) *gatol = tao->gatol;
    371:   if (grtol) *grtol = tao->grtol;
    372:   if (gttol) *gttol = tao->gttol;
    373:   TaoFunctionReturn(0);
    374: }

    378: /*@
    379:    TaoSetFunctionLowerBound - Sets a bound on the solution objective value.
    380:    When an approximate solution with an objective value below this number
    381:    has been found, the solver will terminate.

    383:    Collective on TAO_SOLVER

    385:    Input Parameters:
    386: +  tao - the TAO_SOLVER solver context
    387: -  fmin - the tolerance

    389:    Options Database Keys:
    390: .    -tao_fmin <fmin> - sets the minimum function value

    392:    Level: intermediate

    394: .keywords: options, View, Bounds,

    396: .seealso: TaoSetTolerances()
    397: @*/
    398: int TaoSetFunctionLowerBound(TAO_SOLVER tao,double fmin)
    399: {
    400:   double dflt=-1.0e+30;
    401:   TaoFunctionBegin;
    402:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    403:   if (fmin != TAO_DEFAULT)  tao->fmin = fmin;
    404:   else tao->fmin=dflt;
    405:   TaoFunctionReturn(0);
    406: }

    411: /*@
    412:    TaoSetMaximumIterates - Sets a maximum number of iterates.

    414:    Collective on TAO_SOLVER

    416:    Input Parameters:
    417: +  tao - the TAO_SOLVER solver context
    418: -  maxits - the maximum number of iterates (>=0)

    420:    Options Database Keys:
    421: .    -tao_max_it <its> - sets the maximum number of iterations

    423:    Level: intermediate

    425: .keywords: options, Iterate, convergence

    427: .seealso: TaoSetTolerances(), TaoSetMaximumFunctionEvaluations()
    428: @*/
    429: int TaoSetMaximumIterates(TAO_SOLVER tao,int maxits)
    430: {
    431:   int zero=0;
    432:   TaoFunctionBegin;
    433:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    434:   if (maxits != TAO_DEFAULT)  tao->max_its = TaoMax(zero,maxits);
    435:   TaoFunctionReturn(0);
    436: }

    441: /*@
    442:    TaoSetMaximumFunctionEvaluations - Sets a maximum number of
    443:    function evaluations.

    445:    Collective on TAO_SOLVER

    447:    Input Parameters:
    448: +  tao - the TAO_SOLVER solver context
    449: -  nfcn - the maximum number of function evaluations (>=0)

    451:    Options Database Keys:
    452: .    -tao_max_funcs <nfcn> - sets the maximum number of function evaluations

    454:    Level: intermediate

    456: .keywords: options, Iterate,  convergence

    458: .seealso: TaoSetTolerances(), TaoSetMaximumIterates()
    459: @*/
    460: int TaoSetMaximumFunctionEvaluations(TAO_SOLVER tao,int nfcn)
    461: {
    462:   int zero=0;
    463:   TaoFunctionBegin;
    464:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    465:   if (nfcn != TAO_DEFAULT)  tao->max_funcs = TaoMax(zero,nfcn);
    466:   TaoFunctionReturn(0);
    467: }

    472: /*@
    473:    TaoSetTolerances - Sets convergence parameters. TAO tries to satisfy an
    474:    absolute stopping criteria or a relative stopping criteria.
    475:
    476:    Collective on TAO_SOLVER

    478:    Input Parameters:
    479: +  tao - the TAO_SOLVER solver context
    480: .  fatol - absolute convergence tolerance
    481: .  frtol - relative convergence tolerance
    482: .  catol -  allowable error in constraints
    483: -  crtol - allowable relative error in constraints

    485:    Options Database Keys:
    486: +  -tao_fatol <fatol> - Sets fatol
    487: .  -tao_frtol <frtol> - Sets frtol
    488: .  -tao_catol <catol> - Sets catol
    489: -  -tao_crtol <crtol> - Sets crtol

    491:    Absolute Stopping Criteria:
    492: $  f <= f + fatol
    493: $  B1 - catol <= B(X) <= B2 + catol

    495:    Relative stopping criteria:
    496: $  f <= f + frtol*|f|
    497: $  B1 - catol <= B(X) <= B2 + catol

    499:    Level: beginner

    501: .keywords: options, convergence

    503: .seealso: TaoSetMaximumIterates(),TaoSetTrustRegionTolerance(), TaoSetGradientTolerances
    504: TaoSetMaximumFunctionEvaluations()
    505: @*/
    506: int TaoSetTolerances(TAO_SOLVER tao,double fatol,double frtol,double catol,double crtol)
    507: {
    508:   int info;
    509:   double zero=0.0;
    510:   TaoFunctionBegin;
    511:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);

    513:   if (fatol==TAO_DEFAULT){}
    514:   else if (fatol<0){
    515:     info=PetscLogInfo((tao,"Absolute convergence tolerance < 0 and ignored"));
    516:     CHKERRQ(info); }
    517:   else{
    518:     tao->fatol      = TaoMax(zero,fatol);
    519:   }

    521:   if (frtol==TAO_DEFAULT){}
    522:   else if (frtol<0){
    523:     info=PetscLogInfo((tao,"Relative convergence tolerance < 0 and ignored"));
    524:     CHKERRQ(info); }
    525:   else{
    526:     tao->frtol      = TaoMax(zero,frtol);
    527:   }

    529:   if (catol==TAO_DEFAULT){}
    530:   else if (catol<0){
    531:     info=PetscLogInfo((tao,"Absolute constraint tolerance < 0 and ignored"));
    532:     CHKERRQ(info); }
    533:   else{
    534:     tao->catol      = TaoMax(zero,catol);
    535:   }

    537:   if (crtol==TAO_DEFAULT){}
    538:   else if (crtol<0){
    539:     info=PetscLogInfo((tao,"Relative constraint tolerance < 0 and ignored"));
    540:     CHKERRQ(info); }
    541:   else{
    542:     tao->crtol      = TaoMax(zero,crtol);
    543:   }

    545:   TaoFunctionReturn(0);
    546: }

    552: /*@C
    553:    TaoGetTolerances - Gets convergence parameters.
    554:

    556:    Collective on TAO_SOLVER

    558:    Input Parameters:
    559: .  tao - the TAO_SOLVER solver context

    561:    Input Parameters:
    562: +  fatol - absolute convergence tolerance
    563: .  frtol - relative convergence tolerance
    564: .  catol -  trust region convergence tolerance
    565: -  crtol - convergence of the function evaluates less than this tolerance

    567:    Level: advanced

    569: .keywords: options, convergence

    571: .seealso: TaoSetTolerances
    572: @*/
    573: int TaoGetTolerances(TAO_SOLVER tao,double *fatol,double *frtol,double *catol,double *crtol)
    574: {
    575:   TaoFunctionBegin;
    576:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    577:   if (fatol) *fatol = tao->fatol;
    578:   if (frtol) *frtol = tao->frtol;
    579:   if (catol) *catol = tao->catol;
    580:   if (crtol) *crtol = tao->crtol;
    581:   TaoFunctionReturn(0);
    582: }

    585: /* ------------ Routines to set performance monitoring options ----------- */

    589: /*@C
    590:    TaoSetMonitor - Sets an ADDITIONAL function that is to be used at every
    591:    iteration of the unconstrained minimization solver to display the iteration's
    592:    progress.

    594:    Collective on TAO_SOLVER

    596:    Input Parameters:
    597: +  tao - the TAO_SOLVER solver context
    598: .  mymonitor - monitoring routine
    599: -  mctx - [optional] user-defined context for private data for the
    600:           monitor routine (may be TAO_NULL)

    602:    Calling sequence of mymonitor:
    603: $     int mymonitor(TAO_SOLVER tao,void *mctx)

    605: +    tao - the TAO_SOLVER solver context
    606: -    mctx - [optional] monitoring context

    609:    Options Database Keys:
    610: +    -tao_monitor        - sets TaoDefaultMonitor()
    611: .    -tao_smonitor        - sets short monitor
    612: -    -tao_cancelmonitors - cancels all monitors that have been hardwired into a code by calls to TaoSetMonitor(), but does not cancel those set via the options database.

    614:    Notes:
    615:    Several different monitoring routines may be set by calling
    616:    TaoSetMonitor() multiple times; all will be called in the
    617:    order in which they were set.

    619:    Level: intermediate

    621: .keywords: options, monitor, View

    623: .seealso: TaoDefaultMonitor(), TaoClearMonitor(),  TaoSetDestroyRoutine()
    624: @*/
    625: int TaoSetMonitor(TAO_SOLVER tao,int (*mymonitor)(TAO_SOLVER,void*),void *mctx)
    626: {
    627:   TaoFunctionBegin;
    628:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    629:   if (tao->numbermonitors >= MAX_TAO_MONITORS) {
    630:     SETERRQ(1,"Too many monitors set");
    631:   }

    633:   tao->monitor[tao->numbermonitors]           = mymonitor;
    634:   tao->monitorcontext[tao->numbermonitors++]  = (void*)mctx;
    635:   TaoFunctionReturn(0);
    636: }

    640: /*@
    641:    TaoClearMonitor - Clears all the monitor functions for a TAO_SOLVER object.

    643:    Collective on TAO_SOLVER

    645:    Input Parameters:
    646: .  tao - the TAO_SOLVER solver context

    648:    Options Database:
    649: .  -tao_cancelmonitors - cancels all monitors that have been hardwired
    650:     into a code by calls to TaoSetMonitor(), but does not cancel those
    651:     set via the options database

    653:    Notes:
    654:    There is no way to clear one specific monitor from a TAO_SOLVER object.

    656:    Level: advanced

    658: .keywords: options, monitor, View

    660: .seealso: TaoDefaultMonitor(), TaoSetMonitor()
    661: @*/
    662: int TaoClearMonitor(TAO_SOLVER tao)
    663: {
    664:   TaoFunctionBegin;
    665:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    666:   tao->numbermonitors = 0;
    667:   TaoFunctionReturn(0);
    668: }

    672: /*@C
    673:    TaoSetConvergenceTest - Sets the function that is to be used
    674:    to test for convergence of the iterative minimization solution.

    676:    Collective on TAO_SOLVER

    678:    Input Parameters:
    679: +  tao - the TAO_SOLVER solver context
    680: .  conv - routine to test for convergence
    681: -  cctx - [optional] context for private data for the convergence routine
    682:           (may be TAO_NULL)

    684:    Calling sequence of conv:
    685: $     int conv (TAO_SOLVER tao, void *cctx)

    687: +    tao - the TAO_SOLVER solver context
    688: -    cctx - [optional] convergence context

    690:    Note: This routine should call TaoSetTerminationReason().

    692:    Level: intermediate

    694: .keywords: options, convergence

    696: .seealso: TaoSetTerminationReason(), TaoGetSolutionStatus(), TaoGetTolerances(),  TaoGetGradientTolerances()

    698: @*/
    699: int TaoSetConvergenceTest(TAO_SOLVER tao,int (*conv)(TAO_SOLVER,void*),void *cctx)
    700: {
    701:   TaoFunctionBegin;
    702:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    703:   (tao)->converged = conv;
    704:   (tao)->cnvP      = cctx;
    705:   TaoFunctionReturn(0);
    706: }

    711: /*@C
    712:    TaoGetTerminationReason - Gets the reason the TAO_SOLVER iteration was stopped.

    714:    Not Collective

    716:    Input Parameter:
    717: .  tao - the TAO_SOLVER solver context

    719:    Output Parameter:
    720: .  reason - one of

    722: $    TAO_CONVERGED_ATOL (2),        (res <= atol)
    723: $    TAO_CONVERGED_RTOL (3),        (res/res0 <= rtol)
    724: $    TAO_CONVERGED_TRTOL (4),       (xdiff <= trtol)
    725: $    TAO_CONVERGED_MINF (5),        (f <= fmin)
    726: $    TAO_CONVERGED_USER (6),        (user defined)

    728: $    TAO_DIVERGED_MAXITS (-2),      (its>maxits)
    729: $    TAO_DIVERGED_NAN (-4),         (Numerical problems)
    730: $    TAO_DIVERGED_MAXFCN (-5),      (nfunc > maxnfuncts)
    731: $    TAO_DIVERGED_LS_FAILURE (-6),  (line search failure)
    732: $    TAO_DIVERGED_TR_REDUCTION (-7),
    733: $    TAO_DIVERGED_USER (-8),        (user defined)

    735: $    TAO_CONTINUE_ITERATING  (0)

    737:    where
    738: +  res - residual of optimality conditions
    739: .  res0 - initial residual of optimality conditions
    740: .  xdiff - current trust region size
    741: .  f - function value
    742: .  atol - absolute tolerance
    743: .  rtol - relative tolerance
    744: .  its - current iterate number
    745: .  maxits - maximum number of iterates
    746: .  nfunc - number of function evaluations
    747: -  maxnfuncts - maximum number of function evaluations

    749:    Level: intermediate

    751: .keywords: convergence, View

    753: .seealso: TaoSetConvergenceTest(), TaoSetTolerances()
    754: @*/
    755: int TaoGetTerminationReason(TAO_SOLVER tao,TaoTerminateReason *reason)
    756: {
    757:   TaoFunctionBegin;
    758:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    759:   *reason = tao->reason;
    760:   TaoFunctionReturn(0);
    761: }

    765: /*@
    766:    TaoSetConvergenceHistory - Sets the array used to hold the convergence history.

    768:    Collective on TAO_SOLVER

    770:    Input Parameters:
    771: +  tao - the TAO_SOLVER solver context
    772: .  a   - array to hold history
    773: .  its - integer array holds the number of linear iterations (or
    774:          negative if not converged) for each solve.
    775: .  na  - size of a and its
    776: -  reset - TAO_TRUE indicates each new minimization resets the history counter to zero,
    777:            else it continues storing new values for new minimizations after the old ones

    779:    Notes:
    780:    If set, this array will contain the gradient norms computed at each step.

    782:    This routine is useful, e.g., when running a code for purposes
    783:    of accurate performance monitoring, when no I/O should be done
    784:    during the section of code that is being timed.

    786:    Level: intermediate

    788: .keywords: options, view, monitor, convergence, history

    790: .seealso: TaoGetConvergenceHistory()

    792: @*/
    793: int TaoSetConvergenceHistory(TAO_SOLVER tao, double *a, int *its,int na,TaoTruth reset)
    794: {
    795:   TaoFunctionBegin;
    796:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    797:   if (na) TaoValidScalarPointer(a,2);
    798:   tao->conv_hist       = a;
    799:   tao->conv_hist_its   = its;
    800:   tao->conv_hist_max   = na;
    801:   tao->conv_hist_reset = reset;
    802:   TaoFunctionReturn(0);
    803: }

    807: /*@C
    808:    TaoGetConvergenceHistory - Gets the array used to hold the convergence history.

    810:    Collective on TAO_SOLVER

    812:    Input Parameter:
    813: .  tao - the TAO_SOLVER solver context

    815:    Output Parameters:
    816: +  a   - array to hold history
    817: .  its - integer array holds the number of linear iterations (or
    818:          negative if not converged) for each solve.
    819: -  na  - size of a and its

    821:    Notes:
    822:     The calling sequence for this routine in Fortran is
    823: $   call TaoGetConvergenceHistory(TAO_SOLVER tao, integer na, integer info)

    825:    This routine is useful, e.g., when running a code for purposes
    826:    of accurate performance monitoring, when no I/O should be done
    827:    during the section of code that is being timed.

    829:    Level: advanced

    831: .keywords: convergence, history, monitor, View

    833: .seealso: TaoSetConvergencHistory()

    835: @*/
    836: int TaoGetConvergenceHistory(TAO_SOLVER tao, double **a, int **its,int *na)
    837: {
    838:   TaoFunctionBegin;
    839:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    840:   if (a)   *a   = tao->conv_hist;
    841:   if (its) *its = tao->conv_hist_its;
    842:   if (na) *na   = tao->conv_hist_len;
    843:   TaoFunctionReturn(0);
    844: }

    849: /*@
    850:    TaoSolve - Solves an unconstrained minimization problem.  Call TaoSolve()
    851:    after calling TaoCreate() and optional routines of the form TaoSetXXX().

    853:    Collective on TAO_SOLVER

    855:    Input Parameters:
    856: .  tao - the TAO_SOLVER solver context

    858:    Notes:
    859:    By default the TAO solvers use an initial starting guess of zero.  To
    860:    provide an alternative initial guess, the user must call TaoAppSetInitialSolutionVec()
    861:    before calling TaoSolve().

    863:    Level: advanced

    865: .keywords: Solve

    867: .seealso: TaoCreate(), TaoDestroy()
    868: @*/
    869: int TaoSolve(TAO_SOLVER tao)
    870: {
    871:   int      info;
    872:   TaoVec   *xx;

    874:   TaoFunctionBegin;
    875:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    876:   info = TaoGetSolution(tao,&xx);CHKERRQ(info);
    877:   info = tao->taoappl->InitializeVariables(xx);CHKERRQ(info);
    878:   info = TaoSetUp(tao);CHKERRQ(info);
    879:   info = TaoSetDefaultStatistics(tao); CHKERRQ(info);
    880:   if (tao->solve){ info = (*(tao)->solve)(tao,tao->data);CHKERRQ(info); }
    881:   if (tao->viewtao) { info = TaoView(tao);CHKERRQ(info); }
    882:   if (tao->viewksptao) { info = TaoViewLinearSolver(tao);CHKERRQ(info); }
    883:   TaoFunctionReturn(0);
    884: }

    889: /*@C
    890:    TaoGetMethod - Gets the TAO_SOLVER method type and name (as a string).

    892:    Not Collective

    894:    Input Parameter:
    895: .  tao - the TAO_SOLVER solver context

    897:    Output Parameter:
    898: .  type - TAO_SOLVER method (a charactor string)

    900:    Level: intermediate

    902: .keywords: method
    903: @*/
    904: int TaoGetMethod(TAO_SOLVER tao, TaoMethod *type)
    905: {
    906:   TaoFunctionBegin;
    907:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    908:   *type = tao->type_name;
    909:   TaoFunctionReturn(0);
    910: }

    915: /*@C
    916:    TaoSetStepDirectionVector - Sets the vector where the solution update is
    917:    stored.

    919:    Not Collective, but Vec is parallel if TAO_SOLVER is parallel

    921:    Input Parameter:
    922: +  tao - the TAO_SOLVER solver context
    923: -  dx - the step direction vector

    925:    Level: developer

    927: .keywords: solution, step direction

    929: .seealso: TaoGetSolution(), TaoGetStepDirectionVector()
    930: @*/
    931: int TaoSetStepDirectionVector(TAO_SOLVER tao,TaoVec* dx)
    932: {
    933:   TaoFunctionBegin;
    934:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    935:   tao->vec_sol_update=dx;
    936:   TaoFunctionReturn(0);
    937: }

    942: /*@C
    943:    TaoGetStepDirectionVector - Returns the vector where the solution update is
    944:    stored.

    946:    Not Collective, but Vec is parallel if TAO_SOLVER is parallel

    948:    Input Parameter:
    949: .  tao - the TAO_SOLVER solver context

    951:    Output Parameter:
    952: .  xx - the solution update

    954:    Level: developer

    956: .keywords: solution

    958: .seealso: TaoGetSolution()
    959: @*/
    960: int TaoGetStepDirectionVector(TAO_SOLVER tao,TaoVec** xx)
    961: {
    962:   TaoFunctionBegin;
    963:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    964:   *xx = tao->vec_sol_update;
    965:   TaoFunctionReturn(0);
    966: }

    972: /*@
    973:   TaoSetTrustRegionTolerance - Sets a minimum step size or trust region radius.  The
    974:   solver will terminate when the step size or radius of the trust region is smaller
    975:   than this tolerance.
    976:
    977:   Collective on TAO_SOLVER
    978:
    979:   Input Parameters:
    980: +  tao - the TAO_SOLVER solver context
    981: -  steptol - tolerance
    982:
    983:   Options Database Key:
    984: .  -tao_steptol <trtol> - Sets steptol
    985:
    986:   Level: intermediate
    987:
    988: .keywords: options, convergence, trust region
    989:
    990: .seealso: TaoSetTolerances()
    991: @*/
    992: int TaoSetTrustRegionTolerance(TAO_SOLVER tao,double steptol)
    993: {
    994:   double zero=0.0, dflt=0.0;

    996:   TaoFunctionBegin;
    997:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    998:   if (steptol != TAO_DEFAULT)  tao->xtol = TaoMax(zero,steptol);
    999:   else tao->xtol=dflt;
    1000:   tao->trtol=steptol;
    1001:   TaoFunctionReturn(0);
    1002: }

    1006: /*@C
    1007:    TaoGetTrustRegionRadius - Gets the current trust region radius

    1009:    Collective on TAO_SOLVER

    1011:    Input Parameter:
    1012: .  tao - a TAO optimization solver

    1014:    Output Parameter:
    1015: .  radius - the trust region radius

    1017:    Level: advanced

    1019: .keywords: options, view, trust region

    1021: .seealso: TaoSetTrustRegionRadius(), TaoSetTrustRegionTolerance()
    1022: @*/
    1023: int TaoGetTrustRegionRadius(TAO_SOLVER tao,double *radius)
    1024: {
    1025:   TaoFunctionBegin;
    1026:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    1027:   *radius=tao->step;
    1028:   TaoFunctionReturn(0);
    1029: }
    1032: /*@C
    1033:    TaoGetInitialTrustRegionRadius - Gets the initial trust region radius

    1035:    Collective on TAO_SOLVER

    1037:    Input Parameter:
    1038: .  tao - a TAO optimization solver

    1040:    Output Parameter:
    1041: .  radius - the initial trust region radius

    1043:    Level: intermediate

    1045: .keywords: options, trust region

    1047: .seealso: TaoGetTrustRegionRadius(), TaoSetTrustRegionRadius()
    1048: @*/
    1049: int TaoGetInitialTrustRegionRadius(TAO_SOLVER tao,double *radius)
    1050: {
    1051:   TaoFunctionBegin;
    1052:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    1053:   *radius=tao->trust0;
    1054:   TaoFunctionReturn(0);
    1055: }

    1059: /*@
    1060:    TaoSetTrustRegionRadius - Sets the initial trust region radius.

    1062:    Collective on TAO_SOLVER

    1064:    Input Parameter:
    1065: +  tao - a TAO optimization solver
    1066: -  radius - the trust region radius

    1068:    Level: intermediate

    1070:    Options Database Key:
    1071: .  -tao_trust0

    1073: .keywords: trust region

    1075: .seealso: TaoGetTrustRegionRadius(), TaoSetTrustRegionTolerance()
    1076: @*/
    1077: int TaoSetTrustRegionRadius(TAO_SOLVER tao,double radius)
    1078: {
    1079:   TaoFunctionBegin;
    1080:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    1081:   tao->trust0=radius;
    1082:   tao->step=radius;
    1083:   TaoFunctionReturn(0);
    1084: }

    1089: /*@
    1090:    TaoSetVariableBounds - Sets lower and upper bounds on the variables.

    1092:    Collective on TAO_SOLVER

    1094:    Input Parameters:
    1095: +  tao - the TAO_SOLVER solver context
    1096: .  xxll - vector of lower bounds upon the solution vector
    1097: -  xxuu - vector of upper bounds upon the solution vector

    1099:    Level: developer

    1101: .keywords: bounds

    1103: .seealso: TaoGetVariableBounds(), TaoAppSetVariableBounds()
    1104: @*/
    1105: int TaoSetVariableBounds(TAO_SOLVER tao,TaoVec *xxll,TaoVec *xxuu)
    1106: {
    1107:   int info;
    1108:   double dd;
    1109:   TaoVec *xx;
    1110:   TaoTruth flag;

    1112:   TaoFunctionBegin;
    1113:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    1114:   info=TaoGetSolution(tao,&xx);CHKERRQ(info);
    1115:   if (xxll){
    1116:     info=xx->Compatible(xxll,&flag); CHKERRQ(info);
    1117:     if (flag == TAO_FALSE){
    1118:       SETERRQ(1,"Vector of lower bounds not Compatible with Variable Vector");
    1119:     }
    1120:     if (tao->XL==0){
    1121:       dd=-TAO_INFINITY;
    1122:       info = xxll->SetToConstant(dd); CHKERRQ(info);
    1123:     }
    1124:   }
    1125:   if (xxuu){
    1126:     info=xx->Compatible(xxuu,&flag); CHKERRQ(info);
    1127:     if (flag == TAO_FALSE){
    1128:       SETERRQ(1,"Vector of upper bounds not Compatible with Variable vector");
    1129:     }
    1130:     if (tao->XU==0){
    1131:       dd= TAO_INFINITY;
    1132:       info = xxuu->SetToConstant(dd); CHKERRQ(info);
    1133:     }
    1134:   }
    1135:   tao->XL=xxll;
    1136:   tao->XU=xxuu;
    1137:   TaoFunctionReturn(0);
    1138: }

    1142: /*@C
    1143:    TaoGetDualVariables - Gets the dual variables corresponding to
    1144:    the bounds of the variables.

    1146:    Collective on TAO_SOLVER

    1148:    Input Parameter:
    1149: +  tao - the TAO_SOLVER solver context
    1150: .  DXL   - vector to place the dual variables of the lower bounds
    1151: -  DXU   - vector to place the dual variables of the upper bounds

    1153:    Output Parameter:
    1154: +  DXL   - dual variables of the lower bounds
    1155: -  DXU   - dual variables of the upper bounds

    1157:    Level: advanced

    1159: .keywords: dual, bounds

    1161: .seealso: TaoGetVariableBounds()
    1162: @*/
    1163: int TaoGetDualVariables(TAO_SOLVER tao, TaoVec *DXL, TaoVec *DXU)
    1164: {
    1165:   int info;
    1166:   TaoTruth flag;
    1167:   TaoVec *XL, *XU;

    1169:   TaoFunctionBegin;
    1170:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    1171:   info=TaoGetVariableBounds(tao,&XL,&XU);CHKERRQ(info);

    1173:   info=DXU->Compatible(XU,&flag); CHKERRQ(info);
    1174:   if (flag == TAO_FALSE){
    1175:     SETERRQ(1,"Dual bound vectors not Compatible");
    1176:   }

    1178:   info=DXL->Compatible(XL,&flag); CHKERRQ(info);
    1179:   if (flag == TAO_FALSE){
    1180:     SETERRQ(1,"Dual bound vectors not Compatible");
    1181:   }

    1183:   if (tao->CopyDuals){
    1184:     info = (*tao->CopyDuals)(tao,DXL,DXU,tao->data);CHKERRQ(info);
    1185:   } else {
    1186:     info=DXL->SetToZero();CHKERRQ(info);
    1187:     info=DXU->SetToZero();CHKERRQ(info);
    1188:   }

    1190:   TaoFunctionReturn(0);
    1191: }

    1196: /* ---------------------------------------------------------- */
    1197: /* @C
    1198:    TaoSetInitialVector - Sets the initial vector used by the TAO
    1199:    solver.

    1201:    Collective on TAO_SOLVER

    1203:    Input Parameters:
    1204: +  tao - the TAO solver
    1205: -  xx0 - vector used for initial point (set xx0==TAO_NULL for default)

    1207:    Notes:
    1208:    By default the TAO solvers use an initial starting guess of zero.
    1209:    To provide an alternative initial guess, the user must call
    1210:    TaoSetInitialVector() before calling TaoSolve().

    1212:    This vector will replace the variable vector set in the TaoCreate() routine.

    1214:    The user is responsible for destroying this vector.

    1216:    If this vector is TAO_NULL, TAO will use the set the previous variable
    1217:    vector to a default starting point.

    1219:    Level: developer

    1221: .seealso: TaoSolve(), TaoGetSolution()
    1222: @ */
    1223: int TaoSetInitialVector(TAO_SOLVER tao,TaoVec *xx0)
    1224: {
    1225:   int info;
    1226:   TaoTruth flag;
    1227:   TaoVec* X;

    1229:   TaoFunctionBegin;
    1230:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    1231:   if (xx0==TAO_NULL){
    1232:     //    tao->userstart=TAO_FALSE;
    1233:   } else {
    1234:     info=TaoGetSolution(tao,&X);CHKERRQ(info);
    1235:     info=X->Compatible(xx0,&flag);CHKERRQ(info);
    1236:     if (flag == TAO_FALSE){
    1237:       SETERRQ(1,"New TAO variable vector must have identical structure as the previous variable vector.");
    1238:     }
    1239:     tao->vec_sol=xx0;
    1240:     /*    info=X->CopyFrom(xx0);CHKERRQ(info);   */
    1241:     //    tao->userstart=TAO_TRUE;
    1242:   }
    1243:   TaoFunctionReturn(0);
    1244: }

    1249: /*@C
    1250:    TaoGetVariableBounds - Sets the vector pointers to the vectors
    1251:    containing the upper and lower bounds on the variables.

    1253:    Collective on TAO_SOLVER

    1255:    Input Parameter:
    1256: .  tao - the TAO_SOLVER solver context

    1258:    Output Parameters:
    1259: +  xxll - Pointer to lower bounds on all the variables
    1260: -  xxuu - Pointer to upper bounds on all the variables

    1262:    Level: advanced

    1264: .keywords: bounds, View

    1266: @*/
    1267: int TaoGetVariableBounds(TAO_SOLVER tao,TaoVec **xxll,TaoVec **xxuu)
    1268: {
    1269:   TaoFunctionBegin;
    1270:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    1271:   if (xxll){
    1272:     *xxll=tao->XL;
    1273:   }
    1274:   if (xxuu){
    1275:     *xxuu=tao->XU;
    1276:   }
    1277:   TaoFunctionReturn(0);
    1278: }

    1281: /* ---------------------------------------------------------- */
    1284: /*@
    1285:    TaoLMVMSetSize - Sets the number of previous points and gradients to
    1286:    be used in calculating the step direction for the limited memory
    1287:    variable metric methods.

    1289:    Collective on TAO_SOLVER

    1291:    Input Parameters:
    1292: +  tao - the TAO_SOLVER context
    1293: -  lm - the number of previous points and gradients to be used.

    1295:    Output Parameter:

    1297:    Options Database Keys:
    1298: .  -tao_lmvm_lm <lm>

    1300:    Level: intermediate

    1302: .keywords: method

    1304: @*/
    1305: int TaoLMVMSetSize(TAO_SOLVER tao,int lm)
    1306: {
    1307:   TaoFunctionBegin;
    1308:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    1309:   if (lm < 1) SETERRQ(1,"Gradient History must be positive");
    1310:   tao->lm=lm;

    1312:   TaoFunctionReturn(0);
    1313: }

    1317: /*@C
    1318:    TaoLMVMGetSize - Gets the number of previous points and gradients to
    1319:    be used in calculating the step direction for the limited memory
    1320:    variable metric methods.

    1322:    Collective on TAO_SOLVER

    1324:    Input Parameters:
    1325: .  tao - the TAO_SOLVER context

    1327:    Output Parameter:
    1328: .  lm - the number of previous points and gradients to be used.

    1330:    Level: intermediate

    1332: @*/
    1333: int TaoLMVMGetSize(TAO_SOLVER tao,int *lm)
    1334: {
    1335:   TaoFunctionBegin;
    1336:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);
    1337:   if (lm){
    1338:     *lm=tao->lm;
    1339:   }
    1340:   TaoFunctionReturn(0);
    1341: }

    1344: /* ---------------------------------------------------------- */
    1347: /*@C
    1348:    TaoSetTerminationReason - Sets the termination reason

    1350:    Collective on TAO_SOLVER

    1352:    Input Parameters:
    1353: +  tao - the TAO_SOLVER context
    1354: -  reason - one of

    1356: $    TAO_CONVERGED_ATOL (2),        (res <= atol)
    1357: $    TAO_CONVERGED_RTOL (3),        (res/res0 <= rtol)
    1358: $    TAO_CONVERGED_TRTOL (4),       (xdiff <= trtol)
    1359: $    TAO_CONVERGED_MINF (5),        (f <= fmin)
    1360: $    TAO_CONVERGED_USER (6),        (user defined)

    1362: $    TAO_DIVERGED_MAXITS (-2),      (its>maxits)
    1363: $    TAO_DIVERGED_NAN (-4),         (Numerical problems)
    1364: $    TAO_DIVERGED_MAXFCN (-5),      (nfunc > maxnfuncts)
    1365: $    TAO_DIVERGED_LS_FAILURE (-6),  (line search failure)
    1366: $    TAO_DIVERGED_TR_REDUCTION (-7),
    1367: $    TAO_DIVERGED_USER (-8),        (user defined)

    1369: $    TAO_CONTINUE_ITERATING  (0)

    1371:    where
    1372: +  res - residual of optimality conditions
    1373: .  res0 - initial residual of optimality conditions
    1374: .  xdiff - current trust region size
    1375: .  f - function value
    1376: .  atol - absolute tolerance
    1377: .  rtol - relative tolerance
    1378: .  its - current iterate number
    1379: .  maxits - maximum number of iterates
    1380: .  nfunc - number of function evaluations
    1381: -  maxnfuncts - maximum number of function evaluations

    1384:    Output Parameter:

    1386:    Level: intermediate

    1388: .seealso TaoGetTerminationReason(), TaoAppSetMonitor(), TaoSetMonitor()

    1390: .keywords: convergence

    1392: @*/
    1393: int TaoSetTerminationReason(TAO_SOLVER tao,TaoTerminateReason reason)
    1394: {
    1395:   TaoFunctionBegin;
    1396:   TaoValidHeaderSpecific(tao,TAO_COOKIE,1);

    1398:   tao->reason=reason;

    1400:   TaoFunctionReturn(0);
    1401: }

    1404: /* ------------ Routines to called when destroying this application ----------- */
    1407: /*@C
    1408:    TaoSetDestroyRoutine - Sets an ADDITIONAL function that will be called when
    1409:    this object is destroyed.

    1411:    Collective on TAO_SOLVER

    1413:    Input Parameters:
    1414: +  taoapp - the TAO_SOLVER solver context
    1415: .  destroy - function pointer
    1416: -  mctx - [optional] user-defined context for private data for the
    1417:           destroy routine (may be TAO_NULL)

    1419:    Calling sequence of destroy:
    1420: $     int mydestroy(void *mctx)

    1422: .    mctx - [optional] destroy context

    1425:    Level: intermediate

    1427: .keywords: destroy

    1429: .seealso: TaoSetMonitor(), TaoDestroy()
    1430: @*/
    1431: int TaoSetDestroyRoutine(TAO_SOLVER tao,int (*destroy)(void*),void *mctx)
    1432: {
    1433:   TaoFunctionBegin;
    1434:   if (destroy){
    1435:     if (tao->numberdestroyers >= MAX_TAO_DESTROY) {
    1436:       SETERRQ(1,"TAO ERRROR: Too many TAO destroy routines set");
    1437:     }
    1438:
    1439:     tao->userdestroy[tao->numberdestroyers]           = destroy;
    1440:     tao->userctxdestroy[tao->numberdestroyers++]      = mctx;
    1441:   }
    1442:   TaoFunctionReturn(0);
    1443: }