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); 27 PetscFunctionReturn(0); 28 } 29 30 #undef __FUNCT__ 31 #define __FUNCT__ "TaoLineSearchSetFromOptions_MT" 32 static PetscErrorCode TaoLineSearchSetFromOptions_MT(TaoLineSearch ls) 33 { 34 PetscFunctionBegin; 35 PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1); 36 PetscFunctionReturn(0); 37 } 38 39 #undef __FUNCT__ 40 #define __FUNCT__ "TaoLineSearchView_MT" 41 static PetscErrorCode TaoLineSearchView_MT(TaoLineSearch ls, PetscViewer pv) 42 { 43 PetscErrorCode ierr; 44 PetscBool isascii; 45 46 PetscFunctionBegin; 47 ierr = PetscObjectTypeCompare((PetscObject)pv, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 48 if (isascii) { 49 ierr = PetscViewerASCIIPrintf(pv," maxf=%D, ftol=%g, gtol=%g\n",ls->max_funcs,(double)ls->rtol,(double)ls->ftol);CHKERRQ(ierr); 50 } 51 PetscFunctionReturn(0); 52 } 53 54 #undef __FUNCT__ 55 #define __FUNCT__ "TaoLineSearchApply_MT" 56 /* @ TaoApply_LineSearch - This routine takes step length of 1.0. 57 58 Input Parameters: 59 + tao - Tao context 60 . X - current iterate (on output X contains new iterate, X + step*S) 61 . f - objective function evaluated at X 62 . G - gradient evaluated at X 63 - D - search direction 64 65 66 Info is set to 0. 67 68 @ */ 69 70 static PetscErrorCode TaoLineSearchApply_MT(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s) 71 { 72 PetscErrorCode ierr; 73 TaoLineSearch_MT *mt; 74 75 PetscReal xtrapf = 4.0; 76 PetscReal finit, width, width1, dginit, fm, fxm, fym, dgm, dgxm, dgym; 77 PetscReal dgx, dgy, dg, dg2, fx, fy, stx, sty, dgtest; 78 PetscReal ftest1=0.0, ftest2=0.0; 79 PetscInt i, stage1,n1,n2,nn1,nn2; 80 PetscReal bstepmin1, bstepmin2, bstepmax; 81 PetscBool g_computed=PETSC_FALSE; /* to prevent extra gradient computation */ 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1); 85 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 86 PetscValidScalarPointer(f,3); 87 PetscValidHeaderSpecific(g,VEC_CLASSID,4); 88 PetscValidHeaderSpecific(s,VEC_CLASSID,5); 89 90 /* comm,type,size checks are done in interface TaoLineSearchApply */ 91 mt = (TaoLineSearch_MT*)(ls->data); 92 ls->reason = TAOLINESEARCH_CONTINUE_ITERATING; 93 94 /* Check work vector */ 95 if (!mt->work) { 96 ierr = VecDuplicate(x,&mt->work);CHKERRQ(ierr); 97 mt->x = x; 98 ierr = PetscObjectReference((PetscObject)mt->x);CHKERRQ(ierr); 99 } else if (x != mt->x) { 100 ierr = VecDestroy(&mt->work);CHKERRQ(ierr); 101 ierr = VecDuplicate(x,&mt->work);CHKERRQ(ierr); 102 ierr = PetscObjectDereference((PetscObject)mt->x);CHKERRQ(ierr); 103 mt->x = x; 104 ierr = PetscObjectReference((PetscObject)mt->x);CHKERRQ(ierr); 105 } 106 107 if (ls->bounded) { 108 /* Compute step length needed to make all variables equal a bound */ 109 /* Compute the smallest steplength that will make one nonbinding variable 110 equal the bound */ 111 ierr = VecGetLocalSize(ls->upper,&n1);CHKERRQ(ierr); 112 ierr = VecGetLocalSize(mt->x, &n2);CHKERRQ(ierr); 113 ierr = VecGetSize(ls->upper,&nn1);CHKERRQ(ierr); 114 ierr = VecGetSize(mt->x,&nn2);CHKERRQ(ierr); 115 if (n1 != n2 || nn1 != nn2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Variable vector not compatible with bounds vector"); 116 ierr = VecScale(s,-1.0);CHKERRQ(ierr); 117 ierr = VecBoundGradientProjection(s,x,ls->lower,ls->upper,s);CHKERRQ(ierr); 118 ierr = VecScale(s,-1.0);CHKERRQ(ierr); 119 ierr = VecStepBoundInfo(x,s,ls->lower,ls->upper,&bstepmin1,&bstepmin2,&bstepmax);CHKERRQ(ierr); 120 ls->stepmax = PetscMin(bstepmax,1.0e15); 121 } 122 123 ierr = VecDot(g,s,&dginit); 124 if (PetscIsInfOrNanReal(dginit)) { 125 ierr = PetscInfo1(ls,"Initial Line Search step * g is Inf or Nan (%g)\n",(double)dginit);CHKERRQ(ierr); 126 ls->reason=TAOLINESEARCH_FAILED_INFORNAN; 127 PetscFunctionReturn(0); 128 } 129 if (dginit >= 0.0) { 130 ierr = PetscInfo1(ls,"Initial Line Search step * g is not descent direction (%g)\n",(double)dginit);CHKERRQ(ierr); 131 ls->reason = TAOLINESEARCH_FAILED_ASCENT; 132 PetscFunctionReturn(0); 133 } 134 135 136 /* Initialization */ 137 mt->bracket = 0; 138 stage1 = 1; 139 finit = *f; 140 dgtest = ls->ftol * dginit; 141 width = ls->stepmax - ls->stepmin; 142 width1 = width * 2.0; 143 ierr = VecCopy(x,mt->work);CHKERRQ(ierr); 144 /* Variable dictionary: 145 stx, fx, dgx - the step, function, and derivative at the best step 146 sty, fy, dgy - the step, function, and derivative at the other endpoint 147 of the interval of uncertainty 148 step, f, dg - the step, function, and derivative at the current step */ 149 150 stx = 0.0; 151 fx = finit; 152 dgx = dginit; 153 sty = 0.0; 154 fy = finit; 155 dgy = dginit; 156 157 ls->step=ls->initstep; 158 for (i=0; i< ls->max_funcs; i++) { 159 /* Set min and max steps to correspond to the interval of uncertainty */ 160 if (mt->bracket) { 161 ls->stepmin = PetscMin(stx,sty); 162 ls->stepmax = PetscMax(stx,sty); 163 } else { 164 ls->stepmin = stx; 165 ls->stepmax = ls->step + xtrapf * (ls->step - stx); 166 } 167 168 /* Force the step to be within the bounds */ 169 ls->step = PetscMax(ls->step,ls->stepmin); 170 ls->step = PetscMin(ls->step,ls->stepmax); 171 172 /* If an unusual termination is to occur, then let step be the lowest 173 point obtained thus far */ 174 if ((stx!=0) && (((mt->bracket) && (ls->step <= ls->stepmin || ls->step >= ls->stepmax)) || ((mt->bracket) && (ls->stepmax - ls->stepmin <= ls->rtol * ls->stepmax)) || 175 ((ls->nfeval+ls->nfgeval) >= ls->max_funcs - 1) || (mt->infoc == 0))) { 176 ls->step = stx; 177 } 178 179 ierr = VecCopy(x,mt->work);CHKERRQ(ierr); 180 ierr = VecAXPY(mt->work,ls->step,s);CHKERRQ(ierr); /* W = X + step*S */ 181 182 if (ls->bounded) { 183 ierr = VecMedian(ls->lower, mt->work, ls->upper, mt->work);CHKERRQ(ierr); 184 } 185 if (ls->usegts) { 186 ierr = TaoLineSearchComputeObjectiveAndGTS(ls,mt->work,f,&dg);CHKERRQ(ierr); 187 g_computed=PETSC_FALSE; 188 } else { 189 ierr = TaoLineSearchComputeObjectiveAndGradient(ls,mt->work,f,g);CHKERRQ(ierr); 190 g_computed=PETSC_TRUE; 191 if (ls->bounded) { 192 ierr = VecDot(g,x,&dg);CHKERRQ(ierr); 193 ierr = VecDot(g,mt->work,&dg2);CHKERRQ(ierr); 194 dg = (dg2 - dg)/ls->step; 195 } else { 196 ierr = VecDot(g,s,&dg);CHKERRQ(ierr); 197 } 198 } 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 EXTERN_C_BEGIN 310 #undef __FUNCT__ 311 #define __FUNCT__ "TaoLineSearchCreate_MT" 312 PetscErrorCode TaoLineSearchCreate_MT(TaoLineSearch ls) 313 { 314 PetscErrorCode ierr; 315 TaoLineSearch_MT *ctx; 316 317 PetscFunctionBegin; 318 PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1); 319 ierr = PetscNewLog(ls,&ctx);CHKERRQ(ierr); 320 ctx->bracket=0; 321 ctx->infoc=1; 322 ls->data = (void*)ctx; 323 ls->initstep = 1.0; 324 ls->ops->setup=0; 325 ls->ops->apply=TaoLineSearchApply_MT; 326 ls->ops->view =TaoLineSearchView_MT; 327 ls->ops->destroy=TaoLineSearchDestroy_MT; 328 ls->ops->setfromoptions=TaoLineSearchSetFromOptions_MT; 329 PetscFunctionReturn(0); 330 } 331 EXTERN_C_END 332 333 /* 334 The subroutine mcstep is taken from the work of Jorge Nocedal. 335 this is a variant of More' and Thuente's routine. 336 337 subroutine mcstep 338 339 the purpose of mcstep is to compute a safeguarded step for 340 a linesearch and to update an interval of uncertainty for 341 a minimizer of the function. 342 343 the parameter stx contains the step with the least function 344 value. the parameter stp contains the current step. it is 345 assumed that the derivative at stx is negative in the 346 direction of the step. if bracket is set true then a 347 minimizer has been bracketed in an interval of uncertainty 348 with endpoints stx and sty. 349 350 the subroutine statement is 351 352 subroutine mcstep(stx,fx,dx,sty,fy,dy,stp,fp,dp,bracket, 353 stpmin,stpmax,info) 354 355 where 356 357 stx, fx, and dx are variables which specify the step, 358 the function, and the derivative at the best step obtained 359 so far. The derivative must be negative in the direction 360 of the step, that is, dx and stp-stx must have opposite 361 signs. On output these parameters are updated appropriately. 362 363 sty, fy, and dy are variables which specify the step, 364 the function, and the derivative at the other endpoint of 365 the interval of uncertainty. On output these parameters are 366 updated appropriately. 367 368 stp, fp, and dp are variables which specify the step, 369 the function, and the derivative at the current step. 370 If bracket is set true then on input stp must be 371 between stx and sty. On output stp is set to the new step. 372 373 bracket is a logical variable which specifies if a minimizer 374 has been bracketed. If the minimizer has not been bracketed 375 then on input bracket must be set false. If the minimizer 376 is bracketed then on output bracket is set true. 377 378 stpmin and stpmax are input variables which specify lower 379 and upper bounds for the step. 380 381 info is an integer output variable set as follows: 382 if info = 1,2,3,4,5, then the step has been computed 383 according to one of the five cases below. otherwise 384 info = 0, and this indicates improper input parameters. 385 386 subprograms called 387 388 fortran-supplied ... abs,max,min,sqrt 389 390 argonne national laboratory. minpack project. june 1983 391 jorge j. more', david j. thuente 392 393 */ 394 395 #undef __FUNCT__ 396 #define __FUNCT__ "Tao_mcstep" 397 static PetscErrorCode Tao_mcstep(TaoLineSearch ls,PetscReal *stx,PetscReal *fx,PetscReal *dx,PetscReal *sty,PetscReal *fy,PetscReal *dy,PetscReal *stp,PetscReal *fp,PetscReal *dp) 398 { 399 TaoLineSearch_MT *mtP = (TaoLineSearch_MT *) ls->data; 400 PetscReal gamma1, p, q, r, s, sgnd, stpc, stpf, stpq, theta; 401 PetscInt bound; 402 403 PetscFunctionBegin; 404 /* Check the input parameters for errors */ 405 mtP->infoc = 0; 406 if (mtP->bracket && (*stp <= PetscMin(*stx,*sty) || (*stp >= PetscMax(*stx,*sty)))) SETERRQ(PETSC_COMM_SELF,1,"bad stp in bracket"); 407 if (*dx * (*stp-*stx) >= 0.0) SETERRQ(PETSC_COMM_SELF,1,"dx * (stp-stx) >= 0.0"); 408 if (ls->stepmax < ls->stepmin) SETERRQ(PETSC_COMM_SELF,1,"stepmax > stepmin"); 409 410 /* Determine if the derivatives have opposite sign */ 411 sgnd = *dp * (*dx / PetscAbsReal(*dx)); 412 413 if (*fp > *fx) { 414 /* Case 1: a higher function value. 415 The minimum is bracketed. If the cubic step is closer 416 to stx than the quadratic step, the cubic step is taken, 417 else the average of the cubic and quadratic steps is taken. */ 418 419 mtP->infoc = 1; 420 bound = 1; 421 theta = 3 * (*fx - *fp) / (*stp - *stx) + *dx + *dp; 422 s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dx)); 423 s = PetscMax(s,PetscAbsReal(*dp)); 424 gamma1 = s*PetscSqrtScalar(PetscPowScalar(theta/s,2.0) - (*dx/s)*(*dp/s)); 425 if (*stp < *stx) gamma1 = -gamma1; 426 /* Can p be 0? Check */ 427 p = (gamma1 - *dx) + theta; 428 q = ((gamma1 - *dx) + gamma1) + *dp; 429 r = p/q; 430 stpc = *stx + r*(*stp - *stx); 431 stpq = *stx + ((*dx/((*fx-*fp)/(*stp-*stx)+*dx))*0.5) * (*stp - *stx); 432 433 if (PetscAbsReal(stpc-*stx) < PetscAbsReal(stpq-*stx)) { 434 stpf = stpc; 435 } else { 436 stpf = stpc + 0.5*(stpq - stpc); 437 } 438 mtP->bracket = 1; 439 } else if (sgnd < 0.0) { 440 /* Case 2: A lower function value and derivatives of 441 opposite sign. The minimum is bracketed. If the cubic 442 step is closer to stx than the quadratic (secant) step, 443 the cubic step is taken, else the quadratic step is taken. */ 444 445 mtP->infoc = 2; 446 bound = 0; 447 theta = 3*(*fx - *fp)/(*stp - *stx) + *dx + *dp; 448 s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dx)); 449 s = PetscMax(s,PetscAbsReal(*dp)); 450 gamma1 = s*PetscSqrtScalar(PetscPowScalar(theta/s,2.0) - (*dx/s)*(*dp/s)); 451 if (*stp > *stx) gamma1 = -gamma1; 452 p = (gamma1 - *dp) + theta; 453 q = ((gamma1 - *dp) + gamma1) + *dx; 454 r = p/q; 455 stpc = *stp + r*(*stx - *stp); 456 stpq = *stp + (*dp/(*dp-*dx))*(*stx - *stp); 457 458 if (PetscAbsReal(stpc-*stp) > PetscAbsReal(stpq-*stp)) { 459 stpf = stpc; 460 } else { 461 stpf = stpq; 462 } 463 mtP->bracket = 1; 464 } else if (PetscAbsReal(*dp) < PetscAbsReal(*dx)) { 465 /* Case 3: A lower function value, derivatives of the 466 same sign, and the magnitude of the derivative decreases. 467 The cubic step is only used if the cubic tends to infinity 468 in the direction of the step or if the minimum of the cubic 469 is beyond stp. Otherwise the cubic step is defined to be 470 either stepmin or stepmax. The quadratic (secant) step is also 471 computed and if the minimum is bracketed then the the step 472 closest to stx is taken, else the step farthest away is taken. */ 473 474 mtP->infoc = 3; 475 bound = 1; 476 theta = 3*(*fx - *fp)/(*stp - *stx) + *dx + *dp; 477 s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dx)); 478 s = PetscMax(s,PetscAbsReal(*dp)); 479 480 /* The case gamma1 = 0 only arises if the cubic does not tend 481 to infinity in the direction of the step. */ 482 gamma1 = s*PetscSqrtScalar(PetscMax(0.0,PetscPowScalar(theta/s,2.0) - (*dx/s)*(*dp/s))); 483 if (*stp > *stx) gamma1 = -gamma1; 484 p = (gamma1 - *dp) + theta; 485 q = (gamma1 + (*dx - *dp)) + gamma1; 486 r = p/q; 487 if (r < 0.0 && gamma1 != 0.0) stpc = *stp + r*(*stx - *stp); 488 else if (*stp > *stx) stpc = ls->stepmax; 489 else stpc = ls->stepmin; 490 stpq = *stp + (*dp/(*dp-*dx)) * (*stx - *stp); 491 492 if (mtP->bracket) { 493 if (PetscAbsReal(*stp-stpc) < PetscAbsReal(*stp-stpq)) { 494 stpf = stpc; 495 } else { 496 stpf = stpq; 497 } 498 } else { 499 if (PetscAbsReal(*stp-stpc) > PetscAbsReal(*stp-stpq)) { 500 stpf = stpc; 501 } else { 502 stpf = stpq; 503 } 504 } 505 } else { 506 /* Case 4: A lower function value, derivatives of the 507 same sign, and the magnitude of the derivative does 508 not decrease. If the minimum is not bracketed, the step 509 is either stpmin or stpmax, else the cubic step is taken. */ 510 511 mtP->infoc = 4; 512 bound = 0; 513 if (mtP->bracket) { 514 theta = 3*(*fp - *fy)/(*sty - *stp) + *dy + *dp; 515 s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dy)); 516 s = PetscMax(s,PetscAbsReal(*dp)); 517 gamma1 = s*PetscSqrtScalar(PetscPowScalar(theta/s,2.0) - (*dy/s)*(*dp/s)); 518 if (*stp > *sty) gamma1 = -gamma1; 519 p = (gamma1 - *dp) + theta; 520 q = ((gamma1 - *dp) + gamma1) + *dy; 521 r = p/q; 522 stpc = *stp + r*(*sty - *stp); 523 stpq = *stp + (*dp/(*dp-*dx)) * (*stx - *stp); 524 525 stpf = stpc; 526 } else if (*stp > *stx) { 527 stpf = ls->stepmax; 528 } else { 529 stpf = ls->stepmin; 530 } 531 } 532 533 /* Update the interval of uncertainty. This update does not 534 depend on the new step or the case analysis above. */ 535 536 if (*fp > *fx) { 537 *sty = *stp; 538 *fy = *fp; 539 *dy = *dp; 540 } else { 541 if (sgnd < 0.0) { 542 *sty = *stx; 543 *fy = *fx; 544 *dy = *dx; 545 } 546 *stx = *stp; 547 *fx = *fp; 548 *dx = *dp; 549 } 550 551 /* Compute the new step and safeguard it. */ 552 stpf = PetscMin(ls->stepmax,stpf); 553 stpf = PetscMax(ls->stepmin,stpf); 554 *stp = stpf; 555 if (mtP->bracket && bound) { 556 if (*sty > *stx) { 557 *stp = PetscMin(*stx+0.66*(*sty-*stx),*stp); 558 } else { 559 *stp = PetscMax(*stx+0.66*(*sty-*stx),*stp); 560 } 561 } 562 PetscFunctionReturn(0); 563 } 564