1 #include <petsc/private/taolinesearchimpl.h> 2 #include <../src/tao/linesearch/impls/morethuente/morethuente.h> 3 4 /* 5 This algorithm is taken from More' and Thuente, "Line search algorithms 6 with guaranteed sufficient decrease", Argonne National Laboratory, 7 Technical Report MCS-P330-1092. 8 */ 9 10 static PetscErrorCode Tao_mcstep(TaoLineSearch ls,PetscReal *stx,PetscReal *fx,PetscReal *dx,PetscReal *sty,PetscReal *fy,PetscReal *dy,PetscReal *stp,PetscReal *fp,PetscReal *dp); 11 12 #undef __FUNCT__ 13 #define __FUNCT__ "TaoLineSearchDestroy_MT" 14 static PetscErrorCode TaoLineSearchDestroy_MT(TaoLineSearch ls) 15 { 16 PetscErrorCode ierr; 17 TaoLineSearch_MT *mt; 18 19 PetscFunctionBegin; 20 PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1); 21 mt = (TaoLineSearch_MT*)(ls->data); 22 if (mt->x) { 23 ierr = PetscObjectDereference((PetscObject)mt->x);CHKERRQ(ierr); 24 } 25 ierr = VecDestroy(&mt->work);CHKERRQ(ierr); 26 ierr = PetscFree(ls->data);CHKERRQ(ierr); 27 PetscFunctionReturn(0); 28 } 29 30 #undef __FUNCT__ 31 #define __FUNCT__ "TaoLineSearchSetFromOptions_MT" 32 static PetscErrorCode TaoLineSearchSetFromOptions_MT(PetscOptionItems *PetscOptionsObject,TaoLineSearch ls) 33 { 34 PetscFunctionBegin; 35 PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1); 36 PetscFunctionReturn(0); 37 } 38 39 40 #undef __FUNCT__ 41 #define __FUNCT__ "TaoLineSearchApply_MT" 42 /* @ TaoApply_LineSearch - This routine takes step length of 1.0. 43 44 Input Parameters: 45 + tao - Tao context 46 . X - current iterate (on output X contains new iterate, X + step*S) 47 . f - objective function evaluated at X 48 . G - gradient evaluated at X 49 - D - search direction 50 51 52 Info is set to 0. 53 54 @ */ 55 56 static PetscErrorCode TaoLineSearchApply_MT(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s) 57 { 58 PetscErrorCode ierr; 59 TaoLineSearch_MT *mt; 60 61 PetscReal xtrapf = 4.0; 62 PetscReal finit, width, width1, dginit, fm, fxm, fym, dgm, dgxm, dgym; 63 PetscReal dgx, dgy, dg, dg2, fx, fy, stx, sty, dgtest; 64 PetscReal ftest1=0.0, ftest2=0.0; 65 PetscInt i, stage1,n1,n2,nn1,nn2; 66 PetscReal bstepmin1, bstepmin2, bstepmax; 67 PetscBool g_computed=PETSC_FALSE; /* to prevent extra gradient computation */ 68 69 PetscFunctionBegin; 70 PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1); 71 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 72 PetscValidScalarPointer(f,3); 73 PetscValidHeaderSpecific(g,VEC_CLASSID,4); 74 PetscValidHeaderSpecific(s,VEC_CLASSID,5); 75 76 /* comm,type,size checks are done in interface TaoLineSearchApply */ 77 mt = (TaoLineSearch_MT*)(ls->data); 78 ls->reason = TAOLINESEARCH_CONTINUE_ITERATING; 79 80 /* Check work vector */ 81 if (!mt->work) { 82 ierr = VecDuplicate(x,&mt->work);CHKERRQ(ierr); 83 mt->x = x; 84 ierr = PetscObjectReference((PetscObject)mt->x);CHKERRQ(ierr); 85 } else if (x != mt->x) { 86 ierr = VecDestroy(&mt->work);CHKERRQ(ierr); 87 ierr = VecDuplicate(x,&mt->work);CHKERRQ(ierr); 88 ierr = PetscObjectDereference((PetscObject)mt->x);CHKERRQ(ierr); 89 mt->x = x; 90 ierr = PetscObjectReference((PetscObject)mt->x);CHKERRQ(ierr); 91 } 92 93 if (ls->bounded) { 94 /* Compute step length needed to make all variables equal a bound */ 95 /* Compute the smallest steplength that will make one nonbinding variable 96 equal the bound */ 97 ierr = VecGetLocalSize(ls->upper,&n1);CHKERRQ(ierr); 98 ierr = VecGetLocalSize(mt->x, &n2);CHKERRQ(ierr); 99 ierr = VecGetSize(ls->upper,&nn1);CHKERRQ(ierr); 100 ierr = VecGetSize(mt->x,&nn2);CHKERRQ(ierr); 101 if (n1 != n2 || nn1 != nn2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Variable vector not compatible with bounds vector"); 102 ierr = VecScale(s,-1.0);CHKERRQ(ierr); 103 ierr = VecBoundGradientProjection(s,x,ls->lower,ls->upper,s);CHKERRQ(ierr); 104 ierr = VecScale(s,-1.0);CHKERRQ(ierr); 105 ierr = VecStepBoundInfo(x,s,ls->lower,ls->upper,&bstepmin1,&bstepmin2,&bstepmax);CHKERRQ(ierr); 106 ls->stepmax = PetscMin(bstepmax,1.0e15); 107 } 108 109 ierr = VecDot(g,s,&dginit);CHKERRQ(ierr); 110 if (PetscIsInfOrNanReal(dginit)) { 111 ierr = PetscInfo1(ls,"Initial Line Search step * g is Inf or Nan (%g)\n",(double)dginit);CHKERRQ(ierr); 112 ls->reason=TAOLINESEARCH_FAILED_INFORNAN; 113 PetscFunctionReturn(0); 114 } 115 if (dginit >= 0.0) { 116 ierr = PetscInfo1(ls,"Initial Line Search step * g is not descent direction (%g)\n",(double)dginit);CHKERRQ(ierr); 117 ls->reason = TAOLINESEARCH_FAILED_ASCENT; 118 PetscFunctionReturn(0); 119 } 120 121 122 /* Initialization */ 123 mt->bracket = 0; 124 stage1 = 1; 125 finit = *f; 126 dgtest = ls->ftol * dginit; 127 width = ls->stepmax - ls->stepmin; 128 width1 = width * 2.0; 129 ierr = VecCopy(x,mt->work);CHKERRQ(ierr); 130 /* Variable dictionary: 131 stx, fx, dgx - the step, function, and derivative at the best step 132 sty, fy, dgy - the step, function, and derivative at the other endpoint 133 of the interval of uncertainty 134 step, f, dg - the step, function, and derivative at the current step */ 135 136 stx = 0.0; 137 fx = finit; 138 dgx = dginit; 139 sty = 0.0; 140 fy = finit; 141 dgy = dginit; 142 143 ls->step=ls->initstep; 144 for (i=0; i< ls->max_funcs; i++) { 145 /* Set min and max steps to correspond to the interval of uncertainty */ 146 if (mt->bracket) { 147 ls->stepmin = PetscMin(stx,sty); 148 ls->stepmax = PetscMax(stx,sty); 149 } else { 150 ls->stepmin = stx; 151 ls->stepmax = ls->step + xtrapf * (ls->step - stx); 152 } 153 154 /* Force the step to be within the bounds */ 155 ls->step = PetscMax(ls->step,ls->stepmin); 156 ls->step = PetscMin(ls->step,ls->stepmax); 157 158 /* If an unusual termination is to occur, then let step be the lowest 159 point obtained thus far */ 160 if ((stx!=0) && (((mt->bracket) && (ls->step <= ls->stepmin || ls->step >= ls->stepmax)) || ((mt->bracket) && (ls->stepmax - ls->stepmin <= ls->rtol * ls->stepmax)) || 161 ((ls->nfeval+ls->nfgeval) >= ls->max_funcs - 1) || (mt->infoc == 0))) { 162 ls->step = stx; 163 } 164 165 ierr = VecCopy(x,mt->work);CHKERRQ(ierr); 166 ierr = VecAXPY(mt->work,ls->step,s);CHKERRQ(ierr); /* W = X + step*S */ 167 168 if (ls->bounded) { 169 ierr = VecMedian(ls->lower, mt->work, ls->upper, mt->work);CHKERRQ(ierr); 170 } 171 if (ls->usegts) { 172 ierr = TaoLineSearchComputeObjectiveAndGTS(ls,mt->work,f,&dg);CHKERRQ(ierr); 173 g_computed=PETSC_FALSE; 174 } else { 175 ierr = TaoLineSearchComputeObjectiveAndGradient(ls,mt->work,f,g);CHKERRQ(ierr); 176 g_computed=PETSC_TRUE; 177 if (ls->bounded) { 178 ierr = VecDot(g,x,&dg);CHKERRQ(ierr); 179 ierr = VecDot(g,mt->work,&dg2);CHKERRQ(ierr); 180 dg = (dg2 - dg)/ls->step; 181 } else { 182 ierr = VecDot(g,s,&dg);CHKERRQ(ierr); 183 } 184 } 185 186 if (0 == i) { 187 ls->f_fullstep=*f; 188 } 189 190 if (PetscIsInfOrNanReal(*f) || PetscIsInfOrNanReal(dg)) { 191 /* User provided compute function generated Not-a-Number, assume 192 domain violation and set function value and directional 193 derivative to infinity. */ 194 *f = PETSC_INFINITY; 195 dg = PETSC_INFINITY; 196 } 197 198 ftest1 = finit + ls->step * dgtest; 199 if (ls->bounded) { 200 ftest2 = finit + ls->step * dgtest * ls->ftol; 201 } 202 /* Convergence testing */ 203 if (((*f - ftest1 <= 1.0e-10 * PetscAbsReal(finit)) && (PetscAbsReal(dg) + ls->gtol*dginit <= 0.0))) { 204 ierr = PetscInfo(ls, "Line search success: Sufficient decrease and directional deriv conditions hold\n");CHKERRQ(ierr); 205 ls->reason = TAOLINESEARCH_SUCCESS; 206 break; 207 } 208 209 /* Check Armijo if beyond the first breakpoint */ 210 if (ls->bounded && (*f <= ftest2) && (ls->step >= bstepmin2)) { 211 ierr = PetscInfo(ls,"Line search success: Sufficient decrease.\n");CHKERRQ(ierr); 212 ls->reason = TAOLINESEARCH_SUCCESS; 213 break; 214 } 215 216 /* Checks for bad cases */ 217 if (((mt->bracket) && (ls->step <= ls->stepmin||ls->step >= ls->stepmax)) || (!mt->infoc)) { 218 ierr = PetscInfo(ls,"Rounding errors may prevent further progress. May not be a step satisfying\n");CHKERRQ(ierr); 219 ierr = PetscInfo(ls,"sufficient decrease and curvature conditions. Tolerances may be too small.\n");CHKERRQ(ierr); 220 ls->reason = TAOLINESEARCH_HALTED_OTHER; 221 break; 222 } 223 if ((ls->step == ls->stepmax) && (*f <= ftest1) && (dg <= dgtest)) { 224 ierr = PetscInfo1(ls,"Step is at the upper bound, stepmax (%g)\n",(double)ls->stepmax);CHKERRQ(ierr); 225 ls->reason = TAOLINESEARCH_HALTED_UPPERBOUND; 226 break; 227 } 228 if ((ls->step == ls->stepmin) && (*f >= ftest1) && (dg >= dgtest)) { 229 ierr = PetscInfo1(ls,"Step is at the lower bound, stepmin (%g)\n",(double)ls->stepmin);CHKERRQ(ierr); 230 ls->reason = TAOLINESEARCH_HALTED_LOWERBOUND; 231 break; 232 } 233 if ((mt->bracket) && (ls->stepmax - ls->stepmin <= ls->rtol*ls->stepmax)){ 234 ierr = PetscInfo1(ls,"Relative width of interval of uncertainty is at most rtol (%g)\n",(double)ls->rtol);CHKERRQ(ierr); 235 ls->reason = TAOLINESEARCH_HALTED_RTOL; 236 break; 237 } 238 239 /* In the first stage, we seek a step for which the modified function 240 has a nonpositive value and nonnegative derivative */ 241 if ((stage1) && (*f <= ftest1) && (dg >= dginit * PetscMin(ls->ftol, ls->gtol))) { 242 stage1 = 0; 243 } 244 245 /* A modified function is used to predict the step only if we 246 have not obtained a step for which the modified function has a 247 nonpositive function value and nonnegative derivative, and if a 248 lower function value has been obtained but the decrease is not 249 sufficient */ 250 251 if ((stage1) && (*f <= fx) && (*f > ftest1)) { 252 fm = *f - ls->step * dgtest; /* Define modified function */ 253 fxm = fx - stx * dgtest; /* and derivatives */ 254 fym = fy - sty * dgtest; 255 dgm = dg - dgtest; 256 dgxm = dgx - dgtest; 257 dgym = dgy - dgtest; 258 259 /* if (dgxm * (ls->step - stx) >= 0.0) */ 260 /* Update the interval of uncertainty and compute the new step */ 261 ierr = Tao_mcstep(ls,&stx,&fxm,&dgxm,&sty,&fym,&dgym,&ls->step,&fm,&dgm);CHKERRQ(ierr); 262 263 fx = fxm + stx * dgtest; /* Reset the function and */ 264 fy = fym + sty * dgtest; /* gradient values */ 265 dgx = dgxm + dgtest; 266 dgy = dgym + dgtest; 267 } else { 268 /* Update the interval of uncertainty and compute the new step */ 269 ierr = Tao_mcstep(ls,&stx,&fx,&dgx,&sty,&fy,&dgy,&ls->step,f,&dg);CHKERRQ(ierr); 270 } 271 272 /* Force a sufficient decrease in the interval of uncertainty */ 273 if (mt->bracket) { 274 if (PetscAbsReal(sty - stx) >= 0.66 * width1) ls->step = stx + 0.5*(sty - stx); 275 width1 = width; 276 width = PetscAbsReal(sty - stx); 277 } 278 } 279 if ((ls->nfeval+ls->nfgeval) > ls->max_funcs) { 280 ierr = PetscInfo2(ls,"Number of line search function evals (%D) > maximum (%D)\n",(ls->nfeval+ls->nfgeval),ls->max_funcs);CHKERRQ(ierr); 281 ls->reason = TAOLINESEARCH_HALTED_MAXFCN; 282 } 283 284 /* Finish computations */ 285 ierr = PetscInfo2(ls,"%D function evals in line search, step = %g\n",(ls->nfeval+ls->nfgeval),(double)ls->step);CHKERRQ(ierr); 286 287 /* Set new solution vector and compute gradient if needed */ 288 ierr = VecCopy(mt->work,x);CHKERRQ(ierr); 289 if (!g_computed) { 290 ierr = TaoLineSearchComputeGradient(ls,mt->work,g);CHKERRQ(ierr); 291 } 292 PetscFunctionReturn(0); 293 } 294 295 #undef __FUNCT__ 296 #define __FUNCT__ "TaoLineSearchCreate_MT" 297 PETSC_EXTERN PetscErrorCode TaoLineSearchCreate_MT(TaoLineSearch ls) 298 { 299 PetscErrorCode ierr; 300 TaoLineSearch_MT *ctx; 301 302 PetscFunctionBegin; 303 PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1); 304 ierr = PetscNewLog(ls,&ctx);CHKERRQ(ierr); 305 ctx->bracket=0; 306 ctx->infoc=1; 307 ls->data = (void*)ctx; 308 ls->initstep = 1.0; 309 ls->ops->setup=0; 310 ls->ops->reset=0; 311 ls->ops->apply=TaoLineSearchApply_MT; 312 ls->ops->destroy=TaoLineSearchDestroy_MT; 313 ls->ops->setfromoptions=TaoLineSearchSetFromOptions_MT; 314 PetscFunctionReturn(0); 315 } 316 317 /* 318 The subroutine mcstep is taken from the work of Jorge Nocedal. 319 this is a variant of More' and Thuente's routine. 320 321 subroutine mcstep 322 323 the purpose of mcstep is to compute a safeguarded step for 324 a linesearch and to update an interval of uncertainty for 325 a minimizer of the function. 326 327 the parameter stx contains the step with the least function 328 value. the parameter stp contains the current step. it is 329 assumed that the derivative at stx is negative in the 330 direction of the step. if bracket is set true then a 331 minimizer has been bracketed in an interval of uncertainty 332 with endpoints stx and sty. 333 334 the subroutine statement is 335 336 subroutine mcstep(stx,fx,dx,sty,fy,dy,stp,fp,dp,bracket, 337 stpmin,stpmax,info) 338 339 where 340 341 stx, fx, and dx are variables which specify the step, 342 the function, and the derivative at the best step obtained 343 so far. The derivative must be negative in the direction 344 of the step, that is, dx and stp-stx must have opposite 345 signs. On output these parameters are updated appropriately. 346 347 sty, fy, and dy are variables which specify the step, 348 the function, and the derivative at the other endpoint of 349 the interval of uncertainty. On output these parameters are 350 updated appropriately. 351 352 stp, fp, and dp are variables which specify the step, 353 the function, and the derivative at the current step. 354 If bracket is set true then on input stp must be 355 between stx and sty. On output stp is set to the new step. 356 357 bracket is a logical variable which specifies if a minimizer 358 has been bracketed. If the minimizer has not been bracketed 359 then on input bracket must be set false. If the minimizer 360 is bracketed then on output bracket is set true. 361 362 stpmin and stpmax are input variables which specify lower 363 and upper bounds for the step. 364 365 info is an integer output variable set as follows: 366 if info = 1,2,3,4,5, then the step has been computed 367 according to one of the five cases below. otherwise 368 info = 0, and this indicates improper input parameters. 369 370 subprograms called 371 372 fortran-supplied ... abs,max,min,sqrt 373 374 argonne national laboratory. minpack project. june 1983 375 jorge j. more', david j. thuente 376 377 */ 378 379 #undef __FUNCT__ 380 #define __FUNCT__ "Tao_mcstep" 381 static PetscErrorCode Tao_mcstep(TaoLineSearch ls,PetscReal *stx,PetscReal *fx,PetscReal *dx,PetscReal *sty,PetscReal *fy,PetscReal *dy,PetscReal *stp,PetscReal *fp,PetscReal *dp) 382 { 383 TaoLineSearch_MT *mtP = (TaoLineSearch_MT *) ls->data; 384 PetscReal gamma1, p, q, r, s, sgnd, stpc, stpf, stpq, theta; 385 PetscInt bound; 386 387 PetscFunctionBegin; 388 /* Check the input parameters for errors */ 389 mtP->infoc = 0; 390 if (mtP->bracket && (*stp <= PetscMin(*stx,*sty) || (*stp >= PetscMax(*stx,*sty)))) SETERRQ(PETSC_COMM_SELF,1,"bad stp in bracket"); 391 if (*dx * (*stp-*stx) >= 0.0) SETERRQ(PETSC_COMM_SELF,1,"dx * (stp-stx) >= 0.0"); 392 if (ls->stepmax < ls->stepmin) SETERRQ(PETSC_COMM_SELF,1,"stepmax > stepmin"); 393 394 /* Determine if the derivatives have opposite sign */ 395 sgnd = *dp * (*dx / PetscAbsReal(*dx)); 396 397 if (*fp > *fx) { 398 /* Case 1: a higher function value. 399 The minimum is bracketed. If the cubic step is closer 400 to stx than the quadratic step, the cubic step is taken, 401 else the average of the cubic and quadratic steps is taken. */ 402 403 mtP->infoc = 1; 404 bound = 1; 405 theta = 3 * (*fx - *fp) / (*stp - *stx) + *dx + *dp; 406 s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dx)); 407 s = PetscMax(s,PetscAbsReal(*dp)); 408 gamma1 = s*PetscSqrtScalar(PetscPowScalar(theta/s,2.0) - (*dx/s)*(*dp/s)); 409 if (*stp < *stx) gamma1 = -gamma1; 410 /* Can p be 0? Check */ 411 p = (gamma1 - *dx) + theta; 412 q = ((gamma1 - *dx) + gamma1) + *dp; 413 r = p/q; 414 stpc = *stx + r*(*stp - *stx); 415 stpq = *stx + ((*dx/((*fx-*fp)/(*stp-*stx)+*dx))*0.5) * (*stp - *stx); 416 417 if (PetscAbsReal(stpc-*stx) < PetscAbsReal(stpq-*stx)) { 418 stpf = stpc; 419 } else { 420 stpf = stpc + 0.5*(stpq - stpc); 421 } 422 mtP->bracket = 1; 423 } else if (sgnd < 0.0) { 424 /* Case 2: A lower function value and derivatives of 425 opposite sign. The minimum is bracketed. If the cubic 426 step is closer to stx than the quadratic (secant) step, 427 the cubic step is taken, else the quadratic step is taken. */ 428 429 mtP->infoc = 2; 430 bound = 0; 431 theta = 3*(*fx - *fp)/(*stp - *stx) + *dx + *dp; 432 s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dx)); 433 s = PetscMax(s,PetscAbsReal(*dp)); 434 gamma1 = s*PetscSqrtScalar(PetscPowScalar(theta/s,2.0) - (*dx/s)*(*dp/s)); 435 if (*stp > *stx) gamma1 = -gamma1; 436 p = (gamma1 - *dp) + theta; 437 q = ((gamma1 - *dp) + gamma1) + *dx; 438 r = p/q; 439 stpc = *stp + r*(*stx - *stp); 440 stpq = *stp + (*dp/(*dp-*dx))*(*stx - *stp); 441 442 if (PetscAbsReal(stpc-*stp) > PetscAbsReal(stpq-*stp)) { 443 stpf = stpc; 444 } else { 445 stpf = stpq; 446 } 447 mtP->bracket = 1; 448 } else if (PetscAbsReal(*dp) < PetscAbsReal(*dx)) { 449 /* Case 3: A lower function value, derivatives of the 450 same sign, and the magnitude of the derivative decreases. 451 The cubic step is only used if the cubic tends to infinity 452 in the direction of the step or if the minimum of the cubic 453 is beyond stp. Otherwise the cubic step is defined to be 454 either stepmin or stepmax. The quadratic (secant) step is also 455 computed and if the minimum is bracketed then the step 456 closest to stx is taken, else the step farthest away is taken. */ 457 458 mtP->infoc = 3; 459 bound = 1; 460 theta = 3*(*fx - *fp)/(*stp - *stx) + *dx + *dp; 461 s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dx)); 462 s = PetscMax(s,PetscAbsReal(*dp)); 463 464 /* The case gamma1 = 0 only arises if the cubic does not tend 465 to infinity in the direction of the step. */ 466 gamma1 = s*PetscSqrtScalar(PetscMax(0.0,PetscPowScalar(theta/s,2.0) - (*dx/s)*(*dp/s))); 467 if (*stp > *stx) gamma1 = -gamma1; 468 p = (gamma1 - *dp) + theta; 469 q = (gamma1 + (*dx - *dp)) + gamma1; 470 r = p/q; 471 if (r < 0.0 && gamma1 != 0.0) stpc = *stp + r*(*stx - *stp); 472 else if (*stp > *stx) stpc = ls->stepmax; 473 else stpc = ls->stepmin; 474 stpq = *stp + (*dp/(*dp-*dx)) * (*stx - *stp); 475 476 if (mtP->bracket) { 477 if (PetscAbsReal(*stp-stpc) < PetscAbsReal(*stp-stpq)) { 478 stpf = stpc; 479 } else { 480 stpf = stpq; 481 } 482 } else { 483 if (PetscAbsReal(*stp-stpc) > PetscAbsReal(*stp-stpq)) { 484 stpf = stpc; 485 } else { 486 stpf = stpq; 487 } 488 } 489 } else { 490 /* Case 4: A lower function value, derivatives of the 491 same sign, and the magnitude of the derivative does 492 not decrease. If the minimum is not bracketed, the step 493 is either stpmin or stpmax, else the cubic step is taken. */ 494 495 mtP->infoc = 4; 496 bound = 0; 497 if (mtP->bracket) { 498 theta = 3*(*fp - *fy)/(*sty - *stp) + *dy + *dp; 499 s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dy)); 500 s = PetscMax(s,PetscAbsReal(*dp)); 501 gamma1 = s*PetscSqrtScalar(PetscPowScalar(theta/s,2.0) - (*dy/s)*(*dp/s)); 502 if (*stp > *sty) gamma1 = -gamma1; 503 p = (gamma1 - *dp) + theta; 504 q = ((gamma1 - *dp) + gamma1) + *dy; 505 r = p/q; 506 stpc = *stp + r*(*sty - *stp); 507 stpf = stpc; 508 } else if (*stp > *stx) { 509 stpf = ls->stepmax; 510 } else { 511 stpf = ls->stepmin; 512 } 513 } 514 515 /* Update the interval of uncertainty. This update does not 516 depend on the new step or the case analysis above. */ 517 518 if (*fp > *fx) { 519 *sty = *stp; 520 *fy = *fp; 521 *dy = *dp; 522 } else { 523 if (sgnd < 0.0) { 524 *sty = *stx; 525 *fy = *fx; 526 *dy = *dx; 527 } 528 *stx = *stp; 529 *fx = *fp; 530 *dx = *dp; 531 } 532 533 /* Compute the new step and safeguard it. */ 534 stpf = PetscMin(ls->stepmax,stpf); 535 stpf = PetscMax(ls->stepmin,stpf); 536 *stp = stpf; 537 if (mtP->bracket && bound) { 538 if (*sty > *stx) { 539 *stp = PetscMin(*stx+0.66*(*sty-*stx),*stp); 540 } else { 541 *stp = PetscMax(*stx+0.66*(*sty-*stx),*stp); 542 } 543 } 544 PetscFunctionReturn(0); 545 } 546