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