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 break; 227 } 228 229 /* Checks for bad cases */ 230 if (((mt->bracket) && (ls->step <= ls->stepmin||ls->step >= ls->stepmax)) || (!mt->infoc)) { 231 ierr = PetscInfo(ls,"Rounding errors may prevent further progress. May not be a step satisfying\n");CHKERRQ(ierr); 232 ierr = PetscInfo(ls,"sufficient decrease and curvature conditions. Tolerances may be too small.\n");CHKERRQ(ierr); 233 ls->reason = TAOLINESEARCH_HALTED_OTHER; 234 break; 235 } 236 if ((ls->step == ls->stepmax) && (*f <= ftest1) && (dg <= dgtest)) { 237 ierr = PetscInfo1(ls,"Step is at the upper bound, stepmax (%g)\n",(double)ls->stepmax);CHKERRQ(ierr); 238 ls->reason = TAOLINESEARCH_HALTED_UPPERBOUND; 239 break; 240 } 241 if ((ls->step == ls->stepmin) && (*f >= ftest1) && (dg >= dgtest)) { 242 ierr = PetscInfo1(ls,"Step is at the lower bound, stepmin (%g)\n",(double)ls->stepmin);CHKERRQ(ierr); 243 ls->reason = TAOLINESEARCH_HALTED_LOWERBOUND; 244 break; 245 } 246 if ((mt->bracket) && (ls->stepmax - ls->stepmin <= ls->rtol*ls->stepmax)){ 247 ierr = PetscInfo1(ls,"Relative width of interval of uncertainty is at most rtol (%g)\n",(double)ls->rtol);CHKERRQ(ierr); 248 ls->reason = TAOLINESEARCH_HALTED_RTOL; 249 break; 250 } 251 252 /* In the first stage, we seek a step for which the modified function 253 has a nonpositive value and nonnegative derivative */ 254 if ((stage1) && (*f <= ftest1) && (dg >= dginit * PetscMin(ls->ftol, ls->gtol))) { 255 stage1 = 0; 256 } 257 258 /* A modified function is used to predict the step only if we 259 have not obtained a step for which the modified function has a 260 nonpositive function value and nonnegative derivative, and if a 261 lower function value has been obtained but the decrease is not 262 sufficient */ 263 264 if ((stage1) && (*f <= fx) && (*f > ftest1)) { 265 fm = *f - ls->step * dgtest; /* Define modified function */ 266 fxm = fx - stx * dgtest; /* and derivatives */ 267 fym = fy - sty * dgtest; 268 dgm = dg - dgtest; 269 dgxm = dgx - dgtest; 270 dgym = dgy - dgtest; 271 272 /* if (dgxm * (ls->step - stx) >= 0.0) */ 273 /* Update the interval of uncertainty and compute the new step */ 274 ierr = Tao_mcstep(ls,&stx,&fxm,&dgxm,&sty,&fym,&dgym,&ls->step,&fm,&dgm);CHKERRQ(ierr); 275 276 fx = fxm + stx * dgtest; /* Reset the function and */ 277 fy = fym + sty * dgtest; /* gradient values */ 278 dgx = dgxm + dgtest; 279 dgy = dgym + dgtest; 280 } else { 281 /* Update the interval of uncertainty and compute the new step */ 282 ierr = Tao_mcstep(ls,&stx,&fx,&dgx,&sty,&fy,&dgy,&ls->step,f,&dg);CHKERRQ(ierr); 283 } 284 285 /* Force a sufficient decrease in the interval of uncertainty */ 286 if (mt->bracket) { 287 if (PetscAbsReal(sty - stx) >= 0.66 * width1) ls->step = stx + 0.5*(sty - stx); 288 width1 = width; 289 width = PetscAbsReal(sty - stx); 290 } 291 } 292 if ((ls->nfeval+ls->nfgeval) > ls->max_funcs) { 293 ierr = PetscInfo2(ls,"Number of line search function evals (%D) > maximum (%D)\n",(ls->nfeval+ls->nfgeval),ls->max_funcs);CHKERRQ(ierr); 294 ls->reason = TAOLINESEARCH_HALTED_MAXFCN; 295 } 296 297 /* Finish computations */ 298 ierr = PetscInfo2(ls,"%D function evals in line search, step = %g\n",(ls->nfeval+ls->nfgeval),(double)ls->step);CHKERRQ(ierr); 299 300 /* Set new solution vector and compute gradient if needed */ 301 ierr = VecCopy(mt->work,x);CHKERRQ(ierr); 302 if (!g_computed) { 303 ierr = TaoLineSearchComputeGradient(ls,mt->work,g);CHKERRQ(ierr); 304 } 305 PetscFunctionReturn(0); 306 } 307 308 EXTERN_C_BEGIN 309 #undef __FUNCT__ 310 #define __FUNCT__ "TaoLineSearchCreate_MT" 311 PetscErrorCode TaoLineSearchCreate_MT(TaoLineSearch ls) 312 { 313 PetscErrorCode ierr; 314 TaoLineSearch_MT *ctx; 315 316 PetscFunctionBegin; 317 PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1); 318 ierr = PetscNewLog(ls,&ctx);CHKERRQ(ierr); 319 ctx->bracket=0; 320 ctx->infoc=1; 321 ls->data = (void*)ctx; 322 ls->initstep = 1.0; 323 ls->ops->setup=0; 324 ls->ops->apply=TaoLineSearchApply_MT; 325 ls->ops->view =TaoLineSearchView_MT; 326 ls->ops->destroy=TaoLineSearchDestroy_MT; 327 ls->ops->setfromoptions=TaoLineSearchSetFromOptions_MT; 328 PetscFunctionReturn(0); 329 } 330 EXTERN_C_END 331 332 /* 333 The subroutine mcstep is taken from the work of Jorge Nocedal. 334 this is a variant of More' and Thuente's routine. 335 336 subroutine mcstep 337 338 the purpose of mcstep is to compute a safeguarded step for 339 a linesearch and to update an interval of uncertainty for 340 a minimizer of the function. 341 342 the parameter stx contains the step with the least function 343 value. the parameter stp contains the current step. it is 344 assumed that the derivative at stx is negative in the 345 direction of the step. if bracket is set true then a 346 minimizer has been bracketed in an interval of uncertainty 347 with endpoints stx and sty. 348 349 the subroutine statement is 350 351 subroutine mcstep(stx,fx,dx,sty,fy,dy,stp,fp,dp,bracket, 352 stpmin,stpmax,info) 353 354 where 355 356 stx, fx, and dx are variables which specify the step, 357 the function, and the derivative at the best step obtained 358 so far. The derivative must be negative in the direction 359 of the step, that is, dx and stp-stx must have opposite 360 signs. On output these parameters are updated appropriately. 361 362 sty, fy, and dy are variables which specify the step, 363 the function, and the derivative at the other endpoint of 364 the interval of uncertainty. On output these parameters are 365 updated appropriately. 366 367 stp, fp, and dp are variables which specify the step, 368 the function, and the derivative at the current step. 369 If bracket is set true then on input stp must be 370 between stx and sty. On output stp is set to the new step. 371 372 bracket is a logical variable which specifies if a minimizer 373 has been bracketed. If the minimizer has not been bracketed 374 then on input bracket must be set false. If the minimizer 375 is bracketed then on output bracket is set true. 376 377 stpmin and stpmax are input variables which specify lower 378 and upper bounds for the step. 379 380 info is an integer output variable set as follows: 381 if info = 1,2,3,4,5, then the step has been computed 382 according to one of the five cases below. otherwise 383 info = 0, and this indicates improper input parameters. 384 385 subprograms called 386 387 fortran-supplied ... abs,max,min,sqrt 388 389 argonne national laboratory. minpack project. june 1983 390 jorge j. more', david j. thuente 391 392 */ 393 394 #undef __FUNCT__ 395 #define __FUNCT__ "Tao_mcstep" 396 static PetscErrorCode Tao_mcstep(TaoLineSearch ls,PetscReal *stx,PetscReal *fx,PetscReal *dx,PetscReal *sty,PetscReal *fy,PetscReal *dy,PetscReal *stp,PetscReal *fp,PetscReal *dp) 397 { 398 TaoLineSearch_MT *mtP = (TaoLineSearch_MT *) ls->data; 399 PetscReal gamma1, p, q, r, s, sgnd, stpc, stpf, stpq, theta; 400 PetscInt bound; 401 402 PetscFunctionBegin; 403 /* Check the input parameters for errors */ 404 mtP->infoc = 0; 405 if (mtP->bracket && (*stp <= PetscMin(*stx,*sty) || (*stp >= PetscMax(*stx,*sty)))) SETERRQ(PETSC_COMM_SELF,1,"bad stp in bracket"); 406 if (*dx * (*stp-*stx) >= 0.0) SETERRQ(PETSC_COMM_SELF,1,"dx * (stp-stx) >= 0.0"); 407 if (ls->stepmax < ls->stepmin) SETERRQ(PETSC_COMM_SELF,1,"stepmax > stepmin"); 408 409 /* Determine if the derivatives have opposite sign */ 410 sgnd = *dp * (*dx / PetscAbsReal(*dx)); 411 412 if (*fp > *fx) { 413 /* Case 1: a higher function value. 414 The minimum is bracketed. If the cubic step is closer 415 to stx than the quadratic step, the cubic step is taken, 416 else the average of the cubic and quadratic steps is taken. */ 417 418 mtP->infoc = 1; 419 bound = 1; 420 theta = 3 * (*fx - *fp) / (*stp - *stx) + *dx + *dp; 421 s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dx)); 422 s = PetscMax(s,PetscAbsReal(*dp)); 423 gamma1 = s*PetscSqrtScalar(PetscPowScalar(theta/s,2.0) - (*dx/s)*(*dp/s)); 424 if (*stp < *stx) gamma1 = -gamma1; 425 /* Can p be 0? Check */ 426 p = (gamma1 - *dx) + theta; 427 q = ((gamma1 - *dx) + gamma1) + *dp; 428 r = p/q; 429 stpc = *stx + r*(*stp - *stx); 430 stpq = *stx + ((*dx/((*fx-*fp)/(*stp-*stx)+*dx))*0.5) * (*stp - *stx); 431 432 if (PetscAbsReal(stpc-*stx) < PetscAbsReal(stpq-*stx)) { 433 stpf = stpc; 434 } else { 435 stpf = stpc + 0.5*(stpq - stpc); 436 } 437 mtP->bracket = 1; 438 } else if (sgnd < 0.0) { 439 /* Case 2: A lower function value and derivatives of 440 opposite sign. The minimum is bracketed. If the cubic 441 step is closer to stx than the quadratic (secant) step, 442 the cubic step is taken, else the quadratic step is taken. */ 443 444 mtP->infoc = 2; 445 bound = 0; 446 theta = 3*(*fx - *fp)/(*stp - *stx) + *dx + *dp; 447 s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dx)); 448 s = PetscMax(s,PetscAbsReal(*dp)); 449 gamma1 = s*PetscSqrtScalar(PetscPowScalar(theta/s,2.0) - (*dx/s)*(*dp/s)); 450 if (*stp > *stx) gamma1 = -gamma1; 451 p = (gamma1 - *dp) + theta; 452 q = ((gamma1 - *dp) + gamma1) + *dx; 453 r = p/q; 454 stpc = *stp + r*(*stx - *stp); 455 stpq = *stp + (*dp/(*dp-*dx))*(*stx - *stp); 456 457 if (PetscAbsReal(stpc-*stp) > PetscAbsReal(stpq-*stp)) { 458 stpf = stpc; 459 } else { 460 stpf = stpq; 461 } 462 mtP->bracket = 1; 463 } else if (PetscAbsReal(*dp) < PetscAbsReal(*dx)) { 464 /* Case 3: A lower function value, derivatives of the 465 same sign, and the magnitude of the derivative decreases. 466 The cubic step is only used if the cubic tends to infinity 467 in the direction of the step or if the minimum of the cubic 468 is beyond stp. Otherwise the cubic step is defined to be 469 either stepmin or stepmax. The quadratic (secant) step is also 470 computed and if the minimum is bracketed then the the step 471 closest to stx is taken, else the step farthest away is taken. */ 472 473 mtP->infoc = 3; 474 bound = 1; 475 theta = 3*(*fx - *fp)/(*stp - *stx) + *dx + *dp; 476 s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dx)); 477 s = PetscMax(s,PetscAbsReal(*dp)); 478 479 /* The case gamma1 = 0 only arises if the cubic does not tend 480 to infinity in the direction of the step. */ 481 gamma1 = s*PetscSqrtScalar(PetscMax(0.0,PetscPowScalar(theta/s,2.0) - (*dx/s)*(*dp/s))); 482 if (*stp > *stx) gamma1 = -gamma1; 483 p = (gamma1 - *dp) + theta; 484 q = (gamma1 + (*dx - *dp)) + gamma1; 485 r = p/q; 486 if (r < 0.0 && gamma1 != 0.0) stpc = *stp + r*(*stx - *stp); 487 else if (*stp > *stx) stpc = ls->stepmax; 488 else stpc = ls->stepmin; 489 stpq = *stp + (*dp/(*dp-*dx)) * (*stx - *stp); 490 491 if (mtP->bracket) { 492 if (PetscAbsReal(*stp-stpc) < PetscAbsReal(*stp-stpq)) { 493 stpf = stpc; 494 } else { 495 stpf = stpq; 496 } 497 } else { 498 if (PetscAbsReal(*stp-stpc) > PetscAbsReal(*stp-stpq)) { 499 stpf = stpc; 500 } else { 501 stpf = stpq; 502 } 503 } 504 } else { 505 /* Case 4: A lower function value, derivatives of the 506 same sign, and the magnitude of the derivative does 507 not decrease. If the minimum is not bracketed, the step 508 is either stpmin or stpmax, else the cubic step is taken. */ 509 510 mtP->infoc = 4; 511 bound = 0; 512 if (mtP->bracket) { 513 theta = 3*(*fp - *fy)/(*sty - *stp) + *dy + *dp; 514 s = PetscMax(PetscAbsReal(theta),PetscAbsReal(*dy)); 515 s = PetscMax(s,PetscAbsReal(*dp)); 516 gamma1 = s*PetscSqrtScalar(PetscPowScalar(theta/s,2.0) - (*dy/s)*(*dp/s)); 517 if (*stp > *sty) gamma1 = -gamma1; 518 p = (gamma1 - *dp) + theta; 519 q = ((gamma1 - *dp) + gamma1) + *dy; 520 r = p/q; 521 stpc = *stp + r*(*sty - *stp); 522 stpq = *stp + (*dp/(*dp-*dx)) * (*stx - *stp); 523 524 stpf = stpc; 525 } else if (*stp > *stx) { 526 stpf = ls->stepmax; 527 } else { 528 stpf = ls->stepmin; 529 } 530 } 531 532 /* Update the interval of uncertainty. This update does not 533 depend on the new step or the case analysis above. */ 534 535 if (*fp > *fx) { 536 *sty = *stp; 537 *fy = *fp; 538 *dy = *dp; 539 } else { 540 if (sgnd < 0.0) { 541 *sty = *stx; 542 *fy = *fx; 543 *dy = *dx; 544 } 545 *stx = *stp; 546 *fx = *fp; 547 *dx = *dp; 548 } 549 550 /* Compute the new step and safeguard it. */ 551 stpf = PetscMin(ls->stepmax,stpf); 552 stpf = PetscMax(ls->stepmin,stpf); 553 *stp = stpf; 554 if (mtP->bracket && bound) { 555 if (*sty > *stx) { 556 *stp = PetscMin(*stx+0.66*(*sty-*stx),*stp); 557 } else { 558 *stp = PetscMax(*stx+0.66*(*sty-*stx),*stp); 559 } 560 } 561 PetscFunctionReturn(0); 562 } 563