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