1 #include <petsc-private/linesearchimpl.h> /*I "petscsnes.h" I*/ 2 3 PetscBool SNESLineSearchRegisterAllCalled = PETSC_FALSE; 4 PetscFunctionList SNESLineSearchList = PETSC_NULL; 5 6 PetscClassId SNESLINESEARCH_CLASSID; 7 PetscLogEvent SNESLineSearch_Apply; 8 9 #undef __FUNCT__ 10 #define __FUNCT__ "SNESLineSearchCreate" 11 /*@ 12 SNESLineSearchCreate - Creates the line search context. 13 14 Logically Collective on Comm 15 16 Input Parameters: 17 . comm - MPI communicator for the line search (typically from the associated SNES context). 18 19 Output Parameters: 20 . outlinesearch - the new linesearch context 21 22 Level: beginner 23 24 .keywords: LineSearch, create, context 25 26 .seealso: LineSearchDestroy() 27 @*/ 28 29 PetscErrorCode SNESLineSearchCreate(MPI_Comm comm, SNESLineSearch *outlinesearch) 30 { 31 PetscErrorCode ierr; 32 SNESLineSearch linesearch; 33 34 PetscFunctionBegin; 35 PetscValidPointer(outlinesearch,2); 36 *outlinesearch = PETSC_NULL; 37 ierr = PetscHeaderCreate(linesearch,_p_LineSearch,struct _LineSearchOps,SNESLINESEARCH_CLASSID, 0,"SNESLineSearch","Linesearch","SNESLineSearch",comm,SNESLineSearchDestroy,SNESLineSearchView);CHKERRQ(ierr); 38 39 linesearch->ops->precheck = PETSC_NULL; 40 linesearch->ops->postcheck = PETSC_NULL; 41 42 linesearch->vec_sol_new = PETSC_NULL; 43 linesearch->vec_func_new = PETSC_NULL; 44 linesearch->vec_sol = PETSC_NULL; 45 linesearch->vec_func = PETSC_NULL; 46 linesearch->vec_update = PETSC_NULL; 47 48 linesearch->lambda = 1.0; 49 linesearch->fnorm = 1.0; 50 linesearch->ynorm = 1.0; 51 linesearch->xnorm = 1.0; 52 linesearch->success = PETSC_TRUE; 53 linesearch->norms = PETSC_TRUE; 54 linesearch->keeplambda = PETSC_FALSE; 55 linesearch->damping = 1.0; 56 linesearch->maxstep = 1e8; 57 linesearch->steptol = 1e-12; 58 linesearch->rtol = 1e-8; 59 linesearch->atol = 1e-15; 60 linesearch->ltol = 1e-8; 61 linesearch->precheckctx = PETSC_NULL; 62 linesearch->postcheckctx = PETSC_NULL; 63 linesearch->max_its = 1; 64 linesearch->setupcalled = PETSC_FALSE; 65 *outlinesearch = linesearch; 66 PetscFunctionReturn(0); 67 } 68 69 #undef __FUNCT__ 70 #define __FUNCT__ "SNESLineSearchSetUp" 71 /*@ 72 SNESLineSearchSetUp - Prepares the line search for being applied by allocating 73 any required vectors. 74 75 Collective on SNESLineSearch 76 77 Input Parameters: 78 . linesearch - The LineSearch instance. 79 80 Notes: 81 For most cases, this needn't be called outside of SNESLineSearchApply(). 82 The only current case where this is called outside of this is for the VI 83 solvers, which modify the solution and work vectors before the first call 84 of SNESLineSearchApply, requiring the SNESLineSearch work vectors to be 85 allocated upfront. 86 87 Level: advanced 88 89 .keywords: SNESLineSearch, SetUp 90 91 .seealso: SNESLineSearchReset() 92 @*/ 93 94 PetscErrorCode SNESLineSearchSetUp(SNESLineSearch linesearch) 95 { 96 PetscErrorCode ierr; 97 98 PetscFunctionBegin; 99 if (!((PetscObject)linesearch)->type_name) { 100 ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);CHKERRQ(ierr); 101 } 102 if (!linesearch->setupcalled) { 103 if (!linesearch->vec_sol_new) { 104 ierr = VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new);CHKERRQ(ierr); 105 } 106 if (!linesearch->vec_func_new) { 107 ierr = VecDuplicate(linesearch->vec_sol, &linesearch->vec_func_new);CHKERRQ(ierr); 108 } 109 if (linesearch->ops->setup) { 110 ierr = (*linesearch->ops->setup)(linesearch);CHKERRQ(ierr); 111 } 112 linesearch->lambda = linesearch->damping; 113 linesearch->setupcalled = PETSC_TRUE; 114 } 115 PetscFunctionReturn(0); 116 } 117 118 #undef __FUNCT__ 119 #define __FUNCT__ "SNESLineSearchReset" 120 121 /*@ 122 SNESLineSearchReset - Undoes the SetUp and deletes any Vecs or Mats allocated by the line search. 123 124 Collective on SNESLineSearch 125 126 Input Parameters: 127 . linesearch - The LineSearch instance. 128 129 Level: intermediate 130 131 .keywords: SNESLineSearch, Reset 132 133 .seealso: SNESLineSearchSetUp() 134 @*/ 135 136 PetscErrorCode SNESLineSearchReset(SNESLineSearch linesearch) 137 { 138 PetscErrorCode ierr; 139 140 PetscFunctionBegin; 141 if (linesearch->ops->reset) { 142 (*linesearch->ops->reset)(linesearch); 143 } 144 ierr = VecDestroy(&linesearch->vec_sol_new);CHKERRQ(ierr); 145 ierr = VecDestroy(&linesearch->vec_func_new);CHKERRQ(ierr); 146 147 ierr = VecDestroyVecs(linesearch->nwork, &linesearch->work);CHKERRQ(ierr); 148 linesearch->nwork = 0; 149 linesearch->setupcalled = PETSC_FALSE; 150 PetscFunctionReturn(0); 151 } 152 153 /*MC 154 SNESLineSearchPreCheckFunction - functional form passed to check before line search is called 155 156 Synopsis: 157 #include "petscsnes.h" 158 SNESLineSearchPreCheckFunction(SNESLineSearch snes,Vec x,Vec y, PetscBool *changed); 159 160 Input Parameters: 161 + x - solution vector 162 . y - search direction vector 163 - changed - flag to indicate the precheck changed x or y. 164 165 .seealso: SNESLineSearchSetPreCheck(), SNESLineSearchSetPostCheck() 166 M*/ 167 168 #undef __FUNCT__ 169 #define __FUNCT__ "SNESLineSearchSetPreCheck" 170 /*@C 171 SNESLineSearchSetPreCheck - Sets a pre-check function for the line search routine. 172 173 Logically Collective on SNESLineSearch 174 175 Input Parameters: 176 + linesearch - the SNESLineSearch context 177 . SNESLineSearchPreCheckFunction - [optional] function evaluation routine 178 - ctx - [optional] user-defined context for private data for the 179 function evaluation routine (may be PETSC_NULL) 180 181 182 Level: intermediate 183 184 .keywords: set, linesearch, pre-check 185 186 .seealso: SNESLineSearchSetPostCheck() 187 @*/ 188 PetscErrorCode SNESLineSearchSetPreCheck(SNESLineSearch linesearch, PetscErrorCode (*SNESLineSearchPreCheckFunction)(SNESLineSearch,Vec,Vec,PetscBool*,void*),void *ctx) 189 { 190 PetscFunctionBegin; 191 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 192 if (SNESLineSearchPreCheckFunction) linesearch->ops->precheck = SNESLineSearchPreCheckFunction; 193 if (ctx) linesearch->precheckctx = ctx; 194 PetscFunctionReturn(0); 195 } 196 197 #undef __FUNCT__ 198 #define __FUNCT__ "SNESLineSearchGetPreCheck" 199 /*@C 200 SNESLineSearchSetPreCheck - Gets the pre-check function for the line search routine. 201 202 Input Parameters: 203 . linesearch - the SNESLineSearch context 204 205 Output Parameters: 206 + func - [optional] function evaluation routine 207 - ctx - [optional] user-defined context for private data for the 208 function evaluation routine (may be PETSC_NULL) 209 210 Level: intermediate 211 212 .keywords: get, linesearch, pre-check 213 214 .seealso: SNESLineSearchGetPostCheck(), SNESLineSearchSetPreCheck() 215 @*/ 216 PetscErrorCode SNESLineSearchGetPreCheck(SNESLineSearch linesearch, PetscErrorCode (**SNESLineSearchPreCheckFunction)(SNESLineSearch,Vec,Vec,PetscBool*,void*),void **ctx) 217 { 218 PetscFunctionBegin; 219 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 220 if (SNESLineSearchPreCheckFunction) *SNESLineSearchPreCheckFunction = linesearch->ops->precheck; 221 if (ctx) *ctx = linesearch->precheckctx; 222 PetscFunctionReturn(0); 223 } 224 225 /*MC 226 SNESLineSearchPostheckFunction - functional form that is called after line search is complete 227 228 Synopsis: 229 #include "petscsnes.h" 230 SNESLineSearchPostheckFunction(SNESLineSearch linesearch,Vec x,Vec y, Vec w, *changed_y, PetscBool *changed_w); 231 232 Input Parameters: 233 + x - old solution vector 234 . y - search direction vector 235 . w - new solution vector 236 . changed_y - indicates that the line search changed y 237 - changed_w - indicates that the line search changed w 238 239 240 .seealso: SNESLineSearchSetPreCheck(), SNESLineSearchSetPostCheck() 241 M*/ 242 243 #undef __FUNCT__ 244 #define __FUNCT__ "SNESLineSearchSetPostCheck" 245 /*@C 246 SNESLineSearchSetPostCheck - Sets a post-check function for the line search routine. 247 248 Logically Collective on SNESLineSearch 249 250 Input Parameters: 251 + linesearch - the SNESLineSearch context 252 . SNESLineSearchPostCheckFunction - [optional] function evaluation routine 253 - ctx - [optional] user-defined context for private data for the 254 function evaluation routine (may be PETSC_NULL) 255 256 Level: intermediate 257 258 .keywords: set, linesearch, post-check 259 260 .seealso: SNESLineSearchSetPreCheck() 261 @*/ 262 PetscErrorCode SNESLineSearchSetPostCheck(SNESLineSearch linesearch, PetscErrorCode (*SNESLineSearchPostCheckFunction)(SNESLineSearch,Vec,Vec,Vec,PetscBool *,PetscBool *,void*),void *ctx) 263 { 264 PetscFunctionBegin; 265 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 266 if (SNESLineSearchPostCheckFunction) linesearch->ops->postcheck = SNESLineSearchPostCheckFunction; 267 if (ctx) linesearch->postcheckctx = ctx; 268 PetscFunctionReturn(0); 269 } 270 271 #undef __FUNCT__ 272 #define __FUNCT__ "SNESLineSearchGetPostCheck" 273 /*@C 274 SNESLineSearchGetPostCheck - Gets the post-check function for the line search routine. 275 276 Input Parameters: 277 . linesearch - the SNESLineSearch context 278 279 Output Parameters: 280 + SNESLineSearchPostCheckFunction - [optional] function evaluation routine 281 - ctx - [optional] user-defined context for private data for the 282 function evaluation routine (may be PETSC_NULL) 283 284 Level: intermediate 285 286 .keywords: get, linesearch, post-check 287 288 .seealso: SNESLineSearchGetPreCheck(), SNESLineSearchSetPostCheck() 289 @*/ 290 PetscErrorCode SNESLineSearchGetPostCheck(SNESLineSearch linesearch, PetscErrorCode (**SNESLineSearchPostCheckFunction)(SNESLineSearch,Vec,Vec,Vec,PetscBool *,PetscBool *,void*),void **ctx) 291 { 292 PetscFunctionBegin; 293 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 294 if (SNESLineSearchPostCheckFunction) *SNESLineSearchPostCheckFunction = linesearch->ops->postcheck; 295 if (ctx) *ctx = linesearch->postcheckctx; 296 PetscFunctionReturn(0); 297 } 298 299 #undef __FUNCT__ 300 #define __FUNCT__ "SNESLineSearchPreCheck" 301 /*@ 302 SNESLineSearchPreCheck - Prepares the line search for being applied. 303 304 Logically Collective on SNESLineSearch 305 306 Input Parameters: 307 + linesearch - The linesearch instance. 308 . X - The current solution 309 - Y - The step direction 310 311 Output Parameters: 312 . changed - Indicator that the precheck routine has changed anything 313 314 Level: Beginner 315 316 .keywords: SNESLineSearch, Create 317 318 .seealso: SNESLineSearchPostCheck() 319 @*/ 320 PetscErrorCode SNESLineSearchPreCheck(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed) 321 { 322 PetscErrorCode ierr; 323 324 PetscFunctionBegin; 325 *changed = PETSC_FALSE; 326 if (linesearch->ops->precheck) { 327 ierr = (*linesearch->ops->precheck)(linesearch, X, Y, changed, linesearch->precheckctx);CHKERRQ(ierr); 328 PetscValidLogicalCollectiveBool(linesearch,*changed,4); 329 } 330 PetscFunctionReturn(0); 331 } 332 333 #undef __FUNCT__ 334 #define __FUNCT__ "SNESLineSearchPostCheck" 335 /*@ 336 SNESLineSearchPostCheck - Prepares the line search for being applied. 337 338 Logically Collective on SNESLineSearch 339 340 Input Parameters: 341 + linesearch - The linesearch context 342 . X - The last solution 343 . Y - The step direction 344 - W - The updated solution, W = X + lambda*Y for some lambda 345 346 Output Parameters: 347 + changed_Y - Indicator if the direction Y has been changed. 348 - changed_W - Indicator if the new candidate solution W has been changed. 349 350 Level: Intermediate 351 352 .keywords: SNESLineSearch, Create 353 354 .seealso: SNESLineSearchPreCheck() 355 @*/ 356 PetscErrorCode SNESLineSearchPostCheck(SNESLineSearch linesearch,Vec X,Vec Y,Vec W,PetscBool *changed_Y,PetscBool *changed_W) 357 { 358 PetscErrorCode ierr; 359 360 PetscFunctionBegin; 361 *changed_Y = PETSC_FALSE; 362 *changed_W = PETSC_FALSE; 363 if (linesearch->ops->postcheck) { 364 ierr = (*linesearch->ops->postcheck)(linesearch,X,Y,W,changed_Y,changed_W,linesearch->postcheckctx);CHKERRQ(ierr); 365 PetscValidLogicalCollectiveBool(linesearch,*changed_Y,5); 366 PetscValidLogicalCollectiveBool(linesearch,*changed_W,6); 367 } 368 PetscFunctionReturn(0); 369 } 370 371 #undef __FUNCT__ 372 #define __FUNCT__ "SNESLineSearchPreCheckPicard" 373 /*@C 374 SNESLineSearchPreCheckPicard - Implements a correction that is sometimes useful to improve the convergence rate of Picard iteration 375 376 Logically Collective on SNESLineSearch 377 378 Input Arguments: 379 + linesearch - linesearch context 380 . X - base state for this step 381 . Y - initial correction 382 383 Output Arguments: 384 + Y - correction, possibly modified 385 - changed - flag indicating that Y was modified 386 387 Options Database Key: 388 + -snes_linesearch_precheck_picard - activate this routine 389 - -snes_linesearch_precheck_picard_angle - angle 390 391 Level: advanced 392 393 Notes: 394 This function should be passed to SNESLineSearchSetPreCheck() 395 396 The justification for this method involves the linear convergence of a Picard iteration 397 so the Picard linearization should be provided in place of the "Jacobian". This correction 398 is generally not useful when using a Newton linearization. 399 400 Reference: 401 Hindmarsh and Payne (1996) Time step limits for stable solutions of the ice sheet equation, Annals of Glaciology. 402 403 .seealso: SNESLineSearchSetPreCheck() 404 @*/ 405 PetscErrorCode SNESLineSearchPreCheckPicard(SNESLineSearch linesearch,Vec X,Vec Y,PetscBool *changed,void *ctx) 406 { 407 PetscErrorCode ierr; 408 PetscReal angle = *(PetscReal*)linesearch->precheckctx; 409 Vec Ylast; 410 PetscScalar dot; 411 PetscInt iter; 412 PetscReal ynorm,ylastnorm,theta,angle_radians; 413 SNES snes; 414 415 PetscFunctionBegin; 416 ierr = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr); 417 ierr = PetscObjectQuery((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject*)&Ylast);CHKERRQ(ierr); 418 if (!Ylast) { 419 ierr = VecDuplicate(Y,&Ylast);CHKERRQ(ierr); 420 ierr = PetscObjectCompose((PetscObject)snes,"SNESLineSearchPreCheckPicard_Ylast",(PetscObject)Ylast);CHKERRQ(ierr); 421 ierr = PetscObjectDereference((PetscObject)Ylast);CHKERRQ(ierr); 422 } 423 ierr = SNESGetIterationNumber(snes,&iter);CHKERRQ(ierr); 424 if (iter < 2) { 425 ierr = VecCopy(Y,Ylast);CHKERRQ(ierr); 426 *changed = PETSC_FALSE; 427 PetscFunctionReturn(0); 428 } 429 430 ierr = VecDot(Y,Ylast,&dot);CHKERRQ(ierr); 431 ierr = VecNorm(Y,NORM_2,&ynorm);CHKERRQ(ierr); 432 ierr = VecNorm(Ylast,NORM_2,&ylastnorm);CHKERRQ(ierr); 433 /* Compute the angle between the vectors Y and Ylast, clip to keep inside the domain of acos() */ 434 theta = acos((double)PetscClipInterval(PetscAbsScalar(dot) / (ynorm * ylastnorm),-1.0,1.0)); 435 angle_radians = angle * PETSC_PI / 180.; 436 if (PetscAbsReal(theta) < angle_radians || PetscAbsReal(theta - PETSC_PI) < angle_radians) { 437 /* Modify the step Y */ 438 PetscReal alpha,ydiffnorm; 439 ierr = VecAXPY(Ylast,-1.0,Y);CHKERRQ(ierr); 440 ierr = VecNorm(Ylast,NORM_2,&ydiffnorm);CHKERRQ(ierr); 441 alpha = ylastnorm / ydiffnorm; 442 ierr = VecCopy(Y,Ylast);CHKERRQ(ierr); 443 ierr = VecScale(Y,alpha);CHKERRQ(ierr); 444 ierr = PetscInfo3(snes,"Angle %14.12e degrees less than threshold %14.12e, corrected step by alpha=%14.12e\n",(double)(theta*180./PETSC_PI),(double)angle,(double)alpha);CHKERRQ(ierr); 445 } else { 446 ierr = PetscInfo2(snes,"Angle %14.12e degrees exceeds threshold %14.12e, no correction applied\n",(double)(theta*180./PETSC_PI),(double)angle);CHKERRQ(ierr); 447 ierr = VecCopy(Y,Ylast);CHKERRQ(ierr); 448 *changed = PETSC_FALSE; 449 } 450 PetscFunctionReturn(0); 451 } 452 453 #undef __FUNCT__ 454 #define __FUNCT__ "SNESLineSearchApply" 455 /*@ 456 SNESLineSearchApply - Computes the line-search update. 457 458 Collective on SNESLineSearch 459 460 Input Parameters: 461 + linesearch - The linesearch context 462 . X - The current solution 463 . F - The current function 464 . fnorm - The current norm 465 - Y - The search direction 466 467 Output Parameters: 468 + X - The new solution 469 . F - The new function 470 - fnorm - The new function norm 471 472 Options Database Keys: 473 + -snes_linesearch_type - basic, bt, l2, cp, shell 474 . -snes_linesearch_monitor - Print progress of line searches 475 . -snes_linesearch_damping - The linesearch damping parameter 476 . -snes_linesearch_norms - Turn on/off the linesearch norms 477 . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess 478 - -snes_linesearch_max_it - The number of iterations for iterative line searches 479 480 Notes: 481 This is typically called from within a SNESSolve() implementation in order to 482 help with convergence of the nonlinear method. Various SNES types use line searches 483 in different ways, but the overarching theme is that a line search is used to determine 484 an optimal damping parameter of a step at each iteration of the method. Each 485 application of the line search may invoke SNESComputeFunction several times, and 486 therefore may be fairly expensive. 487 488 Level: Intermediate 489 490 .keywords: SNESLineSearch, Create 491 492 .seealso: SNESLineSearchCreate(), SNESLineSearchPreCheck(), SNESLineSearchPostCheck(), SNESSolve(), SNESComputeFunction() 493 @*/ 494 PetscErrorCode SNESLineSearchApply(SNESLineSearch linesearch, Vec X, Vec F, PetscReal * fnorm, Vec Y) 495 { 496 PetscErrorCode ierr; 497 498 PetscFunctionBegin; 499 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 500 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 501 PetscValidHeaderSpecific(F,VEC_CLASSID,3); 502 PetscValidHeaderSpecific(Y,VEC_CLASSID,4); 503 504 linesearch->success = PETSC_TRUE; 505 506 linesearch->vec_sol = X; 507 linesearch->vec_update = Y; 508 linesearch->vec_func = F; 509 510 ierr = SNESLineSearchSetUp(linesearch);CHKERRQ(ierr); 511 512 if (!linesearch->keeplambda) 513 linesearch->lambda = linesearch->damping; /* set the initial guess to lambda */ 514 515 if (fnorm) { 516 linesearch->fnorm = *fnorm; 517 } else { 518 ierr = VecNorm(F, NORM_2, &linesearch->fnorm);CHKERRQ(ierr); 519 } 520 521 ierr = PetscLogEventBegin(SNESLineSearch_Apply,linesearch,X,F,Y);CHKERRQ(ierr); 522 523 ierr = (*linesearch->ops->apply)(linesearch);CHKERRQ(ierr); 524 525 ierr = PetscLogEventEnd(SNESLineSearch_Apply,linesearch,X,F,Y);CHKERRQ(ierr); 526 527 if (fnorm) 528 *fnorm = linesearch->fnorm; 529 PetscFunctionReturn(0); 530 } 531 532 #undef __FUNCT__ 533 #define __FUNCT__ "SNESLineSearchDestroy" 534 /*@ 535 SNESLineSearchDestroy - Destroys the line search instance. 536 537 Collective on SNESLineSearch 538 539 Input Parameters: 540 . linesearch - The linesearch context 541 542 Level: Intermediate 543 544 .keywords: SNESLineSearch, Destroy 545 546 .seealso: SNESLineSearchCreate(), SNESLineSearchReset(), SNESDestroy() 547 @*/ 548 PetscErrorCode SNESLineSearchDestroy(SNESLineSearch * linesearch) 549 { 550 PetscErrorCode ierr; 551 552 PetscFunctionBegin; 553 if (!*linesearch) PetscFunctionReturn(0); 554 PetscValidHeaderSpecific((*linesearch),SNESLINESEARCH_CLASSID,1); 555 if (--((PetscObject)(*linesearch))->refct > 0) {*linesearch = 0; PetscFunctionReturn(0);} 556 ierr = PetscObjectDepublish((*linesearch));CHKERRQ(ierr); 557 ierr = SNESLineSearchReset(*linesearch);CHKERRQ(ierr); 558 if ((*linesearch)->ops->destroy) { 559 (*linesearch)->ops->destroy(*linesearch); 560 } 561 ierr = PetscViewerDestroy(&(*linesearch)->monitor);CHKERRQ(ierr); 562 ierr = PetscHeaderDestroy(linesearch);CHKERRQ(ierr); 563 PetscFunctionReturn(0); 564 } 565 566 #undef __FUNCT__ 567 #define __FUNCT__ "SNESLineSearchSetMonitor" 568 /*@ 569 SNESLineSearchSetMonitor - Turns on/off printing useful information and debugging output about the line search. 570 571 Input Parameters: 572 + snes - nonlinear context obtained from SNESCreate() 573 - flg - PETSC_TRUE to monitor the line search 574 575 Logically Collective on SNES 576 577 Options Database: 578 . -snes_linesearch_monitor - enables the monitor 579 580 Level: intermediate 581 582 583 .seealso: SNESLineSearchGetMonitor(), PetscViewer 584 @*/ 585 PetscErrorCode SNESLineSearchSetMonitor(SNESLineSearch linesearch, PetscBool flg) 586 { 587 PetscErrorCode ierr; 588 589 PetscFunctionBegin; 590 if (flg && !linesearch->monitor) { 591 ierr = PetscViewerASCIIOpen(((PetscObject)linesearch)->comm,"stdout",&linesearch->monitor);CHKERRQ(ierr); 592 } else if (!flg && linesearch->monitor) { 593 ierr = PetscViewerDestroy(&linesearch->monitor);CHKERRQ(ierr); 594 } 595 PetscFunctionReturn(0); 596 } 597 598 #undef __FUNCT__ 599 #define __FUNCT__ "SNESLineSearchGetMonitor" 600 /*@ 601 SNESLineSearchGetMonitor - Gets the PetscViewer instance for the line search monitor. 602 603 Input Parameters: 604 . linesearch - linesearch context 605 606 Input Parameters: 607 . monitor - monitor context 608 609 Logically Collective on SNES 610 611 612 Options Database Keys: 613 . -snes_linesearch_monitor - enables the monitor 614 615 Level: intermediate 616 617 618 .seealso: SNESLineSearchSetMonitor(), PetscViewer 619 @*/ 620 PetscErrorCode SNESLineSearchGetMonitor(SNESLineSearch linesearch, PetscViewer *monitor) 621 { 622 PetscFunctionBegin; 623 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 624 if (monitor) { 625 PetscValidPointer(monitor, 2); 626 *monitor = linesearch->monitor; 627 } 628 PetscFunctionReturn(0); 629 } 630 631 #undef __FUNCT__ 632 #define __FUNCT__ "SNESLineSearchSetFromOptions" 633 /*@ 634 SNESLineSearchSetFromOptions - Sets options for the line search 635 636 Input Parameters: 637 . linesearch - linesearch context 638 639 Options Database Keys: 640 + -snes_linesearch_type <type> - basic, bt, l2, cp, shell 641 . -snes_linesearch_order <order> - 1, 2, 3. Most types only support certain orders (bt supports 2 or 3) 642 . -snes_linesearch_norms - Turn on/off the linesearch norms for the basic linesearch type 643 . -snes_linesearch_minlambda - The minimum step length 644 . -snes_linesearch_maxstep - The maximum step size 645 . -snes_linesearch_rtol - Relative tolerance for iterative line searches 646 . -snes_linesearch_atol - Absolute tolerance for iterative line searches 647 . -snes_linesearch_ltol - Change in lambda tolerance for iterative line searches 648 . -snes_linesearch_max_it - The number of iterations for iterative line searches 649 . -snes_linesearch_monitor - Print progress of line searches 650 . -snes_linesearch_damping - The linesearch damping parameter 651 . -snes_linesearch_keeplambda - Keep the previous search length as the initial guess. 652 . -snes_linesearch_precheck_picard - Use precheck that speeds up convergence of picard method 653 - -snes_linesearch_precheck_picard_angle - Angle used in picard precheck method 654 655 Logically Collective on SNESLineSearch 656 657 Level: intermediate 658 659 .seealso: SNESLineSearchCreate(), SNESLineSearchSetOrder(), SNESLineSearchSetType(), SNESLineSearchSetTolerances(), SNESLineSearchSetDamping(), SNESLineSearchPreCheckPicard() 660 @*/ 661 PetscErrorCode SNESLineSearchSetFromOptions(SNESLineSearch linesearch) 662 { 663 PetscErrorCode ierr; 664 const char *deft = SNESLINESEARCHBASIC; 665 char type[256]; 666 PetscBool flg, set; 667 668 PetscFunctionBegin; 669 if (!SNESLineSearchRegisterAllCalled) {ierr = SNESLineSearchRegisterAll(PETSC_NULL);CHKERRQ(ierr);} 670 671 ierr = PetscObjectOptionsBegin((PetscObject)linesearch);CHKERRQ(ierr); 672 if (((PetscObject)linesearch)->type_name) { 673 deft = ((PetscObject)linesearch)->type_name; 674 } 675 ierr = PetscOptionsList("-snes_linesearch_type","Linesearch type","SNESLineSearchSetType",SNESLineSearchList,deft,type,256,&flg);CHKERRQ(ierr); 676 if (flg) { 677 ierr = SNESLineSearchSetType(linesearch,type);CHKERRQ(ierr); 678 } else if (!((PetscObject)linesearch)->type_name) { 679 ierr = SNESLineSearchSetType(linesearch,deft);CHKERRQ(ierr); 680 } 681 682 ierr = PetscOptionsBool("-snes_linesearch_monitor","Print progress of line searches","SNESSNESLineSearchSetMonitor", 683 linesearch->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 684 if (set) {ierr = SNESLineSearchSetMonitor(linesearch,flg);CHKERRQ(ierr);} 685 686 /* tolerances */ 687 ierr = PetscOptionsReal("-snes_linesearch_minlambda","Minimum step length","SNESLineSearchSetTolerances",linesearch->steptol,&linesearch->steptol,0);CHKERRQ(ierr); 688 ierr = PetscOptionsReal("-snes_linesearch_maxstep","Maximum step size","SNESLineSearchSetTolerances",linesearch->maxstep,&linesearch->maxstep,0);CHKERRQ(ierr); 689 ierr = PetscOptionsReal("-snes_linesearch_rtol","Relative tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->rtol,&linesearch->rtol,0);CHKERRQ(ierr); 690 ierr = PetscOptionsReal("-snes_linesearch_atol","Absolute tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->atol,&linesearch->atol,0);CHKERRQ(ierr); 691 ierr = PetscOptionsReal("-snes_linesearch_ltol","Change in lambda tolerance for iterative line search","SNESLineSearchSetTolerances",linesearch->ltol,&linesearch->ltol,0);CHKERRQ(ierr); 692 ierr = PetscOptionsInt("-snes_linesearch_max_it","Maximum iterations for iterative line searches","SNESLineSearchSetTolerances",linesearch->max_its,&linesearch->max_its,0);CHKERRQ(ierr); 693 694 /* damping parameters */ 695 ierr = PetscOptionsReal("-snes_linesearch_damping","Line search damping and initial step guess","SNESLineSearchSetDamping",linesearch->damping,&linesearch->damping,0);CHKERRQ(ierr); 696 697 ierr = PetscOptionsBool("-snes_linesearch_keeplambda","Use previous lambda as damping","SNESLineSearchSetKeepLambda",linesearch->keeplambda,&linesearch->keeplambda,0);CHKERRQ(ierr); 698 699 /* precheck */ 700 ierr = PetscOptionsBool("-snes_linesearch_precheck_picard","Use a correction that sometimes improves convergence of Picard iteration","SNESLineSearchPreCheckPicard",flg,&flg,&set);CHKERRQ(ierr); 701 if (set) { 702 if (flg) { 703 linesearch->precheck_picard_angle = 10.; /* correction only active if angle is less than 10 degrees */ 704 ierr = PetscOptionsReal("-snes_linesearch_precheck_picard_angle","Maximum angle at which to activate the correction", 705 "none",linesearch->precheck_picard_angle,&linesearch->precheck_picard_angle,PETSC_NULL);CHKERRQ(ierr); 706 ierr = SNESLineSearchSetPreCheck(linesearch,SNESLineSearchPreCheckPicard,&linesearch->precheck_picard_angle);CHKERRQ(ierr); 707 } else { 708 ierr = SNESLineSearchSetPreCheck(linesearch,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 709 } 710 } 711 ierr = PetscOptionsInt("-snes_linesearch_order","Order of approximation used in the line search","SNESLineSearchSetOrder",linesearch->order,&linesearch->order,0);CHKERRQ(ierr); 712 ierr = PetscOptionsBool("-snes_linesearch_norms","Compute final norms in line search","SNESLineSearchSetComputeNorms",linesearch->norms,&linesearch->norms,0);CHKERRQ(ierr); 713 714 if (linesearch->ops->setfromoptions) { 715 (*linesearch->ops->setfromoptions)(linesearch);CHKERRQ(ierr); 716 } 717 718 ierr = PetscObjectProcessOptionsHandlers((PetscObject)linesearch);CHKERRQ(ierr); 719 ierr = PetscOptionsEnd();CHKERRQ(ierr); 720 PetscFunctionReturn(0); 721 } 722 723 #undef __FUNCT__ 724 #define __FUNCT__ "SNESLineSearchView" 725 /*@ 726 SNESLineSearchView - Prints useful information about the line search not 727 related to an individual call. 728 729 Input Parameters: 730 . linesearch - linesearch context 731 732 Logically Collective on SNESLineSearch 733 734 Level: intermediate 735 736 .seealso: SNESLineSearchCreate() 737 @*/ 738 PetscErrorCode SNESLineSearchView(SNESLineSearch linesearch, PetscViewer viewer) 739 { 740 PetscErrorCode ierr; 741 PetscBool iascii; 742 743 PetscFunctionBegin; 744 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 745 if (!viewer) { 746 ierr = PetscViewerASCIIGetStdout(((PetscObject)linesearch)->comm,&viewer);CHKERRQ(ierr); 747 } 748 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 749 PetscCheckSameComm(linesearch,1,viewer,2); 750 751 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 752 if (iascii) { 753 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)linesearch,viewer,"SNESLineSearch Object");CHKERRQ(ierr); 754 if (linesearch->ops->view) { 755 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 756 ierr = (*linesearch->ops->view)(linesearch,viewer);CHKERRQ(ierr); 757 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 758 } 759 ierr = PetscViewerASCIIPrintf(viewer," maxstep=%e, minlambda=%e\n", (double)linesearch->maxstep,(double)linesearch->steptol);CHKERRQ(ierr); 760 ierr = PetscViewerASCIIPrintf(viewer," tolerances: relative=%e, absolute=%e, lambda=%e\n", (double)linesearch->rtol,(double)linesearch->atol,(double)linesearch->ltol);CHKERRQ(ierr); 761 ierr = PetscViewerASCIIPrintf(viewer," maximum iterations=%D\n", linesearch->max_its);CHKERRQ(ierr); 762 if (linesearch->ops->precheck) { 763 if (linesearch->ops->precheck == SNESLineSearchPreCheckPicard) { 764 ierr = PetscViewerASCIIPrintf(viewer," using precheck step to speed up Picard convergence\n", linesearch->max_its);CHKERRQ(ierr); 765 } else { 766 ierr = PetscViewerASCIIPrintf(viewer," using user-defined precheck step\n", linesearch->max_its);CHKERRQ(ierr); 767 } 768 } 769 if (linesearch->ops->postcheck) { 770 ierr = PetscViewerASCIIPrintf(viewer," using user-defined postcheck step\n", linesearch->max_its);CHKERRQ(ierr); 771 } 772 } 773 PetscFunctionReturn(0); 774 } 775 776 #undef __FUNCT__ 777 #define __FUNCT__ "SNESLineSearchSetType" 778 /*@C 779 SNESLineSearchSetType - Sets the linesearch type 780 781 Input Parameters: 782 + linesearch - linesearch context 783 - type - The type of line search to be used 784 785 Available Types: 786 + basic - Simple damping line search. 787 . bt - Backtracking line search over the L2 norm of the function 788 . l2 - Secant line search over the L2 norm of the function 789 . cp - Critical point secant line search assuming F(x) = grad G(x) for some unknown G(x) 790 - shell - User provided SNESLineSearch implementation 791 792 Logically Collective on SNESLineSearch 793 794 Level: intermediate 795 796 797 .seealso: SNESLineSearchCreate() 798 @*/ 799 PetscErrorCode SNESLineSearchSetType(SNESLineSearch linesearch, SNESLineSearchType type) 800 { 801 PetscErrorCode ierr,(*r)(SNESLineSearch); 802 PetscBool match; 803 804 PetscFunctionBegin; 805 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 806 PetscValidCharPointer(type,2); 807 808 ierr = PetscObjectTypeCompare((PetscObject)linesearch,type,&match);CHKERRQ(ierr); 809 if (match) PetscFunctionReturn(0); 810 811 ierr = PetscFunctionListFind(((PetscObject)linesearch)->comm,SNESLineSearchList,type,PETSC_TRUE,(void (**)(void)) &r);CHKERRQ(ierr); 812 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested Line Search type %s",type); 813 /* Destroy the previous private linesearch context */ 814 if (linesearch->ops->destroy) { 815 ierr = (*(linesearch)->ops->destroy)(linesearch);CHKERRQ(ierr); 816 linesearch->ops->destroy = PETSC_NULL; 817 } 818 /* Reinitialize function pointers in SNESLineSearchOps structure */ 819 linesearch->ops->apply = 0; 820 linesearch->ops->view = 0; 821 linesearch->ops->setfromoptions = 0; 822 linesearch->ops->destroy = 0; 823 824 ierr = PetscObjectChangeTypeName((PetscObject)linesearch,type);CHKERRQ(ierr); 825 ierr = (*r)(linesearch);CHKERRQ(ierr); 826 #if defined(PETSC_HAVE_AMS) 827 if (PetscAMSPublishAll) { 828 ierr = PetscObjectAMSPublish((PetscObject)linesearch);CHKERRQ(ierr); 829 } 830 #endif 831 PetscFunctionReturn(0); 832 } 833 834 #undef __FUNCT__ 835 #define __FUNCT__ "SNESLineSearchSetSNES" 836 /*@ 837 SNESLineSearchSetSNES - Sets the SNES for the linesearch for function evaluation. 838 839 Input Parameters: 840 + linesearch - linesearch context 841 - snes - The snes instance 842 843 Level: developer 844 845 Notes: 846 This happens automatically when the line search is gotten/created with 847 SNESGetSNESLineSearch(). This routine is therefore mainly called within SNES 848 implementations. 849 850 Level: developer 851 852 .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES 853 @*/ 854 PetscErrorCode SNESLineSearchSetSNES(SNESLineSearch linesearch, SNES snes) 855 { 856 PetscFunctionBegin; 857 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 858 PetscValidHeaderSpecific(snes,SNES_CLASSID,2); 859 linesearch->snes = snes; 860 PetscFunctionReturn(0); 861 } 862 863 #undef __FUNCT__ 864 #define __FUNCT__ "SNESLineSearchGetSNES" 865 /*@ 866 SNESLineSearchGetSNES - Gets the SNES instance associated with the line search. 867 Having an associated SNES is necessary because most line search implementations must be able to 868 evaluate the function using SNESComputeFunction() for the associated SNES. This routine 869 is used in the line search implementations when one must get this associated SNES instance. 870 871 Input Parameters: 872 . linesearch - linesearch context 873 874 Output Parameters: 875 . snes - The snes instance 876 877 Level: developer 878 879 .seealso: SNESLineSearchGetSNES(), SNESLineSearchSetVecs(), SNES 880 @*/ 881 PetscErrorCode SNESLineSearchGetSNES(SNESLineSearch linesearch, SNES *snes) 882 { 883 PetscFunctionBegin; 884 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 885 PetscValidPointer(snes, 2); 886 *snes = linesearch->snes; 887 PetscFunctionReturn(0); 888 } 889 890 #undef __FUNCT__ 891 #define __FUNCT__ "SNESLineSearchGetLambda" 892 /*@ 893 SNESLineSearchGetLambda - Gets the last linesearch steplength discovered. 894 895 Input Parameters: 896 . linesearch - linesearch context 897 898 Output Parameters: 899 . lambda - The last steplength computed during SNESLineSearchApply() 900 901 Level: advanced 902 903 Notes: 904 This is useful in methods where the solver is ill-scaled and 905 requires some adaptive notion of the difference in scale between the 906 solution and the function. For instance, SNESQN may be scaled by the 907 line search lambda using the argument -snes_qn_scaling ls. 908 909 910 .seealso: SNESLineSearchSetLambda(), SNESLineSearchGetDamping(), SNESLineSearchApply() 911 @*/ 912 PetscErrorCode SNESLineSearchGetLambda(SNESLineSearch linesearch,PetscReal *lambda) 913 { 914 PetscFunctionBegin; 915 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 916 PetscValidPointer(lambda, 2); 917 *lambda = linesearch->lambda; 918 PetscFunctionReturn(0); 919 } 920 921 #undef __FUNCT__ 922 #define __FUNCT__ "SNESLineSearchSetLambda" 923 /*@ 924 SNESLineSearchSetLambda - Sets the linesearch steplength. 925 926 Input Parameters: 927 + linesearch - linesearch context 928 - lambda - The last steplength. 929 930 Notes: 931 This routine is typically used within implementations of SNESLineSearchApply 932 to set the final steplength. This routine (and SNESLineSearchGetLambda()) were 933 added in order to facilitate Quasi-Newton methods that use the previous steplength 934 as an inner scaling parameter. 935 936 Level: advanced 937 938 .seealso: SNESLineSearchGetLambda() 939 @*/ 940 PetscErrorCode SNESLineSearchSetLambda(SNESLineSearch linesearch, PetscReal lambda) 941 { 942 PetscFunctionBegin; 943 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 944 linesearch->lambda = lambda; 945 PetscFunctionReturn(0); 946 } 947 948 #undef __FUNCT__ 949 #define __FUNCT__ "SNESLineSearchGetTolerances" 950 /*@ 951 SNESLineSearchGetTolerances - Gets the tolerances for the linesearch. These include 952 tolerances for the relative and absolute change in the function norm, the change 953 in lambda for iterative line searches, the minimum steplength, the maximum steplength, 954 and the maximum number of iterations the line search procedure may take. 955 956 Input Parameters: 957 . linesearch - linesearch context 958 959 Output Parameters: 960 + steptol - The minimum steplength 961 . maxstep - The maximum steplength 962 . rtol - The relative tolerance for iterative line searches 963 . atol - The absolute tolerance for iterative line searches 964 . ltol - The change in lambda tolerance for iterative line searches 965 - max_it - The maximum number of iterations of the line search 966 967 Level: intermediate 968 969 Notes: 970 Different line searches may implement these parameters slightly differently as 971 the type requires. 972 973 .seealso: SNESLineSearchSetTolerances() 974 @*/ 975 PetscErrorCode SNESLineSearchGetTolerances(SNESLineSearch linesearch,PetscReal *steptol,PetscReal *maxstep, PetscReal *rtol, PetscReal *atol, PetscReal *ltol, PetscInt *max_its) 976 { 977 PetscFunctionBegin; 978 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 979 if (steptol) { 980 PetscValidPointer(steptol, 2); 981 *steptol = linesearch->steptol; 982 } 983 if (maxstep) { 984 PetscValidPointer(maxstep, 3); 985 *maxstep = linesearch->maxstep; 986 } 987 if (rtol) { 988 PetscValidPointer(rtol, 4); 989 *rtol = linesearch->rtol; 990 } 991 if (atol) { 992 PetscValidPointer(atol, 5); 993 *atol = linesearch->atol; 994 } 995 if (ltol) { 996 PetscValidPointer(ltol, 6); 997 *ltol = linesearch->ltol; 998 } 999 if (max_its) { 1000 PetscValidPointer(max_its, 7); 1001 *max_its = linesearch->max_its; 1002 } 1003 PetscFunctionReturn(0); 1004 } 1005 1006 #undef __FUNCT__ 1007 #define __FUNCT__ "SNESLineSearchSetTolerances" 1008 /*@ 1009 SNESLineSearchSetTolerances - Gets the tolerances for the linesearch. These include 1010 tolerances for the relative and absolute change in the function norm, the change 1011 in lambda for iterative line searches, the minimum steplength, the maximum steplength, 1012 and the maximum number of iterations the line search procedure may take. 1013 1014 Input Parameters: 1015 + linesearch - linesearch context 1016 . steptol - The minimum steplength 1017 . maxstep - The maximum steplength 1018 . rtol - The relative tolerance for iterative line searches 1019 . atol - The absolute tolerance for iterative line searches 1020 . ltol - The change in lambda tolerance for iterative line searches 1021 - max_it - The maximum number of iterations of the line search 1022 1023 Notes: 1024 The user may choose to not set any of the tolerances using PETSC_DEFAULT in 1025 place of an argument. 1026 1027 Level: intermediate 1028 1029 .seealso: SNESLineSearchGetTolerances() 1030 @*/ 1031 PetscErrorCode SNESLineSearchSetTolerances(SNESLineSearch linesearch,PetscReal steptol,PetscReal maxstep, PetscReal rtol, PetscReal atol, PetscReal ltol, PetscInt max_its) 1032 { 1033 PetscFunctionBegin; 1034 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1035 PetscValidLogicalCollectiveReal(linesearch,steptol,2); 1036 PetscValidLogicalCollectiveReal(linesearch,maxstep,3); 1037 PetscValidLogicalCollectiveReal(linesearch,rtol,4); 1038 PetscValidLogicalCollectiveReal(linesearch,atol,5); 1039 PetscValidLogicalCollectiveReal(linesearch,ltol,6); 1040 PetscValidLogicalCollectiveInt(linesearch,max_its,7); 1041 1042 if (steptol!= PETSC_DEFAULT) { 1043 if (steptol < 0.0) SETERRQ1(((PetscObject)linesearch)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Minimum step length %14.12e must be non-negative",(double)steptol); 1044 linesearch->steptol = steptol; 1045 } 1046 1047 if (maxstep!= PETSC_DEFAULT) { 1048 if (maxstep < 0.0) SETERRQ1(((PetscObject)linesearch)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Maximum step length %14.12e must be non-negative",(double)maxstep); 1049 linesearch->maxstep = maxstep; 1050 } 1051 1052 if (rtol != PETSC_DEFAULT) { 1053 if (rtol < 0.0 || 1.0 <= rtol) SETERRQ1(((PetscObject)linesearch)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Relative tolerance %14.12e must be non-negative and less than 1.0",(double)rtol); 1054 linesearch->rtol = rtol; 1055 } 1056 1057 if (atol != PETSC_DEFAULT) { 1058 if (atol < 0.0) SETERRQ1(((PetscObject)linesearch)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %14.12e must be non-negative",(double)atol); 1059 linesearch->atol = atol; 1060 } 1061 1062 if (ltol != PETSC_DEFAULT) { 1063 if (ltol < 0.0) SETERRQ1(((PetscObject)linesearch)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Labmda tolerance %14.12e must be non-negative",(double)ltol); 1064 linesearch->ltol = ltol; 1065 } 1066 1067 if (max_its != PETSC_DEFAULT) { 1068 if (max_its < 0) SETERRQ1(((PetscObject)linesearch)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of iterations %D must be non-negative",max_its); 1069 linesearch->max_its = max_its; 1070 } 1071 1072 PetscFunctionReturn(0); 1073 } 1074 1075 #undef __FUNCT__ 1076 #define __FUNCT__ "SNESLineSearchGetDamping" 1077 /*@ 1078 SNESLineSearchGetDamping - Gets the line search damping parameter. 1079 1080 Input Parameters: 1081 . linesearch - linesearch context 1082 1083 Output Parameters: 1084 . damping - The damping parameter 1085 1086 Level: advanced 1087 1088 .seealso: SNESLineSearchGetStepTolerance(), SNESQN 1089 @*/ 1090 1091 PetscErrorCode SNESLineSearchGetDamping(SNESLineSearch linesearch,PetscReal *damping) 1092 { 1093 PetscFunctionBegin; 1094 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1095 PetscValidPointer(damping, 2); 1096 *damping = linesearch->damping; 1097 PetscFunctionReturn(0); 1098 } 1099 1100 #undef __FUNCT__ 1101 #define __FUNCT__ "SNESLineSearchSetDamping" 1102 /*@ 1103 SNESLineSearchSetDamping - Sets the line search damping paramter. 1104 1105 Input Parameters: 1106 . linesearch - linesearch context 1107 . damping - The damping parameter 1108 1109 Level: intermediate 1110 1111 Notes: 1112 The basic line search merely takes the update step scaled by the damping parameter. 1113 The use of the damping parameter in the l2 and cp line searches is much more subtle; 1114 it is used as a starting point in calculating the secant step. However, the eventual 1115 step may be of greater length than the damping parameter. In the bt line search it is 1116 used as the maximum possible step length, as the bt line search only backtracks. 1117 1118 .seealso: SNESLineSearchGetDamping() 1119 @*/ 1120 PetscErrorCode SNESLineSearchSetDamping(SNESLineSearch linesearch,PetscReal damping) 1121 { 1122 PetscFunctionBegin; 1123 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1124 linesearch->damping = damping; 1125 PetscFunctionReturn(0); 1126 } 1127 1128 #undef __FUNCT__ 1129 #define __FUNCT__ "SNESLineSearchGetOrder" 1130 /*@ 1131 SNESLineSearchGetOrder - Gets the line search approximation order. 1132 1133 Input Parameters: 1134 . linesearch - linesearch context 1135 1136 Output Parameters: 1137 . order - The order 1138 1139 Possible Values for order: 1140 + 1 or SNES_LINESEARCH_ORDER_LINEAR - linear order 1141 . 2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order 1142 - 3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order 1143 1144 Level: intermediate 1145 1146 .seealso: SNESLineSearchSetOrder() 1147 @*/ 1148 1149 PetscErrorCode SNESLineSearchGetOrder(SNESLineSearch linesearch,PetscInt *order) 1150 { 1151 PetscFunctionBegin; 1152 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1153 PetscValidPointer(order, 2); 1154 *order = linesearch->order; 1155 PetscFunctionReturn(0); 1156 } 1157 1158 #undef __FUNCT__ 1159 #define __FUNCT__ "SNESLineSearchSetOrder" 1160 /*@ 1161 SNESLineSearchSetOrder - Sets the line search damping paramter. 1162 1163 Input Parameters: 1164 . linesearch - linesearch context 1165 . order - The damping parameter 1166 1167 Level: intermediate 1168 1169 Possible Values for order: 1170 + 1 or SNES_LINESEARCH_ORDER_LINEAR - linear order 1171 . 2 or SNES_LINESEARCH_ORDER_QUADRATIC - quadratic order 1172 - 3 or SNES_LINESEARCH_ORDER_CUBIC - cubic order 1173 1174 Notes: 1175 Variable orders are supported by the following line searches: 1176 + bt - cubic and quadratic 1177 - cp - linear and quadratic 1178 1179 .seealso: SNESLineSearchGetOrder() 1180 @*/ 1181 PetscErrorCode SNESLineSearchSetOrder(SNESLineSearch linesearch,PetscInt order) 1182 { 1183 PetscFunctionBegin; 1184 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1185 linesearch->order = order; 1186 PetscFunctionReturn(0); 1187 } 1188 1189 #undef __FUNCT__ 1190 #define __FUNCT__ "SNESLineSearchGetNorms" 1191 /*@ 1192 SNESLineSearchGetNorms - Gets the norms for for X, Y, and F. 1193 1194 Input Parameters: 1195 . linesearch - linesearch context 1196 1197 Output Parameters: 1198 + xnorm - The norm of the current solution 1199 . fnorm - The norm of the current function 1200 - ynorm - The norm of the current update 1201 1202 Notes: 1203 This function is mainly called from SNES implementations. 1204 1205 Level: developer 1206 1207 .seealso: SNESLineSearchSetNorms() SNESLineSearchGetVecs() 1208 @*/ 1209 PetscErrorCode SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal * xnorm, PetscReal * fnorm, PetscReal * ynorm) 1210 { 1211 PetscFunctionBegin; 1212 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1213 if (xnorm) { 1214 *xnorm = linesearch->xnorm; 1215 } 1216 if (fnorm) { 1217 *fnorm = linesearch->fnorm; 1218 } 1219 if (ynorm) { 1220 *ynorm = linesearch->ynorm; 1221 } 1222 PetscFunctionReturn(0); 1223 } 1224 1225 #undef __FUNCT__ 1226 #define __FUNCT__ "SNESLineSearchSetNorms" 1227 /*@ 1228 SNESLineSearchSetNorms - Gets the computed norms for for X, Y, and F. 1229 1230 Input Parameters: 1231 + linesearch - linesearch context 1232 . xnorm - The norm of the current solution 1233 . fnorm - The norm of the current function 1234 - ynorm - The norm of the current update 1235 1236 Level: advanced 1237 1238 .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs() 1239 @*/ 1240 PetscErrorCode SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm) 1241 { 1242 PetscFunctionBegin; 1243 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1244 linesearch->xnorm = xnorm; 1245 linesearch->fnorm = fnorm; 1246 linesearch->ynorm = ynorm; 1247 PetscFunctionReturn(0); 1248 } 1249 1250 #undef __FUNCT__ 1251 #define __FUNCT__ "SNESLineSearchComputeNorms" 1252 /*@ 1253 SNESLineSearchComputeNorms - Computes the norms of X, F, and Y. 1254 1255 Input Parameters: 1256 . linesearch - linesearch context 1257 1258 Options Database Keys: 1259 . -snes_linesearch_norms - turn norm computation on or off 1260 1261 Level: intermediate 1262 1263 .seealso: SNESLineSearchGetNorms, SNESLineSearchSetNorms(), SNESLineSearchSetComputeNorms() 1264 @*/ 1265 PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch) 1266 { 1267 PetscErrorCode ierr; 1268 SNES snes; 1269 1270 PetscFunctionBegin; 1271 if (linesearch->norms) { 1272 if (linesearch->ops->vinorm) { 1273 ierr = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr); 1274 ierr = VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm);CHKERRQ(ierr); 1275 ierr = VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm);CHKERRQ(ierr); 1276 ierr = (*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm);CHKERRQ(ierr); 1277 } else { 1278 ierr = VecNormBegin(linesearch->vec_func, NORM_2, &linesearch->fnorm);CHKERRQ(ierr); 1279 ierr = VecNormBegin(linesearch->vec_sol, NORM_2, &linesearch->xnorm);CHKERRQ(ierr); 1280 ierr = VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm);CHKERRQ(ierr); 1281 ierr = VecNormEnd(linesearch->vec_func, NORM_2, &linesearch->fnorm);CHKERRQ(ierr); 1282 ierr = VecNormEnd(linesearch->vec_sol, NORM_2, &linesearch->xnorm);CHKERRQ(ierr); 1283 ierr = VecNormEnd(linesearch->vec_update, NORM_2, &linesearch->ynorm);CHKERRQ(ierr); 1284 } 1285 } 1286 PetscFunctionReturn(0); 1287 } 1288 1289 #undef __FUNCT__ 1290 #define __FUNCT__ "SNESLineSearchSetComputeNorms" 1291 /*@ 1292 SNESLineSearchSetComputeNorms - Turns on or off the computation of final norms in the line search. 1293 1294 Input Parameters: 1295 + linesearch - linesearch context 1296 - flg - indicates whether or not to compute norms 1297 1298 Options Database Keys: 1299 . -snes_linesearch_norms - turn norm computation on or off 1300 1301 Notes: 1302 This is most relevant to the SNESLINESEARCHBASIC line search type. 1303 1304 Level: intermediate 1305 1306 .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetNorms(), SNESLineSearchComputeNorms(), SNESLINESEARCHBASIC 1307 @*/ 1308 PetscErrorCode SNESLineSearchSetComputeNorms(SNESLineSearch linesearch, PetscBool flg) 1309 { 1310 PetscFunctionBegin; 1311 linesearch->norms = flg; 1312 PetscFunctionReturn(0); 1313 } 1314 1315 #undef __FUNCT__ 1316 #define __FUNCT__ "SNESLineSearchGetVecs" 1317 /*@ 1318 SNESLineSearchGetVecs - Gets the vectors from the SNESLineSearch context 1319 1320 Input Parameters: 1321 . linesearch - linesearch context 1322 1323 Output Parameters: 1324 + X - The old solution 1325 . F - The old function 1326 . Y - The search direction 1327 . W - The new solution 1328 - G - The new function 1329 1330 Level: advanced 1331 1332 .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs() 1333 @*/ 1334 PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch,Vec *X,Vec *F, Vec *Y,Vec *W,Vec *G) 1335 { 1336 PetscFunctionBegin; 1337 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1338 if (X) { 1339 PetscValidPointer(X, 2); 1340 *X = linesearch->vec_sol; 1341 } 1342 if (F) { 1343 PetscValidPointer(F, 3); 1344 *F = linesearch->vec_func; 1345 } 1346 if (Y) { 1347 PetscValidPointer(Y, 4); 1348 *Y = linesearch->vec_update; 1349 } 1350 if (W) { 1351 PetscValidPointer(W, 5); 1352 *W = linesearch->vec_sol_new; 1353 } 1354 if (G) { 1355 PetscValidPointer(G, 6); 1356 *G = linesearch->vec_func_new; 1357 } 1358 1359 PetscFunctionReturn(0); 1360 } 1361 1362 #undef __FUNCT__ 1363 #define __FUNCT__ "SNESLineSearchSetVecs" 1364 /*@ 1365 SNESLineSearchSetVecs - Sets the vectors on the SNESLineSearch context 1366 1367 Input Parameters: 1368 + linesearch - linesearch context 1369 . X - The old solution 1370 . F - The old function 1371 . Y - The search direction 1372 . W - The new solution 1373 - G - The new function 1374 1375 Level: advanced 1376 1377 .seealso: SNESLineSearchSetNorms(), SNESLineSearchGetVecs() 1378 @*/ 1379 PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch,Vec X,Vec F,Vec Y,Vec W, Vec G) 1380 { 1381 PetscFunctionBegin; 1382 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1383 if (X) { 1384 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 1385 linesearch->vec_sol = X; 1386 } 1387 if (F) { 1388 PetscValidHeaderSpecific(F,VEC_CLASSID,3); 1389 linesearch->vec_func = F; 1390 } 1391 if (Y) { 1392 PetscValidHeaderSpecific(Y,VEC_CLASSID,4); 1393 linesearch->vec_update = Y; 1394 } 1395 if (W) { 1396 PetscValidHeaderSpecific(W,VEC_CLASSID,5); 1397 linesearch->vec_sol_new = W; 1398 } 1399 if (G) { 1400 PetscValidHeaderSpecific(G,VEC_CLASSID,6); 1401 linesearch->vec_func_new = G; 1402 } 1403 PetscFunctionReturn(0); 1404 } 1405 1406 #undef __FUNCT__ 1407 #define __FUNCT__ "SNESLineSearchAppendOptionsPrefix" 1408 /*@C 1409 SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all 1410 SNES options in the database. 1411 1412 Logically Collective on SNESLineSearch 1413 1414 Input Parameters: 1415 + snes - the SNES context 1416 - prefix - the prefix to prepend to all option names 1417 1418 Notes: 1419 A hyphen (-) must NOT be given at the beginning of the prefix name. 1420 The first character of all runtime options is AUTOMATICALLY the hyphen. 1421 1422 Level: advanced 1423 1424 .keywords: SNESLineSearch, append, options, prefix, database 1425 1426 .seealso: SNESGetOptionsPrefix() 1427 @*/ 1428 PetscErrorCode SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch,const char prefix[]) 1429 { 1430 PetscErrorCode ierr; 1431 1432 PetscFunctionBegin; 1433 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1434 ierr = PetscObjectAppendOptionsPrefix((PetscObject)linesearch,prefix);CHKERRQ(ierr); 1435 PetscFunctionReturn(0); 1436 } 1437 1438 #undef __FUNCT__ 1439 #define __FUNCT__ "SNESLineSearchGetOptionsPrefix" 1440 /*@C 1441 SNESLineSearchGetOptionsPrefix - Sets the prefix used for searching for all 1442 SNESLineSearch options in the database. 1443 1444 Not Collective 1445 1446 Input Parameter: 1447 . linesearch - the SNESLineSearch context 1448 1449 Output Parameter: 1450 . prefix - pointer to the prefix string used 1451 1452 Notes: 1453 On the fortran side, the user should pass in a string 'prefix' of 1454 sufficient length to hold the prefix. 1455 1456 Level: advanced 1457 1458 .keywords: SNESLineSearch, get, options, prefix, database 1459 1460 .seealso: SNESAppendOptionsPrefix() 1461 @*/ 1462 PetscErrorCode SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch,const char *prefix[]) 1463 { 1464 PetscErrorCode ierr; 1465 1466 PetscFunctionBegin; 1467 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1468 ierr = PetscObjectGetOptionsPrefix((PetscObject)linesearch,prefix);CHKERRQ(ierr); 1469 PetscFunctionReturn(0); 1470 } 1471 1472 #undef __FUNCT__ 1473 #define __FUNCT__ "SNESLineSearchGetWork" 1474 /*@ 1475 SNESLineSearchGetWork - Gets work vectors for the line search. 1476 1477 Input Parameter: 1478 + linesearch - the SNESLineSearch context 1479 - nwork - the number of work vectors 1480 1481 Level: developer 1482 1483 Notes: 1484 This is typically called at the beginning of a SNESLineSearch or SNESLineSearchShell implementation. 1485 1486 .keywords: SNESLineSearch, work, vector 1487 1488 .seealso: SNESDefaultGetWork() 1489 @*/ 1490 PetscErrorCode SNESLineSearchGetWork(SNESLineSearch linesearch, PetscInt nwork) 1491 { 1492 PetscErrorCode ierr; 1493 1494 PetscFunctionBegin; 1495 if (linesearch->vec_sol) { 1496 ierr = VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work);CHKERRQ(ierr); 1497 } 1498 SETERRQ(((PetscObject)linesearch)->comm, PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!"); 1499 PetscFunctionReturn(0); 1500 } 1501 1502 #undef __FUNCT__ 1503 #define __FUNCT__ "SNESLineSearchGetSuccess" 1504 /*@ 1505 SNESLineSearchGetSuccess - Gets the success/failure status of the last line search application 1506 1507 Input Parameters: 1508 . linesearch - linesearch context 1509 1510 Output Parameters: 1511 . success - The success or failure status 1512 1513 Notes: 1514 This is typically called after SNESLineSearchApply in order to determine if the line-search failed 1515 (and set the SNES convergence accordingly). 1516 1517 Level: intermediate 1518 1519 .seealso: SNESLineSearchSetSuccess() 1520 @*/ 1521 PetscErrorCode SNESLineSearchGetSuccess(SNESLineSearch linesearch, PetscBool *success) 1522 { 1523 PetscFunctionBegin; 1524 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1525 PetscValidPointer(success, 2); 1526 if (success) { 1527 *success = linesearch->success; 1528 } 1529 PetscFunctionReturn(0); 1530 } 1531 1532 #undef __FUNCT__ 1533 #define __FUNCT__ "SNESLineSearchSetSuccess" 1534 /*@ 1535 SNESLineSearchSetSuccess - Sets the success/failure status of the last line search application 1536 1537 Input Parameters: 1538 + linesearch - linesearch context 1539 - success - The success or failure status 1540 1541 Notes: 1542 This is typically called in a SNESLineSearchApply() or SNESLineSearchShell implementation to set 1543 the success or failure of the line search method. 1544 1545 Level: developer 1546 1547 .seealso: SNESLineSearchGetSuccess() 1548 @*/ 1549 PetscErrorCode SNESLineSearchSetSuccess(SNESLineSearch linesearch, PetscBool success) 1550 { 1551 PetscFunctionBegin; 1552 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1553 linesearch->success = success; 1554 PetscFunctionReturn(0); 1555 } 1556 1557 #undef __FUNCT__ 1558 #define __FUNCT__ "SNESLineSearchSetVIFunctions" 1559 /*@C 1560 SNESLineSearchSetVIFunctions - Sets VI-specific functions for line search computation. 1561 1562 Input Parameters: 1563 + snes - nonlinear context obtained from SNESCreate() 1564 . projectfunc - function for projecting the function to the bounds 1565 - normfunc - function for computing the norm of an active set 1566 1567 Logically Collective on SNES 1568 1569 Calling sequence of projectfunc: 1570 .vb 1571 projectfunc (SNES snes, Vec X) 1572 .ve 1573 1574 Input parameters for projectfunc: 1575 + snes - nonlinear context 1576 - X - current solution 1577 1578 Output parameters for projectfunc: 1579 . X - Projected solution 1580 1581 Calling sequence of normfunc: 1582 .vb 1583 projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm) 1584 .ve 1585 1586 Input parameters for normfunc: 1587 + snes - nonlinear context 1588 . X - current solution 1589 - F - current residual 1590 1591 Output parameters for normfunc: 1592 . fnorm - VI-specific norm of the function 1593 1594 Notes: 1595 The VI solvers require projection of the solution to the feasible set. projectfunc should implement this. 1596 1597 The VI solvers require special evaluation of the function norm such that the norm is only calculated 1598 on the inactive set. This should be implemented by normfunc. 1599 1600 Level: developer 1601 1602 .keywords: SNES, line search, VI, nonlinear, set, line search 1603 1604 .seealso: SNESLineSearchGetVIFunctions(), SNESLineSearchSetPostCheck(), SNESLineSearchSetPreCheck() 1605 @*/ 1606 extern PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc projectfunc, SNESLineSearchVINormFunc normfunc) 1607 { 1608 PetscFunctionBegin; 1609 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1610 if (projectfunc) linesearch->ops->viproject = projectfunc; 1611 if (normfunc) linesearch->ops->vinorm = normfunc; 1612 PetscFunctionReturn(0); 1613 } 1614 1615 #undef __FUNCT__ 1616 #define __FUNCT__ "SNESLineSearchGetVIFunctions" 1617 /*@C 1618 SNESLineSearchGetVIFunctions - Sets VI-specific functions for line search computation. 1619 1620 Input Parameters: 1621 . snes - nonlinear context obtained from SNESCreate() 1622 1623 Output Parameters: 1624 + projectfunc - function for projecting the function to the bounds 1625 - normfunc - function for computing the norm of an active set 1626 1627 Logically Collective on SNES 1628 1629 Level: developer 1630 1631 .keywords: SNES, line search, VI, nonlinear, get, line search 1632 1633 .seealso: SNESLineSearchSetVIFunctions(), SNESLineSearchGetPostCheck(), SNESLineSearchGetPreCheck() 1634 @*/ 1635 extern PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc *projectfunc, SNESLineSearchVINormFunc *normfunc) 1636 { 1637 PetscFunctionBegin; 1638 if (projectfunc) *projectfunc = linesearch->ops->viproject; 1639 if (normfunc) *normfunc = linesearch->ops->vinorm; 1640 PetscFunctionReturn(0); 1641 } 1642 1643 #undef __FUNCT__ 1644 #define __FUNCT__ "SNESLineSearchRegister" 1645 /*@C 1646 SNESLineSearchRegister - See SNESLineSearchRegisterDynamic() 1647 1648 Level: advanced 1649 @*/ 1650 PetscErrorCode SNESLineSearchRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(SNESLineSearch)) 1651 { 1652 char fullname[PETSC_MAX_PATH_LEN]; 1653 PetscErrorCode ierr; 1654 1655 PetscFunctionBegin; 1656 ierr = PetscFunctionListConcat(path,name,fullname);CHKERRQ(ierr); 1657 ierr = PetscFunctionListAdd(PETSC_COMM_WORLD,&SNESLineSearchList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr); 1658 PetscFunctionReturn(0); 1659 } 1660