static PetscErrorCode TaoSolve_SSILS(Tao tao) { TAO_SSLS *ssls = (TAO_SSLS *)tao->data; PetscReal psi, ndpsi, normd, innerd, t=0; PetscReal delta, rho; PetscInt iter=0,kspits; TaoConvergedReason reason; TaoLineSearchConvergedReason ls_reason; PetscErrorCode ierr; PetscFunctionBegin; /* Assume that Setup has been called! Set the structure for the Jacobian and create a linear solver. */ delta = ssls->delta; rho = ssls->rho; ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); ierr = VecMedian(tao->XL,tao->solution,tao->XU,tao->solution);CHKERRQ(ierr); ierr = TaoLineSearchSetObjectiveAndGradientRoutine(tao->linesearch,Tao_SSLS_FunctionGradient,tao);CHKERRQ(ierr); ierr = TaoLineSearchSetObjectiveRoutine(tao->linesearch,Tao_SSLS_Function,tao);CHKERRQ(ierr); /* Calculate the function value and fischer function value at the current iterate */ ierr = TaoLineSearchComputeObjectiveAndGradient(tao->linesearch,tao->solution,&psi,ssls->dpsi);CHKERRQ(ierr); ierr = VecNorm(ssls->dpsi,NORM_2,&ndpsi);CHKERRQ(ierr); while (1) { ierr=PetscInfo3(tao, "iter: %D, merit: %g, ndpsi: %g\n",iter, (double)ssls->merit, (double)ndpsi);CHKERRQ(ierr); /* Check the termination criteria */ ierr = TaoMonitor(tao,iter++,ssls->merit,ndpsi,0.0,t,&reason);CHKERRQ(ierr); if (reason!=TAO_CONTINUE_ITERATING) break; /* Calculate direction. (Really negative of newton direction. Therefore, rest of the code uses -d.) */ ierr = KSPSetOperators(tao->ksp,tao->jacobian,tao->jacobian_pre);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp,ssls->ff,tao->stepdirection);CHKERRQ(ierr); ierr = KSPGetIterationNumber(tao->ksp,&kspits);CHKERRQ(ierr); tao->ksp_its+=kspits; ierr = VecNorm(tao->stepdirection,NORM_2,&normd);CHKERRQ(ierr); ierr = VecDot(tao->stepdirection,ssls->dpsi,&innerd);CHKERRQ(ierr); /* Make sure that we have a descent direction */ if (innerd <= delta*pow(normd, rho)) { ierr = PetscInfo(tao, "newton direction not descent\n");CHKERRQ(ierr); ierr = VecCopy(ssls->dpsi,tao->stepdirection);CHKERRQ(ierr); ierr = VecDot(tao->stepdirection,ssls->dpsi,&innerd);CHKERRQ(ierr); } ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); innerd = -innerd; ierr = TaoLineSearchSetInitialStepLength(tao->linesearch,1.0); ierr = TaoLineSearchApply(tao->linesearch,tao->solution,&psi,ssls->dpsi,tao->stepdirection,&t,&ls_reason);CHKERRQ(ierr); ierr = VecNorm(ssls->dpsi,NORM_2,&ndpsi);CHKERRQ(ierr); } PetscFunctionReturn(0); }
static PetscErrorCode TaoLineSearchApply_Unit(TaoLineSearch ls,Vec x,PetscReal *f,Vec g,Vec step_direction) { PetscErrorCode ierr; PetscReal ftry; PetscReal startf = *f; PetscFunctionBegin; /* Take unit step (newx = startx + 1.0*step_direction) */ ierr = VecAXPY(x,1.0,step_direction);CHKERRQ(ierr); ierr = TaoLineSearchComputeObjectiveAndGradient(ls,x,&ftry,g);CHKERRQ(ierr); ierr = PetscInfo1(ls,"Tao Apply Unit Step: %4.4e\n",1.0);CHKERRQ(ierr); if (startf < ftry){ ierr = PetscInfo2(ls,"Tao Apply Unit Step, FINCREASE: F old:= %12.10e, F new: %12.10e\n",(double)startf,(double)ftry);CHKERRQ(ierr); } *f = ftry; ls->step = 1.0; ls->reason=TAOLINESEARCH_SUCCESS; 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); }
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 TaoSolve_SQPCON(Tao tao) { TAO_SQPCON *sqpconP = (TAO_SQPCON*)tao->data; PetscInt iter=0; TaoConvergedReason reason = TAO_CONTINUE_ITERATING; TaoLineSearchConvergedReason ls_reason = TAOLINESEARCH_CONTINUE_ITERATING; PetscReal step=1.0,f,fm, fold; PetscReal cnorm, mnorm; PetscBool use_update=PETSC_TRUE; /* don't update Q if line search failed */ PetscErrorCode ierr; PetscFunctionBegin; /* Scatter to U,V */ ierr = VecScatterBegin(sqpconP->state_scatter, tao->solution, sqpconP->U, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(sqpconP->state_scatter, tao->solution, sqpconP->U, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterBegin(sqpconP->design_scatter, tao->solution, sqpconP->V, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(sqpconP->design_scatter, tao->solution, sqpconP->V, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); /* Evaluate Function, Gradient, Constraints, and Jacobian */ ierr = TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient);CHKERRQ(ierr); ierr = TaoComputeConstraints(tao,tao->solution, tao->constraints);CHKERRQ(ierr); ierr = TaoComputeJacobianState(tao,tao->solution, &tao->jacobian_state, &tao->jacobian_state_pre, &tao->jacobian_state_inv, &sqpconP->statematflag);CHKERRQ(ierr); ierr = TaoComputeJacobianDesign(tao,tao->solution, &tao->jacobian_design, &tao->jacobian_design_pre, &sqpconP->statematflag);CHKERRQ(ierr); /* Scatter gradient to GU,GV */ ierr = VecScatterBegin(sqpconP->state_scatter, tao->gradient, sqpconP->GU, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(sqpconP->state_scatter, tao->gradient, sqpconP->GU, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterBegin(sqpconP->design_scatter, tao->gradient, sqpconP->GV, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(sqpconP->design_scatter, tao->gradient, sqpconP->GV, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecNorm(tao->gradient, NORM_2, &mnorm);CHKERRQ(ierr); /* Evaluate constraint norm */ ierr = VecNorm(tao->constraints, NORM_2, &cnorm);CHKERRQ(ierr); /* Monitor convergence */ ierr = TaoMonitor(tao, iter,f,mnorm,cnorm,step,&reason);CHKERRQ(ierr); while (reason == TAO_CONTINUE_ITERATING) { /* Solve tbar = -A\t (t is constraints vector) */ ierr = MatMult(tao->jacobian_state_inv, tao->constraints, sqpconP->Tbar);CHKERRQ(ierr); ierr = VecScale(sqpconP->Tbar, -1.0);CHKERRQ(ierr); /* aqwac = A'\(Q*Tbar + c) */ if (iter > 0) { ierr = MatMult(sqpconP->Q,sqpconP->Tbar,sqpconP->WV);CHKERRQ(ierr); } else { ierr = VecCopy(sqpconP->Tbar, sqpconP->WV);CHKERRQ(ierr); } ierr = VecAXPY(sqpconP->WV,1.0,sqpconP->GU);CHKERRQ(ierr); ierr = MatMultTranspose(tao->jacobian_state_inv, sqpconP->WV, sqpconP->aqwac);CHKERRQ(ierr); /* Reduced Gradient dbar = d - B^t * aqwac */ ierr = MatMultTranspose(tao->jacobian_design,sqpconP->aqwac, sqpconP->dbar);CHKERRQ(ierr); ierr = VecScale(sqpconP->dbar, -1.0);CHKERRQ(ierr); ierr = VecAXPY(sqpconP->dbar,1.0,sqpconP->GV);CHKERRQ(ierr); /* update reduced hessian */ ierr = MatLMVMUpdate(sqpconP->R, sqpconP->V, sqpconP->dbar);CHKERRQ(ierr); /* Solve R*dv = -dbar using approx. hessian */ ierr = MatLMVMSolve(sqpconP->R, sqpconP->dbar, sqpconP->DV);CHKERRQ(ierr); ierr = VecScale(sqpconP->DV, -1.0);CHKERRQ(ierr); /* Backsolve for u = A\(g - B*dv) = tbar - A\(B*dv)*/ ierr = MatMult(tao->jacobian_design, sqpconP->DV, sqpconP->WL);CHKERRQ(ierr); ierr = MatMult(tao->jacobian_state_inv, sqpconP->WL, sqpconP->DU);CHKERRQ(ierr); ierr = VecScale(sqpconP->DU, -1.0);CHKERRQ(ierr); ierr = VecAXPY(sqpconP->DU, 1.0, sqpconP->Tbar);CHKERRQ(ierr); /* Assemble Big D */ ierr = VecScatterBegin(sqpconP->state_scatter, sqpconP->DU, tao->stepdirection, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterEnd(sqpconP->state_scatter, sqpconP->DU, tao->stepdirection, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterBegin(sqpconP->design_scatter, sqpconP->DV, tao->stepdirection, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterEnd(sqpconP->design_scatter, sqpconP->DV, tao->stepdirection, INSERT_VALUES, SCATTER_REVERSE);CHKERRQ(ierr); /* Perform Line Search */ ierr = VecCopy(tao->solution, sqpconP->Xold);CHKERRQ(ierr); ierr = VecCopy(tao->gradient, sqpconP->Gold);CHKERRQ(ierr); fold = f; ierr = TaoLineSearchComputeObjectiveAndGradient(tao->linesearch,tao->solution,&fm,sqpconP->GL);CHKERRQ(ierr); ierr = TaoLineSearchSetInitialStepLength(tao->linesearch,1.0); ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &fm, sqpconP->GL, tao->stepdirection,&step, &ls_reason);CHKERRQ(ierr); ierr = TaoAddLineSearchCounts(tao);CHKERRQ(ierr); if (ls_reason < 0) { ierr = VecCopy(sqpconP->Xold, tao->solution); ierr = VecCopy(sqpconP->Gold, tao->gradient); f = fold; ierr = VecAXPY(tao->solution, 1.0, tao->stepdirection);CHKERRQ(ierr); ierr = PetscInfo(tao,"Line Search Failed, using full step.");CHKERRQ(ierr); use_update=PETSC_FALSE; } else { use_update = PETSC_TRUE; } /* Scatter X to U,V */ ierr = VecScatterBegin(sqpconP->state_scatter, tao->solution, sqpconP->U, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(sqpconP->state_scatter, tao->solution, sqpconP->U, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterBegin(sqpconP->design_scatter, tao->solution, sqpconP->V, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(sqpconP->design_scatter, tao->solution, sqpconP->V, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); /* Evaluate Function, Gradient, Constraints, and Jacobian */ ierr = TaoComputeObjectiveAndGradient(tao,tao->solution,&f,tao->gradient);CHKERRQ(ierr); ierr = TaoComputeConstraints(tao,tao->solution, tao->constraints);CHKERRQ(ierr); ierr = TaoComputeJacobianState(tao,tao->solution, &tao->jacobian_state, &tao->jacobian_state_pre, &tao->jacobian_state_inv, &sqpconP->statematflag);CHKERRQ(ierr); ierr = TaoComputeJacobianDesign(tao,tao->solution, &tao->jacobian_design, &tao->jacobian_design_pre, &sqpconP->designmatflag);CHKERRQ(ierr); /* Scatter gradient to GU,GV */ ierr = VecScatterBegin(sqpconP->state_scatter, tao->gradient, sqpconP->GU, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(sqpconP->state_scatter, tao->gradient, sqpconP->GU, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterBegin(sqpconP->design_scatter, tao->gradient, sqpconP->GV, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(sqpconP->design_scatter, tao->gradient, sqpconP->GV, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); /* Update approx to hessian of the Lagrangian wrt state (Q) with u_k+1, gu_k+1 */ if (use_update) { ierr = MatApproxUpdate(sqpconP->Q,sqpconP->U,sqpconP->GU);CHKERRQ(ierr); } ierr = VecNorm(sqpconP->GL, NORM_2, &mnorm);CHKERRQ(ierr); /* Evaluate constraint norm */ ierr = VecNorm(tao->constraints, NORM_2, &cnorm);CHKERRQ(ierr); /* Monitor convergence */ iter++; ierr = TaoMonitor(tao, iter,f,mnorm,cnorm,step,&reason);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); }
static PetscErrorCode TaoSolve_ASILS(Tao tao) { TAO_SSLS *asls = (TAO_SSLS *)tao->data; PetscReal psi,ndpsi, normd, innerd, t=0; PetscInt iter=0, nf; PetscErrorCode ierr; TaoConvergedReason reason; TaoLineSearchConvergedReason ls_reason; PetscFunctionBegin; /* Assume that Setup has been called! Set the structure for the Jacobian and create a linear solver. */ ierr = TaoComputeVariableBounds(tao);CHKERRQ(ierr); ierr = TaoLineSearchSetObjectiveAndGradientRoutine(tao->linesearch,Tao_ASLS_FunctionGradient,tao);CHKERRQ(ierr); ierr = TaoLineSearchSetObjectiveRoutine(tao->linesearch,Tao_SSLS_Function,tao);CHKERRQ(ierr); /* Calculate the function value and fischer function value at the current iterate */ ierr = TaoLineSearchComputeObjectiveAndGradient(tao->linesearch,tao->solution,&psi,asls->dpsi);CHKERRQ(ierr); ierr = VecNorm(asls->dpsi,NORM_2,&ndpsi);CHKERRQ(ierr); while (1) { /* Check the termination criteria */ ierr = PetscInfo3(tao,"iter %D, merit: %g, ||dpsi||: %g\n",iter, (double)asls->merit, (double)ndpsi);CHKERRQ(ierr); ierr = TaoMonitor(tao, iter++, asls->merit, ndpsi, 0.0, t, &reason);CHKERRQ(ierr); if (TAO_CONTINUE_ITERATING != reason) break; /* We are going to solve a linear system of equations. We need to set the tolerances for the solve so that we maintain an asymptotic rate of convergence that is superlinear. Note: these tolerances are for the reduced system. We really need to make sure that the full system satisfies the full-space conditions. This rule gives superlinear asymptotic convergence asls->atol = min(0.5, asls->merit*sqrt(asls->merit)); asls->rtol = 0.0; This rule gives quadratic asymptotic convergence asls->atol = min(0.5, asls->merit*asls->merit); asls->rtol = 0.0; Calculate a free and fixed set of variables. The fixed set of variables are those for the d_b is approximately equal to zero. The definition of approximately changes as we approach the solution to the problem. No one rule is guaranteed to work in all cases. The following definition is based on the norm of the Jacobian matrix. If the norm is large, the tolerance becomes smaller. */ ierr = MatNorm(tao->jacobian,NORM_1,&asls->identifier);CHKERRQ(ierr); asls->identifier = PetscMin(asls->merit, 1e-2) / (1 + asls->identifier); ierr = VecSet(asls->t1,-asls->identifier);CHKERRQ(ierr); ierr = VecSet(asls->t2, asls->identifier);CHKERRQ(ierr); ierr = ISDestroy(&asls->fixed);CHKERRQ(ierr); ierr = ISDestroy(&asls->free);CHKERRQ(ierr); ierr = VecWhichBetweenOrEqual(asls->t1, asls->db, asls->t2, &asls->fixed);CHKERRQ(ierr); ierr = ISComplementVec(asls->fixed,asls->t1, &asls->free);CHKERRQ(ierr); ierr = ISGetSize(asls->fixed,&nf);CHKERRQ(ierr); ierr = PetscInfo1(tao,"Number of fixed variables: %D\n", nf);CHKERRQ(ierr); /* We now have our partition. Now calculate the direction in the fixed variable space. */ ierr = TaoVecGetSubVec(asls->ff, asls->fixed, tao->subset_type, 0.0, &asls->r1); ierr = TaoVecGetSubVec(asls->da, asls->fixed, tao->subset_type, 1.0, &asls->r2); ierr = VecPointwiseDivide(asls->r1,asls->r1,asls->r2);CHKERRQ(ierr); ierr = VecSet(tao->stepdirection,0.0);CHKERRQ(ierr); ierr = VecISAXPY(tao->stepdirection, asls->fixed,1.0,asls->r1);CHKERRQ(ierr); /* Our direction in the Fixed Variable Set is fixed. Calculate the information needed for the step in the Free Variable Set. To do this, we need to know the diagonal perturbation and the right hand side. */ ierr = TaoVecGetSubVec(asls->da, asls->free, tao->subset_type, 0.0, &asls->r1);CHKERRQ(ierr); ierr = TaoVecGetSubVec(asls->ff, asls->free, tao->subset_type, 0.0, &asls->r2);CHKERRQ(ierr); ierr = TaoVecGetSubVec(asls->db, asls->free, tao->subset_type, 1.0, &asls->r3);CHKERRQ(ierr); ierr = VecPointwiseDivide(asls->r1,asls->r1, asls->r3);CHKERRQ(ierr); ierr = VecPointwiseDivide(asls->r2,asls->r2, asls->r3);CHKERRQ(ierr); /* r1 is the diagonal perturbation r2 is the right hand side r3 is no longer needed Now need to modify r2 for our direction choice in the fixed variable set: calculate t1 = J*d, take the reduced vector of t1 and modify r2. */ ierr = MatMult(tao->jacobian, tao->stepdirection, asls->t1);CHKERRQ(ierr); ierr = TaoVecGetSubVec(asls->t1,asls->free,tao->subset_type,0.0,&asls->r3);CHKERRQ(ierr); ierr = VecAXPY(asls->r2, -1.0, asls->r3);CHKERRQ(ierr); /* Calculate the reduced problem matrix and the direction */ if (!asls->w && (tao->subset_type == TAO_SUBSET_MASK || tao->subset_type == TAO_SUBSET_MATRIXFREE)) { ierr = VecDuplicate(tao->solution, &asls->w);CHKERRQ(ierr); } ierr = TaoMatGetSubMat(tao->jacobian, asls->free, asls->w, tao->subset_type,&asls->J_sub);CHKERRQ(ierr); if (tao->jacobian != tao->jacobian_pre) { ierr = TaoMatGetSubMat(tao->jacobian_pre, asls->free, asls->w, tao->subset_type, &asls->Jpre_sub);CHKERRQ(ierr); } else { ierr = MatDestroy(&asls->Jpre_sub);CHKERRQ(ierr); asls->Jpre_sub = asls->J_sub; ierr = PetscObjectReference((PetscObject)(asls->Jpre_sub));CHKERRQ(ierr); } ierr = MatDiagonalSet(asls->J_sub, asls->r1,ADD_VALUES);CHKERRQ(ierr); ierr = TaoVecGetSubVec(tao->stepdirection, asls->free, tao->subset_type, 0.0, &asls->dxfree);CHKERRQ(ierr); ierr = VecSet(asls->dxfree, 0.0);CHKERRQ(ierr); /* Calculate the reduced direction. (Really negative of Newton direction. Therefore, rest of the code uses -d.) */ ierr = KSPReset(tao->ksp); ierr = KSPSetOperators(tao->ksp, asls->J_sub, asls->Jpre_sub);CHKERRQ(ierr); ierr = KSPSolve(tao->ksp, asls->r2, asls->dxfree);CHKERRQ(ierr); /* Add the direction in the free variables back into the real direction. */ ierr = VecISAXPY(tao->stepdirection, asls->free, 1.0,asls->dxfree);CHKERRQ(ierr); /* Check the real direction for descent and if not, use the negative gradient direction. */ ierr = VecNorm(tao->stepdirection, NORM_2, &normd);CHKERRQ(ierr); ierr = VecDot(tao->stepdirection, asls->dpsi, &innerd);CHKERRQ(ierr); if (innerd <= asls->delta*pow(normd, asls->rho)) { ierr = PetscInfo1(tao,"Gradient direction: %5.4e.\n", (double)innerd);CHKERRQ(ierr); ierr = PetscInfo1(tao, "Iteration %D: newton direction not descent\n", iter);CHKERRQ(ierr); ierr = VecCopy(asls->dpsi, tao->stepdirection);CHKERRQ(ierr); ierr = VecDot(asls->dpsi, tao->stepdirection, &innerd);CHKERRQ(ierr); } ierr = VecScale(tao->stepdirection, -1.0);CHKERRQ(ierr); innerd = -innerd; /* We now have a correct descent direction. Apply a linesearch to find the new iterate. */ ierr = TaoLineSearchSetInitialStepLength(tao->linesearch, 1.0);CHKERRQ(ierr); ierr = TaoLineSearchApply(tao->linesearch, tao->solution, &psi,asls->dpsi, tao->stepdirection, &t, &ls_reason);CHKERRQ(ierr); ierr = VecNorm(asls->dpsi, NORM_2, &ndpsi);CHKERRQ(ierr); } PetscFunctionReturn(0); }