1 #ifndef lint 2 static char vcid[] = "$Id: ls.c,v 1.70 1996/08/12 03:42:59 bsmith Exp bsmith $"; 3 #endif 4 5 #include <math.h> 6 #include "src/snes/impls/ls/ls.h" 7 #include "pinclude/pviewer.h" 8 9 /* 10 Implements a line search variant of Newton's Method 11 for solving systems of nonlinear equations. 12 13 Input parameters: 14 . snes - nonlinear context obtained from SNESCreate() 15 16 Output Parameters: 17 . outits - Number of global iterations until termination. 18 19 Notes: 20 This implements essentially a truncated Newton method with a 21 line search. By default a cubic backtracking line search 22 is employed, as described in the text "Numerical Methods for 23 Unconstrained Optimization and Nonlinear Equations" by Dennis 24 and Schnabel. 25 */ 26 27 int SNESSolve_EQ_LS(SNES snes,int *outits) 28 { 29 SNES_LS *neP = (SNES_LS *) snes->data; 30 int maxits, i, history_len, ierr, lits, lsfail; 31 MatStructure flg = DIFFERENT_NONZERO_PATTERN; 32 double fnorm, gnorm, xnorm, ynorm, *history; 33 Vec Y, X, F, G, W, TMP; 34 35 history = snes->conv_hist; /* convergence history */ 36 history_len = snes->conv_hist_len; /* convergence history length */ 37 maxits = snes->max_its; /* maximum number of iterations */ 38 X = snes->vec_sol; /* solution vector */ 39 F = snes->vec_func; /* residual vector */ 40 Y = snes->work[0]; /* work vectors */ 41 G = snes->work[1]; 42 W = snes->work[2]; 43 44 ierr = VecNorm(X,NORM_2,&xnorm); CHKERRQ(ierr); /* xnorm = || X || */ 45 snes->iter = 0; 46 ierr = SNESComputeFunction(snes,X,F); CHKERRQ(ierr); /* F(X) */ 47 ierr = VecNorm(F,NORM_2,&fnorm); CHKERRQ(ierr); /* fnorm <- ||F|| */ 48 snes->norm = fnorm; 49 if (history && history_len > 0) history[0] = fnorm; 50 SNESMonitor(snes,0,fnorm); 51 52 /* set parameter for default relative tolerance convergence test */ 53 snes->ttol = fnorm*snes->rtol; 54 55 for ( i=0; i<maxits; i++ ) { 56 snes->iter = i+1; 57 58 /* Solve J Y = -F, where J is Jacobian matrix */ 59 ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr); 60 ierr = SLESSetOperators(snes->sles,snes->jacobian,snes->jacobian_pre,flg); CHKERRQ(ierr); 61 ierr = SLESSolve(snes->sles,F,Y,&lits); CHKERRQ(ierr); 62 ierr = VecCopy(Y,snes->vec_sol_update_always); CHKERRQ(ierr); 63 ierr = (*neP->LineSearch)(snes,X,F,G,Y,W,fnorm,&ynorm,&gnorm,&lsfail);CHKERRQ(ierr); 64 if (lsfail) snes->nfailures++; 65 66 TMP = F; F = G; snes->vec_func_always = F; G = TMP; 67 TMP = X; X = Y; snes->vec_sol_always = X; Y = TMP; 68 fnorm = gnorm; 69 70 snes->norm = fnorm; 71 if (history && history_len > i+1) history[i+1] = fnorm; 72 ierr = VecNorm(X,NORM_2,&xnorm); CHKERRQ(ierr); /* xnorm = || X || */ 73 SNESMonitor(snes,i+1,fnorm); 74 75 /* Test for convergence */ 76 if ((*snes->converged)(snes,xnorm,ynorm,fnorm,snes->cnvP)) { 77 if (X != snes->vec_sol) { 78 ierr = VecCopy(X,snes->vec_sol); CHKERRQ(ierr); 79 snes->vec_sol_always = snes->vec_sol; 80 snes->vec_func_always = snes->vec_func; 81 } 82 break; 83 } 84 } 85 if (i == maxits) { 86 PLogInfo(snes, 87 "SNESSolve_EQ_LS: Maximum number of iterations has been reached: %d\n",maxits); 88 i--; 89 } 90 *outits = i+1; 91 return 0; 92 } 93 /* ------------------------------------------------------------ */ 94 int SNESSetUp_EQ_LS(SNES snes ) 95 { 96 int ierr; 97 snes->nwork = 4; 98 ierr = VecDuplicateVecs(snes->vec_sol,snes->nwork,&snes->work);CHKERRQ(ierr); 99 PLogObjectParents(snes,snes->nwork,snes->work); 100 snes->vec_sol_update_always = snes->work[3]; 101 return 0; 102 } 103 /* ------------------------------------------------------------ */ 104 int SNESDestroy_EQ_LS(PetscObject obj) 105 { 106 SNES snes = (SNES) obj; 107 int ierr; 108 if (snes->nwork) { 109 ierr = VecDestroyVecs(snes->work,snes->nwork); CHKERRQ(ierr); 110 } 111 PetscFree(snes->data); 112 return 0; 113 } 114 /* ------------------------------------------------------------ */ 115 /*ARGSUSED*/ 116 /*@C 117 SNESNoLineSearch - This routine is not a line search at all; 118 it simply uses the full Newton step. Thus, this routine is intended 119 to serve as a template and is not recommended for general use. 120 121 Input Parameters: 122 . snes - nonlinear context 123 . x - current iterate 124 . f - residual evaluated at x 125 . y - search direction (contains new iterate on output) 126 . w - work vector 127 . fnorm - 2-norm of f 128 129 Output Parameters: 130 . g - residual evaluated at new iterate y 131 . y - new iterate (contains search direction on input) 132 . gnorm - 2-norm of g 133 . ynorm - 2-norm of search length 134 . flag - set to 0, indicating a successful line search 135 136 Options Database Key: 137 $ -snes_line_search basic 138 139 .keywords: SNES, nonlinear, line search, cubic 140 141 .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(), 142 SNESSetLineSearch() 143 @*/ 144 int SNESNoLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w, 145 double fnorm, double *ynorm, double *gnorm,int *flag ) 146 { 147 int ierr; 148 Scalar mone = -1.0; 149 150 *flag = 0; 151 PLogEventBegin(SNES_LineSearch,snes,x,f,g); 152 ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr); /* ynorm = || y || */ 153 ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr); /* y <- x + y */ 154 ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* F(y) */ 155 ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); /* gnorm = || g || */ 156 PLogEventEnd(SNES_LineSearch,snes,x,f,g); 157 return 0; 158 } 159 /* ------------------------------------------------------------------ */ 160 /*@C 161 SNESCubicLineSearch - This routine performs a cubic line search and 162 is the default line search method. 163 164 Input Parameters: 165 . snes - nonlinear context 166 . x - current iterate 167 . f - residual evaluated at x 168 . y - search direction (contains new iterate on output) 169 . w - work vector 170 . fnorm - 2-norm of f 171 172 Output Parameters: 173 . g - residual evaluated at new iterate y 174 . y - new iterate (contains search direction on input) 175 . gnorm - 2-norm of g 176 . ynorm - 2-norm of search length 177 . flag - 0 if line search succeeds; -1 on failure. 178 179 Options Database Key: 180 $ -snes_line_search cubic 181 182 Notes: 183 This line search is taken from "Numerical Methods for Unconstrained 184 Optimization and Nonlinear Equations" by Dennis and Schnabel, page 325. 185 186 .keywords: SNES, nonlinear, line search, cubic 187 188 .seealso: SNESNoLineSearch(), SNESNoLineSearch(), SNESSetLineSearch() 189 @*/ 190 int SNESCubicLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w, 191 double fnorm, double *ynorm, double *gnorm,int *flag) 192 { 193 double steptol, initslope,lambdaprev, gnormprev,a, b, d, t1, t2; 194 double maxstep,minlambda,alpha,lambda,lambdatemp; 195 #if defined(PETSC_COMPLEX) 196 Scalar cinitslope,clambda; 197 #endif 198 int ierr, count; 199 SNES_LS *neP = (SNES_LS *) snes->data; 200 Scalar mone = -1.0,scale; 201 202 PLogEventBegin(SNES_LineSearch,snes,x,f,g); 203 *flag = 0; 204 alpha = neP->alpha; 205 maxstep = neP->maxstep; 206 steptol = neP->steptol; 207 208 ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr); 209 if (*ynorm > maxstep) { /* Step too big, so scale back */ 210 scale = maxstep/(*ynorm); 211 #if defined(PETSC_COMPLEX) 212 PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",real(scale)); 213 #else 214 PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",scale); 215 #endif 216 ierr = VecScale(&scale,y); CHKERRQ(ierr); 217 *ynorm = maxstep; 218 } 219 minlambda = steptol/(*ynorm); 220 ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr); 221 #if defined(PETSC_COMPLEX) 222 ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr); 223 initslope = real(cinitslope); 224 #else 225 ierr = VecDot(f,w,&initslope); CHKERRQ(ierr); 226 #endif 227 if (initslope > 0.0) initslope = -initslope; 228 if (initslope == 0.0) initslope = -1.0; 229 230 ierr = VecCopy(y,w); CHKERRQ(ierr); 231 ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr); 232 ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 233 ierr = VecNorm(g,NORM_2,gnorm); 234 if (*gnorm <= fnorm + alpha*initslope) { /* Sufficient reduction */ 235 ierr = VecCopy(w,y); CHKERRQ(ierr); 236 PLogInfo(snes,"SNESCubicLineSearch: Using full step\n"); 237 goto theend; 238 } 239 240 /* Fit points with quadratic */ 241 lambda = 1.0; count = 0; 242 lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 243 lambdaprev = lambda; 244 gnormprev = *gnorm; 245 if (lambdatemp <= .1*lambda) lambda = .1*lambda; 246 else lambda = lambdatemp; 247 ierr = VecCopy(x,w); CHKERRQ(ierr); 248 lambda = -lambda; 249 #if defined(PETSC_COMPLEX) 250 clambda = lambda; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr); 251 #else 252 ierr = VecAXPY(&lambda,y,w); CHKERRQ(ierr); 253 #endif 254 ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 255 ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 256 if (*gnorm <= fnorm + alpha*initslope) { /* sufficient reduction */ 257 ierr = VecCopy(w,y); CHKERRQ(ierr); 258 PLogInfo(snes, 259 "SNESCubicLineSearch: Quadratically determined step, lambda %g\n",lambda); 260 goto theend; 261 } 262 263 /* Fit points with cubic */ 264 count = 1; 265 while (1) { 266 if (lambda <= minlambda) { /* bad luck; use full step */ 267 PLogInfo(snes, 268 "SNESCubicLineSearch:Unable to find good step length! %d \n",count); 269 PLogInfo(snes, 270 "SNESCubicLineSearch:f %g fnew %g ynorm %g lambda %g initial slope %g\n",fnorm,*gnorm,*ynorm,lambda,initslope); 271 ierr = VecCopy(w,y); CHKERRQ(ierr); 272 *flag = -1; break; 273 } 274 t1 = *gnorm - fnorm - lambda*initslope; 275 t2 = gnormprev - fnorm - lambdaprev*initslope; 276 a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 277 b = (-lambdaprev*t1/(lambda*lambda) + 278 lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 279 d = b*b - 3*a*initslope; 280 if (d < 0.0) d = 0.0; 281 if (a == 0.0) { 282 lambdatemp = -initslope/(2.0*b); 283 } else { 284 lambdatemp = (-b + sqrt(d))/(3.0*a); 285 } 286 if (lambdatemp > .5*lambda) { 287 lambdatemp = .5*lambda; 288 } 289 lambdaprev = lambda; 290 gnormprev = *gnorm; 291 if (lambdatemp <= .1*lambda) { 292 lambda = .1*lambda; 293 } 294 else lambda = lambdatemp; 295 ierr = VecCopy( x, w ); CHKERRQ(ierr); 296 lambda = -lambda; 297 #if defined(PETSC_COMPLEX) 298 clambda = lambda; 299 ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr); 300 #else 301 ierr = VecAXPY(&lambda,y,w); CHKERRQ(ierr); 302 #endif 303 ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 304 ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 305 if (*gnorm <= fnorm + alpha*initslope) { /* is reduction enough */ 306 ierr = VecCopy(w,y); CHKERRQ(ierr); 307 PLogInfo(snes, 308 "SNESCubicLineSearch: Cubically determined step, lambda %g\n",lambda); 309 *flag = -1; break; 310 } 311 count++; 312 } 313 theend: 314 PLogEventEnd(SNES_LineSearch,snes,x,f,g); 315 return 0; 316 } 317 /* ------------------------------------------------------------------ */ 318 /*@C 319 SNESQuadraticLineSearch - This routine performs a cubic line search. 320 321 Input Parameters: 322 . snes - the SNES context 323 . x - current iterate 324 . f - residual evaluated at x 325 . y - search direction (contains new iterate on output) 326 . w - work vector 327 . fnorm - 2-norm of f 328 329 Output Parameters: 330 . g - residual evaluated at new iterate y 331 . y - new iterate (contains search direction on input) 332 . gnorm - 2-norm of g 333 . ynorm - 2-norm of search length 334 . flag - 0 if line search succeeds; -1 on failure. 335 336 Options Database Key: 337 $ -snes_line_search quadratic 338 339 Notes: 340 Use SNESSetLineSearch() 341 to set this routine within the SNES_EQ_LS method. 342 343 .keywords: SNES, nonlinear, quadratic, line search 344 345 .seealso: SNESCubicLineSearch(), SNESNoLineSearch(), SNESSetLineSearch() 346 @*/ 347 int SNESQuadraticLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w, 348 double fnorm, double *ynorm, double *gnorm,int *flag) 349 { 350 double steptol,initslope,lambdaprev,gnormprev,maxstep,minlambda,alpha,lambda,lambdatemp; 351 #if defined(PETSC_COMPLEX) 352 Scalar cinitslope,clambda; 353 #endif 354 int ierr,count; 355 SNES_LS *neP = (SNES_LS *) snes->data; 356 Scalar mone = -1.0,scale; 357 358 PLogEventBegin(SNES_LineSearch,snes,x,f,g); 359 *flag = 0; 360 alpha = neP->alpha; 361 maxstep = neP->maxstep; 362 steptol = neP->steptol; 363 364 VecNorm(y, NORM_2,ynorm ); 365 if (*ynorm > maxstep) { /* Step too big, so scale back */ 366 scale = maxstep/(*ynorm); 367 ierr = VecScale(&scale,y); CHKERRQ(ierr); 368 *ynorm = maxstep; 369 } 370 minlambda = steptol/(*ynorm); 371 ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr); 372 #if defined(PETSC_COMPLEX) 373 ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr); 374 initslope = real(cinitslope); 375 #else 376 ierr = VecDot(f,w,&initslope); CHKERRQ(ierr); 377 #endif 378 if (initslope > 0.0) initslope = -initslope; 379 if (initslope == 0.0) initslope = -1.0; 380 381 ierr = VecCopy(y,w); CHKERRQ(ierr); 382 ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr); 383 ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 384 ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 385 if (*gnorm <= fnorm + alpha*initslope) { /* Sufficient reduction */ 386 ierr = VecCopy(w,y); CHKERRQ(ierr); 387 PLogInfo(snes,"SNESQuadraticLineSearch: Using full step\n"); 388 goto theend; 389 } 390 391 /* Fit points with quadratic */ 392 lambda = 1.0; count = 0; 393 count = 1; 394 while (1) { 395 if (lambda <= minlambda) { /* bad luck; use full step */ 396 PLogInfo(snes, 397 "SNESQuadraticLineSearch:Unable to find good step length! %d \n",count); 398 PLogInfo(snes, 399 "SNESQuadraticLineSearch:f %g fnew %g ynorm %g lambda %g\n",fnorm,*gnorm,*ynorm,lambda); 400 ierr = VecCopy(w,y); CHKERRQ(ierr); 401 *flag = -1; break; 402 } 403 lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 404 lambdaprev = lambda; 405 gnormprev = *gnorm; 406 if (lambdatemp <= .1*lambda) { 407 lambda = .1*lambda; 408 } else lambda = lambdatemp; 409 ierr = VecCopy(x,w); CHKERRQ(ierr); 410 lambda = -lambda; 411 #if defined(PETSC_COMPLEX) 412 clambda = lambda; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr); 413 #else 414 ierr = VecAXPY(&lambda,y,w); CHKERRQ(ierr); 415 #endif 416 ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 417 ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 418 if (*gnorm <= fnorm + alpha*initslope) { /* sufficient reduction */ 419 ierr = VecCopy(w,y); CHKERRQ(ierr); 420 PLogInfo(snes, 421 "SNESQuadraticLineSearch:Quadratically determined step, lambda %g\n",lambda); 422 break; 423 } 424 count++; 425 } 426 theend: 427 PLogEventEnd(SNES_LineSearch,snes,x,f,g); 428 return 0; 429 } 430 /* ------------------------------------------------------------ */ 431 /*@C 432 SNESSetLineSearch - Sets the line search routine to be used 433 by the method SNES_EQ_LS. 434 435 Input Parameters: 436 . snes - nonlinear context obtained from SNESCreate() 437 . func - pointer to int function 438 439 Available Routines: 440 . SNESCubicLineSearch() - default line search 441 . SNESQuadraticLineSearch() - quadratic line search 442 . SNESNoLineSearch() - the full Newton step (actually not a line search) 443 444 Options Database Keys: 445 $ -snes_line_search [basic,quadratic,cubic] 446 447 Calling sequence of func: 448 func (SNES snes, Vec x, Vec f, Vec g, Vec y, 449 Vec w, double fnorm, double *ynorm, 450 double *gnorm, *flag) 451 452 Input parameters for func: 453 . snes - nonlinear context 454 . x - current iterate 455 . f - residual evaluated at x 456 . y - search direction (contains new iterate on output) 457 . w - work vector 458 . fnorm - 2-norm of f 459 460 Output parameters for func: 461 . g - residual evaluated at new iterate y 462 . y - new iterate (contains search direction on input) 463 . gnorm - 2-norm of g 464 . ynorm - 2-norm of search length 465 . flag - set to 0 if the line search succeeds; a nonzero integer 466 on failure. 467 468 .keywords: SNES, nonlinear, set, line search, routine 469 470 .seealso: SNESNoLineSearch(), SNESQuadraticLineSearch(), SNESCubicLineSearch() 471 @*/ 472 int SNESSetLineSearch(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec, 473 double,double*,double*,int*)) 474 { 475 if ((snes)->type == SNES_EQ_LS) ((SNES_LS *)(snes->data))->LineSearch = func; 476 return 0; 477 } 478 /* ------------------------------------------------------------------ */ 479 static int SNESPrintHelp_EQ_LS(SNES snes,char *p) 480 { 481 SNES_LS *ls = (SNES_LS *)snes->data; 482 483 PetscPrintf(snes->comm," method SNES_EQ_LS (ls) for systems of nonlinear equations:\n"); 484 PetscPrintf(snes->comm," %ssnes_line_search [basic,quadratic,cubic]\n",p); 485 PetscPrintf(snes->comm," %ssnes_line_search_alpha <alpha> (default %g)\n",p,ls->alpha); 486 PetscPrintf(snes->comm," %ssnes_line_search_maxstep <max> (default %g)\n",p,ls->maxstep); 487 PetscPrintf(snes->comm," %ssnes_line_search_steptol <tol> (default %g)\n",p,ls->steptol); 488 return 0; 489 } 490 /* ------------------------------------------------------------------ */ 491 static int SNESView_EQ_LS(PetscObject obj,Viewer viewer) 492 { 493 SNES snes = (SNES)obj; 494 SNES_LS *ls = (SNES_LS *)snes->data; 495 FILE *fd; 496 char *cstr; 497 int ierr; 498 ViewerType vtype; 499 500 ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr); 501 if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) { 502 ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr); 503 if (ls->LineSearch == SNESNoLineSearch) cstr = "SNESNoLineSearch"; 504 else if (ls->LineSearch == SNESQuadraticLineSearch) cstr = "SNESQuadraticLineSearch"; 505 else if (ls->LineSearch == SNESCubicLineSearch) cstr = "SNESCubicLineSearch"; 506 else cstr = "unknown"; 507 PetscFPrintf(snes->comm,fd," line search variant: %s\n",cstr); 508 PetscFPrintf(snes->comm,fd," alpha=%g, maxstep=%g, steptol=%g\n", 509 ls->alpha,ls->maxstep,ls->steptol); 510 } 511 return 0; 512 } 513 /* ------------------------------------------------------------------ */ 514 static int SNESSetFromOptions_EQ_LS(SNES snes) 515 { 516 SNES_LS *ls = (SNES_LS *)snes->data; 517 char ver[16]; 518 double tmp; 519 int ierr,flg; 520 521 ierr = OptionsGetDouble(snes->prefix,"-snes_line_search_alpa",&tmp, &flg);CHKERRQ(ierr); 522 if (flg) { 523 ls->alpha = tmp; 524 } 525 ierr = OptionsGetDouble(snes->prefix,"-snes_line_search_maxstep",&tmp, &flg);CHKERRQ(ierr); 526 if (flg) { 527 ls->maxstep = tmp; 528 } 529 ierr = OptionsGetDouble(snes->prefix,"-snes_line_search_steptol",&tmp, &flg);CHKERRQ(ierr); 530 if (flg) { 531 ls->steptol = tmp; 532 } 533 ierr = OptionsGetString(snes->prefix,"-snes_line_search",ver,16, &flg); CHKERRQ(ierr); 534 if (flg) { 535 if (!PetscStrcmp(ver,"basic")) { 536 SNESSetLineSearch(snes,SNESNoLineSearch); 537 } 538 else if (!PetscStrcmp(ver,"quadratic")) { 539 SNESSetLineSearch(snes,SNESQuadraticLineSearch); 540 } 541 else if (!PetscStrcmp(ver,"cubic")) { 542 SNESSetLineSearch(snes,SNESCubicLineSearch); 543 } 544 else {SETERRQ(1,"SNESSetFromOptions_EQ_LS:Unknown line search");} 545 } 546 return 0; 547 } 548 /* ------------------------------------------------------------ */ 549 int SNESCreate_EQ_LS(SNES snes ) 550 { 551 SNES_LS *neP; 552 553 if (snes->method_class != SNES_NONLINEAR_EQUATIONS) 554 SETERRQ(1,"SNESCreate_EQ_LS:For SNES_NONLINEAR_EQUATIONS only"); 555 snes->type = SNES_EQ_LS; 556 snes->setup = SNESSetUp_EQ_LS; 557 snes->solve = SNESSolve_EQ_LS; 558 snes->destroy = SNESDestroy_EQ_LS; 559 snes->converged = SNESConverged_EQ_LS; 560 snes->printhelp = SNESPrintHelp_EQ_LS; 561 snes->setfromoptions = SNESSetFromOptions_EQ_LS; 562 snes->view = SNESView_EQ_LS; 563 snes->nwork = 0; 564 565 neP = PetscNew(SNES_LS); CHKPTRQ(neP); 566 PLogObjectMemory(snes,sizeof(SNES_LS)); 567 snes->data = (void *) neP; 568 neP->alpha = 1.e-4; 569 neP->maxstep = 1.e8; 570 neP->steptol = 1.e-12; 571 neP->LineSearch = SNESCubicLineSearch; 572 return 0; 573 } 574 575 576 577 578