static PetscErrorCode TaoLineSearchApply_GPCG(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s) { TaoLineSearch_GPCG *neP = (TaoLineSearch_GPCG *)ls->data; PetscErrorCode ierr; PetscInt i; PetscBool g_computed=PETSC_FALSE; /* to prevent extra gradient computation */ PetscReal d1,finit,actred,prered,rho, gdx; PetscFunctionBegin; /* ls->stepmin - lower bound for step */ /* ls->stepmax - upper bound for step */ /* ls->rtol - relative tolerance for an acceptable step */ /* ls->ftol - tolerance for sufficient decrease condition */ /* ls->gtol - tolerance for curvature condition */ /* ls->nfeval - number of function evaluations */ /* ls->nfeval - number of function/gradient evaluations */ /* ls->max_funcs - maximum number of function evaluations */ ls->reason = TAOLINESEARCH_CONTINUE_ITERATING; ls->step = ls->initstep; if (!neP->W2) { ierr = VecDuplicate(x,&neP->W2);CHKERRQ(ierr); ierr = VecDuplicate(x,&neP->W1);CHKERRQ(ierr); ierr = VecDuplicate(x,&neP->Gold);CHKERRQ(ierr); neP->x = x; ierr = PetscObjectReference((PetscObject)neP->x);CHKERRQ(ierr); } else if (x != neP->x) { ierr = VecDestroy(&neP->x);CHKERRQ(ierr); ierr = VecDestroy(&neP->W1);CHKERRQ(ierr); ierr = VecDestroy(&neP->W2);CHKERRQ(ierr); ierr = VecDestroy(&neP->Gold);CHKERRQ(ierr); ierr = VecDuplicate(x,&neP->W1);CHKERRQ(ierr); ierr = VecDuplicate(x,&neP->W2);CHKERRQ(ierr); ierr = VecDuplicate(x,&neP->Gold);CHKERRQ(ierr); ierr = PetscObjectDereference((PetscObject)neP->x);CHKERRQ(ierr); neP->x = x; ierr = PetscObjectReference((PetscObject)neP->x);CHKERRQ(ierr); } ierr = VecDot(g,s,&gdx);CHKERRQ(ierr); if (gdx > 0) { ierr = PetscInfo1(ls,"Line search error: search direction is not descent direction. dot(g,s) = %g\n",(double)gdx);CHKERRQ(ierr); ls->reason = TAOLINESEARCH_FAILED_ASCENT; PetscFunctionReturn(0); } ierr = VecCopy(x,neP->W2);CHKERRQ(ierr); ierr = VecCopy(g,neP->Gold);CHKERRQ(ierr); if (ls->bounded) { /* Compute the smallest steplength that will make one nonbinding variable equal the bound */ ierr = VecStepBoundInfo(x,s,ls->lower,ls->upper,&rho,&actred,&d1);CHKERRQ(ierr); ls->step = PetscMin(ls->step,d1); } rho=0; actred=0; if (ls->step < 0) { ierr = PetscInfo1(ls,"Line search error: initial step parameter %g< 0\n",(double)ls->step);CHKERRQ(ierr); ls->reason = TAOLINESEARCH_HALTED_OTHER; PetscFunctionReturn(0); } /* Initialization */ finit = *f; for (i=0; i< ls->max_funcs; i++) { /* Force the step to be within the bounds */ ls->step = PetscMax(ls->step,ls->stepmin); ls->step = PetscMin(ls->step,ls->stepmax); ierr = VecCopy(x,neP->W2);CHKERRQ(ierr); ierr = VecAXPY(neP->W2,ls->step,s);CHKERRQ(ierr); if (ls->bounded) { /* Make sure new vector is numerically within bounds */ ierr = VecMedian(neP->W2,ls->lower,ls->upper,neP->W2);CHKERRQ(ierr); } /* Gradient is not needed here. Unless there is a separate gradient routine, compute it here anyway to prevent recomputing at the end of the line search */ if (ls->hasobjective) { ierr = TaoLineSearchComputeObjective(ls,neP->W2,f);CHKERRQ(ierr); g_computed=PETSC_FALSE; } else if (ls->usegts){ ierr = TaoLineSearchComputeObjectiveAndGTS(ls,neP->W2,f,&gdx);CHKERRQ(ierr); g_computed=PETSC_FALSE; } else { ierr = TaoLineSearchComputeObjectiveAndGradient(ls,neP->W2,f,g);CHKERRQ(ierr); g_computed=PETSC_TRUE; } if (0 == i) { ls->f_fullstep = *f; } actred = *f - finit; ierr = VecCopy(neP->W2,neP->W1);CHKERRQ(ierr); ierr = VecAXPY(neP->W1,-1.0,x);CHKERRQ(ierr); /* W1 = W2 - X */ ierr = VecDot(neP->W1,neP->Gold,&prered);CHKERRQ(ierr); if (fabs(prered)<1.0e-100) prered=1.0e-12; rho = actred/prered; /* If sufficient progress has been obtained, accept the point. Otherwise, backtrack. */ if (actred > 0) { ierr = PetscInfo(ls,"Step resulted in ascent, rejecting.\n");CHKERRQ(ierr); ls->step = (ls->step)/2; } else if (rho > ls->ftol){ break; } else{ ls->step = (ls->step)/2; } /* Convergence testing */ if (ls->step <= ls->stepmin || ls->step >= ls->stepmax) { ls->reason = TAOLINESEARCH_HALTED_OTHER; ierr = PetscInfo(ls,"Rounding errors may prevent further progress. May not be a step satisfying\n");CHKERRQ(ierr); ierr = PetscInfo(ls,"sufficient decrease and curvature conditions. Tolerances may be too small.\n");CHKERRQ(ierr); break; } if (ls->step == ls->stepmax) { ierr = PetscInfo1(ls,"Step is at the upper bound, stepmax (%g)\n",(double)ls->stepmax);CHKERRQ(ierr); ls->reason = TAOLINESEARCH_HALTED_UPPERBOUND; break; } if (ls->step == ls->stepmin) { ierr = PetscInfo1(ls,"Step is at the lower bound, stepmin (%g)\n",(double)ls->stepmin);CHKERRQ(ierr); ls->reason = TAOLINESEARCH_HALTED_LOWERBOUND; break; } if ((ls->nfeval+ls->nfgeval) >= ls->max_funcs) { ierr = PetscInfo2(ls,"Number of line search function evals (%D) > maximum (%D)\n",ls->nfeval+ls->nfgeval,ls->max_funcs);CHKERRQ(ierr); ls->reason = TAOLINESEARCH_HALTED_MAXFCN; break; } if ((neP->bracket) && (ls->stepmax - ls->stepmin <= ls->rtol*ls->stepmax)){ ierr = PetscInfo1(ls,"Relative width of interval of uncertainty is at most rtol (%g)\n",(double)ls->rtol);CHKERRQ(ierr); ls->reason = TAOLINESEARCH_HALTED_RTOL; break; } } ierr = PetscInfo2(ls,"%D function evals in line search, step = %g\n",ls->nfeval+ls->nfgeval,(double)ls->step);CHKERRQ(ierr); /* set new solution vector and compute gradient if necessary */ ierr = VecCopy(neP->W2, x);CHKERRQ(ierr); if (ls->reason == TAOLINESEARCH_CONTINUE_ITERATING) { ls->reason = TAOLINESEARCH_SUCCESS; } if (!g_computed) { ierr = TaoLineSearchComputeGradient(ls,x,g);CHKERRQ(ierr); } PetscFunctionReturn(0); }
static PetscErrorCode TaoLineSearchApply_MT(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s) { PetscErrorCode ierr; TaoLineSearch_MT *mt; PetscReal xtrapf = 4.0; PetscReal finit, width, width1, dginit, fm, fxm, fym, dgm, dgxm, dgym; PetscReal dgx, dgy, dg, dg2, fx, fy, stx, sty, dgtest; PetscReal ftest1=0.0, ftest2=0.0; PetscInt i, stage1,n1,n2,nn1,nn2; PetscReal bstepmin1, bstepmin2, bstepmax; PetscBool g_computed=PETSC_FALSE; /* to prevent extra gradient computation */ PetscFunctionBegin; PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1); PetscValidHeaderSpecific(x,VEC_CLASSID,2); PetscValidScalarPointer(f,3); PetscValidHeaderSpecific(g,VEC_CLASSID,4); PetscValidHeaderSpecific(s,VEC_CLASSID,5); /* comm,type,size checks are done in interface TaoLineSearchApply */ mt = (TaoLineSearch_MT*)(ls->data); ls->reason = TAOLINESEARCH_CONTINUE_ITERATING; /* Check work vector */ if (!mt->work) { ierr = VecDuplicate(x,&mt->work);CHKERRQ(ierr); mt->x = x; ierr = PetscObjectReference((PetscObject)mt->x);CHKERRQ(ierr); } else if (x != mt->x) { ierr = VecDestroy(&mt->work);CHKERRQ(ierr); ierr = VecDuplicate(x,&mt->work);CHKERRQ(ierr); ierr = PetscObjectDereference((PetscObject)mt->x);CHKERRQ(ierr); mt->x = x; ierr = PetscObjectReference((PetscObject)mt->x);CHKERRQ(ierr); } if (ls->bounded) { /* Compute step length needed to make all variables equal a bound */ /* Compute the smallest steplength that will make one nonbinding variable equal the bound */ ierr = VecGetLocalSize(ls->upper,&n1);CHKERRQ(ierr); ierr = VecGetLocalSize(mt->x, &n2);CHKERRQ(ierr); ierr = VecGetSize(ls->upper,&nn1);CHKERRQ(ierr); ierr = VecGetSize(mt->x,&nn2);CHKERRQ(ierr); if (n1 != n2 || nn1 != nn2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Variable vector not compatible with bounds vector"); ierr = VecScale(s,-1.0);CHKERRQ(ierr); ierr = VecBoundGradientProjection(s,x,ls->lower,ls->upper,s);CHKERRQ(ierr); ierr = VecScale(s,-1.0);CHKERRQ(ierr); ierr = VecStepBoundInfo(x,s,ls->lower,ls->upper,&bstepmin1,&bstepmin2,&bstepmax);CHKERRQ(ierr); ls->stepmax = PetscMin(bstepmax,1.0e15); } ierr = VecDot(g,s,&dginit);CHKERRQ(ierr); if (PetscIsInfOrNanReal(dginit)) { ierr = PetscInfo1(ls,"Initial Line Search step * g is Inf or Nan (%g)\n",(double)dginit);CHKERRQ(ierr); ls->reason=TAOLINESEARCH_FAILED_INFORNAN; PetscFunctionReturn(0); } if (dginit >= 0.0) { ierr = PetscInfo1(ls,"Initial Line Search step * g is not descent direction (%g)\n",(double)dginit);CHKERRQ(ierr); ls->reason = TAOLINESEARCH_FAILED_ASCENT; PetscFunctionReturn(0); } /* Initialization */ mt->bracket = 0; stage1 = 1; finit = *f; dgtest = ls->ftol * dginit; width = ls->stepmax - ls->stepmin; width1 = width * 2.0; ierr = VecCopy(x,mt->work);CHKERRQ(ierr); /* Variable dictionary: stx, fx, dgx - the step, function, and derivative at the best step sty, fy, dgy - the step, function, and derivative at the other endpoint of the interval of uncertainty step, f, dg - the step, function, and derivative at the current step */ stx = 0.0; fx = finit; dgx = dginit; sty = 0.0; fy = finit; dgy = dginit; ls->step=ls->initstep; for (i=0; i< ls->max_funcs; i++) { /* Set min and max steps to correspond to the interval of uncertainty */ if (mt->bracket) { ls->stepmin = PetscMin(stx,sty); ls->stepmax = PetscMax(stx,sty); } else { ls->stepmin = stx; ls->stepmax = ls->step + xtrapf * (ls->step - stx); } /* Force the step to be within the bounds */ ls->step = PetscMax(ls->step,ls->stepmin); ls->step = PetscMin(ls->step,ls->stepmax); /* If an unusual termination is to occur, then let step be the lowest point obtained thus far */ if ((stx!=0) && (((mt->bracket) && (ls->step <= ls->stepmin || ls->step >= ls->stepmax)) || ((mt->bracket) && (ls->stepmax - ls->stepmin <= ls->rtol * ls->stepmax)) || ((ls->nfeval+ls->nfgeval) >= ls->max_funcs - 1) || (mt->infoc == 0))) { ls->step = stx; } ierr = VecCopy(x,mt->work);CHKERRQ(ierr); ierr = VecAXPY(mt->work,ls->step,s);CHKERRQ(ierr); /* W = X + step*S */ if (ls->bounded) { ierr = VecMedian(ls->lower, mt->work, ls->upper, mt->work);CHKERRQ(ierr); } if (ls->usegts) { ierr = TaoLineSearchComputeObjectiveAndGTS(ls,mt->work,f,&dg);CHKERRQ(ierr); g_computed=PETSC_FALSE; } else { ierr = TaoLineSearchComputeObjectiveAndGradient(ls,mt->work,f,g);CHKERRQ(ierr); g_computed=PETSC_TRUE; if (ls->bounded) { ierr = VecDot(g,x,&dg);CHKERRQ(ierr); ierr = VecDot(g,mt->work,&dg2);CHKERRQ(ierr); dg = (dg2 - dg)/ls->step; } else { ierr = VecDot(g,s,&dg);CHKERRQ(ierr); } } if (0 == i) { ls->f_fullstep=*f; } if (PetscIsInfOrNanReal(*f) || PetscIsInfOrNanReal(dg)) { /* User provided compute function generated Not-a-Number, assume domain violation and set function value and directional derivative to infinity. */ *f = PETSC_INFINITY; dg = PETSC_INFINITY; } ftest1 = finit + ls->step * dgtest; if (ls->bounded) { ftest2 = finit + ls->step * dgtest * ls->ftol; } /* Convergence testing */ if (((*f - ftest1 <= 1.0e-10 * PetscAbsReal(finit)) && (PetscAbsReal(dg) + ls->gtol*dginit <= 0.0))) { ierr = PetscInfo(ls, "Line search success: Sufficient decrease and directional deriv conditions hold\n");CHKERRQ(ierr); ls->reason = TAOLINESEARCH_SUCCESS; break; } /* Check Armijo if beyond the first breakpoint */ if (ls->bounded && (*f <= ftest2) && (ls->step >= bstepmin2)) { ierr = PetscInfo(ls,"Line search success: Sufficient decrease.\n");CHKERRQ(ierr); ls->reason = TAOLINESEARCH_SUCCESS; break; } /* Checks for bad cases */ if (((mt->bracket) && (ls->step <= ls->stepmin||ls->step >= ls->stepmax)) || (!mt->infoc)) { ierr = PetscInfo(ls,"Rounding errors may prevent further progress. May not be a step satisfying\n");CHKERRQ(ierr); ierr = PetscInfo(ls,"sufficient decrease and curvature conditions. Tolerances may be too small.\n");CHKERRQ(ierr); ls->reason = TAOLINESEARCH_HALTED_OTHER; break; } if ((ls->step == ls->stepmax) && (*f <= ftest1) && (dg <= dgtest)) { ierr = PetscInfo1(ls,"Step is at the upper bound, stepmax (%g)\n",(double)ls->stepmax);CHKERRQ(ierr); ls->reason = TAOLINESEARCH_HALTED_UPPERBOUND; break; } if ((ls->step == ls->stepmin) && (*f >= ftest1) && (dg >= dgtest)) { ierr = PetscInfo1(ls,"Step is at the lower bound, stepmin (%g)\n",(double)ls->stepmin);CHKERRQ(ierr); ls->reason = TAOLINESEARCH_HALTED_LOWERBOUND; break; } if ((mt->bracket) && (ls->stepmax - ls->stepmin <= ls->rtol*ls->stepmax)){ ierr = PetscInfo1(ls,"Relative width of interval of uncertainty is at most rtol (%g)\n",(double)ls->rtol);CHKERRQ(ierr); ls->reason = TAOLINESEARCH_HALTED_RTOL; break; } /* In the first stage, we seek a step for which the modified function has a nonpositive value and nonnegative derivative */ if ((stage1) && (*f <= ftest1) && (dg >= dginit * PetscMin(ls->ftol, ls->gtol))) { stage1 = 0; } /* A modified function is used to predict the step only if we have not obtained a step for which the modified function has a nonpositive function value and nonnegative derivative, and if a lower function value has been obtained but the decrease is not sufficient */ if ((stage1) && (*f <= fx) && (*f > ftest1)) { fm = *f - ls->step * dgtest; /* Define modified function */ fxm = fx - stx * dgtest; /* and derivatives */ fym = fy - sty * dgtest; dgm = dg - dgtest; dgxm = dgx - dgtest; dgym = dgy - dgtest; /* if (dgxm * (ls->step - stx) >= 0.0) */ /* Update the interval of uncertainty and compute the new step */ ierr = Tao_mcstep(ls,&stx,&fxm,&dgxm,&sty,&fym,&dgym,&ls->step,&fm,&dgm);CHKERRQ(ierr); fx = fxm + stx * dgtest; /* Reset the function and */ fy = fym + sty * dgtest; /* gradient values */ dgx = dgxm + dgtest; dgy = dgym + dgtest; } else { /* Update the interval of uncertainty and compute the new step */ ierr = Tao_mcstep(ls,&stx,&fx,&dgx,&sty,&fy,&dgy,&ls->step,f,&dg);CHKERRQ(ierr); } /* Force a sufficient decrease in the interval of uncertainty */ if (mt->bracket) { if (PetscAbsReal(sty - stx) >= 0.66 * width1) ls->step = stx + 0.5*(sty - stx); width1 = width; width = PetscAbsReal(sty - stx); } } if ((ls->nfeval+ls->nfgeval) > ls->max_funcs) { ierr = PetscInfo2(ls,"Number of line search function evals (%D) > maximum (%D)\n",(ls->nfeval+ls->nfgeval),ls->max_funcs);CHKERRQ(ierr); ls->reason = TAOLINESEARCH_HALTED_MAXFCN; } /* Finish computations */ ierr = PetscInfo2(ls,"%D function evals in line search, step = %g\n",(ls->nfeval+ls->nfgeval),(double)ls->step);CHKERRQ(ierr); /* Set new solution vector and compute gradient if needed */ ierr = VecCopy(mt->work,x);CHKERRQ(ierr); if (!g_computed) { ierr = TaoLineSearchComputeGradient(ls,mt->work,g);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* @ TaoApply_OWArmijo - This routine performs a linesearch. It backtracks until the (nonmonotone) OWArmijo conditions are satisfied. Input Parameters: + tao - TAO_SOLVER context . X - current iterate (on output X contains new iterate, X + step*S) . S - search direction . f - merit function evaluated at X . G - gradient of merit function evaluated at X . W - work vector - step - initial estimate of step length Output parameters: + f - merit function evaluated at new iterate, X + step*S . G - gradient of merit function evaluated at new iterate, X + step*S . X - new iterate - step - final step length Info is set to one of: . 0 - the line search succeeds; the sufficient decrease condition and the directional derivative condition hold negative number if an input parameter is invalid - -1 - step < 0 positive number > 1 if the line search otherwise terminates + 1 - Step is at the lower bound, stepmin. @ */ static PetscErrorCode TaoLineSearchApply_OWArmijo(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s) { TaoLineSearch_OWARMIJO *armP = (TaoLineSearch_OWARMIJO *)ls->data; PetscErrorCode ierr; PetscInt i; PetscReal fact, ref, gdx; PetscInt idx; PetscBool g_computed=PETSC_FALSE; /* to prevent extra gradient computation */ Vec g_old; PetscReal owlqn_minstep=0.005; PetscReal partgdx; MPI_Comm comm; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)ls,&comm);CHKERRQ(ierr); fact = 0.0; ls->nfeval=0; ls->reason = TAOLINESEARCH_CONTINUE_ITERATING; if (!armP->work) { ierr = VecDuplicate(x,&armP->work);CHKERRQ(ierr); armP->x = x; ierr = PetscObjectReference((PetscObject)armP->x);CHKERRQ(ierr); } else if (x != armP->x) { ierr = VecDestroy(&armP->work);CHKERRQ(ierr); ierr = VecDuplicate(x,&armP->work);CHKERRQ(ierr); ierr = PetscObjectDereference((PetscObject)armP->x);CHKERRQ(ierr); armP->x = x; ierr = PetscObjectReference((PetscObject)armP->x);CHKERRQ(ierr); } /* Check linesearch parameters */ if (armP->alpha < 1) { ierr = PetscInfo1(ls,"OWArmijo line search error: alpha (%g) < 1\n", (double)armP->alpha);CHKERRQ(ierr); ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER; } else if ((armP->beta <= 0) || (armP->beta >= 1)) { ierr = PetscInfo1(ls,"OWArmijo line search error: beta (%g) invalid\n", (double)armP->beta);CHKERRQ(ierr); ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER; } else if ((armP->beta_inf <= 0) || (armP->beta_inf >= 1)) { ierr = PetscInfo1(ls,"OWArmijo line search error: beta_inf (%g) invalid\n", (double)armP->beta_inf);CHKERRQ(ierr); ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER; } else if ((armP->sigma <= 0) || (armP->sigma >= 0.5)) { ierr = PetscInfo1(ls,"OWArmijo line search error: sigma (%g) invalid\n", (double)armP->sigma);CHKERRQ(ierr); ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER; } else if (armP->memorySize < 1) { ierr = PetscInfo1(ls,"OWArmijo line search error: memory_size (%D) < 1\n", armP->memorySize);CHKERRQ(ierr); ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER; } else if ((armP->referencePolicy != REFERENCE_MAX) && (armP->referencePolicy != REFERENCE_AVE) && (armP->referencePolicy != REFERENCE_MEAN)) { ierr = PetscInfo(ls,"OWArmijo line search error: reference_policy invalid\n");CHKERRQ(ierr); ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER; } else if ((armP->replacementPolicy != REPLACE_FIFO) && (armP->replacementPolicy != REPLACE_MRU)) { ierr = PetscInfo(ls,"OWArmijo line search error: replacement_policy invalid\n");CHKERRQ(ierr); ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER; } else if (PetscIsInfOrNanReal(*f)) { ierr = PetscInfo(ls,"OWArmijo line search error: initial function inf or nan\n");CHKERRQ(ierr); ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER; } if (ls->reason != TAOLINESEARCH_CONTINUE_ITERATING) PetscFunctionReturn(0); /* Check to see of the memory has been allocated. If not, allocate the historical array and populate it with the initial function values. */ if (!armP->memory) { ierr = PetscMalloc1(armP->memorySize, &armP->memory );CHKERRQ(ierr); } if (!armP->memorySetup) { for (i = 0; i < armP->memorySize; i++) { armP->memory[i] = armP->alpha*(*f); } armP->current = 0; armP->lastReference = armP->memory[0]; armP->memorySetup=PETSC_TRUE; } /* Calculate reference value (MAX) */ ref = armP->memory[0]; idx = 0; for (i = 1; i < armP->memorySize; i++) { if (armP->memory[i] > ref) { ref = armP->memory[i]; idx = i; } } if (armP->referencePolicy == REFERENCE_AVE) { ref = 0; for (i = 0; i < armP->memorySize; i++) { ref += armP->memory[i]; } ref = ref / armP->memorySize; ref = PetscMax(ref, armP->memory[armP->current]); } else if (armP->referencePolicy == REFERENCE_MEAN) { ref = PetscMin(ref, 0.5*(armP->lastReference + armP->memory[armP->current])); } if (armP->nondescending) { fact = armP->sigma; } ierr = VecDuplicate(g,&g_old);CHKERRQ(ierr); ierr = VecCopy(g,g_old);CHKERRQ(ierr); ls->step = ls->initstep; while (ls->step >= owlqn_minstep && ls->nfeval < ls->max_funcs) { /* Calculate iterate */ ierr = VecCopy(x,armP->work);CHKERRQ(ierr); ierr = VecAXPY(armP->work,ls->step,s);CHKERRQ(ierr); partgdx=0.0; ierr = ProjWork_OWLQN(armP->work,x,g_old,&partgdx); ierr = MPI_Allreduce(&partgdx,&gdx,1,MPIU_REAL,MPIU_SUM,comm);CHKERRQ(ierr); /* Check the condition of gdx */ if (PetscIsInfOrNanReal(gdx)) { ierr = PetscInfo1(ls,"Initial Line Search step * g is Inf or Nan (%g)\n",(double)gdx);CHKERRQ(ierr); ls->reason=TAOLINESEARCH_FAILED_INFORNAN; PetscFunctionReturn(0); } if (gdx >= 0.0) { ierr = PetscInfo1(ls,"Initial Line Search step is not descent direction (g's=%g)\n",(double)gdx);CHKERRQ(ierr); ls->reason = TAOLINESEARCH_FAILED_ASCENT; PetscFunctionReturn(0); } /* Calculate function at new iterate */ ierr = TaoLineSearchComputeObjectiveAndGradient(ls,armP->work,f,g);CHKERRQ(ierr); g_computed=PETSC_TRUE; if (ls->step == ls->initstep) { ls->f_fullstep = *f; } if (PetscIsInfOrNanReal(*f)) { ls->step *= armP->beta_inf; } else { /* Check descent condition */ if (armP->nondescending && *f <= ref - ls->step*fact*ref) break; if (!armP->nondescending && *f <= ref + armP->sigma * gdx) break; ls->step *= armP->beta; } } ierr = VecDestroy(&g_old);CHKERRQ(ierr); /* Check termination */ if (PetscIsInfOrNanReal(*f)) { ierr = PetscInfo(ls, "Function is inf or nan.\n");CHKERRQ(ierr); ls->reason = TAOLINESEARCH_FAILED_BADPARAMETER; } else if (ls->step < owlqn_minstep) { ierr = PetscInfo(ls, "Step length is below tolerance.\n");CHKERRQ(ierr); ls->reason = TAOLINESEARCH_HALTED_RTOL; } else if (ls->nfeval >= ls->max_funcs) { ierr = PetscInfo2(ls, "Number of line search function evals (%D) > maximum allowed (%D)\n",ls->nfeval, ls->max_funcs);CHKERRQ(ierr); ls->reason = TAOLINESEARCH_HALTED_MAXFCN; } if (ls->reason) PetscFunctionReturn(0); /* Successful termination, update memory */ armP->lastReference = ref; if (armP->replacementPolicy == REPLACE_FIFO) { armP->memory[armP->current++] = *f; if (armP->current >= armP->memorySize) { armP->current = 0; } } else { armP->current = idx; armP->memory[idx] = *f; } /* Update iterate and compute gradient */ ierr = VecCopy(armP->work,x);CHKERRQ(ierr); if (!g_computed) { ierr = TaoLineSearchComputeGradient(ls, x, g);CHKERRQ(ierr); } ierr = PetscInfo2(ls, "%D function evals in line search, step = %10.4f\n",ls->nfeval, (double)ls->step);CHKERRQ(ierr); PetscFunctionReturn(0); }