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 linesearch->steptol = steptol; 973 linesearch->maxstep = maxstep; 974 linesearch->rtol = rtol; 975 linesearch->atol = atol; 976 linesearch->ltol = ltol; 977 linesearch->max_its = max_its; 978 PetscFunctionReturn(0); 979 } 980 981 982 #undef __FUNCT__ 983 #define __FUNCT__ "SNESLineSearchGetDamping" 984 /*@ 985 SNESLineSearchGetDamping - Gets the line search damping parameter. 986 987 Input Parameters: 988 . linesearch - linesearch context. 989 990 Output Parameters: 991 . damping - The damping parameter. 992 993 Level: intermediate 994 995 .seealso: SNESLineSearchGetStepTolerance() 996 @*/ 997 998 PetscErrorCode SNESLineSearchGetDamping(SNESLineSearch linesearch,PetscReal *damping) 999 { 1000 PetscFunctionBegin; 1001 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1002 PetscValidPointer(damping, 2); 1003 *damping = linesearch->damping; 1004 PetscFunctionReturn(0); 1005 } 1006 1007 #undef __FUNCT__ 1008 #define __FUNCT__ "SNESLineSearchSetDamping" 1009 /*@ 1010 SNESLineSearchSetDamping - Sets the line search damping paramter. 1011 1012 Input Parameters: 1013 . linesearch - linesearch context. 1014 . damping - The damping parameter. 1015 1016 Level: intermediate 1017 1018 Notes: 1019 The basic line search merely takes the update step scaled by the damping parameter. 1020 The use of the damping parameter in the l2 and cp line searches is much more subtle; 1021 it is used as a starting point in calculating the secant step; however, the eventual 1022 step may be of greater length than the damping parameter. In the bt line search it is 1023 used as the maximum possible step length, as the bt line search only backtracks. 1024 1025 .seealso: SNESLineSearchGetDamping() 1026 @*/ 1027 PetscErrorCode SNESLineSearchSetDamping(SNESLineSearch linesearch,PetscReal damping) 1028 { 1029 PetscFunctionBegin; 1030 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1031 linesearch->damping = damping; 1032 PetscFunctionReturn(0); 1033 } 1034 1035 #undef __FUNCT__ 1036 #define __FUNCT__ "SNESLineSearchGetOrder" 1037 /*@ 1038 SNESLineSearchGetOrder - Gets the line search approximation order. 1039 1040 Input Parameters: 1041 . linesearch - linesearch context. 1042 1043 Output Parameters: 1044 . order - The order. 1045 1046 Level: intermediate 1047 1048 .seealso: SNESLineSearchSetOrder() 1049 @*/ 1050 1051 PetscErrorCode SNESLineSearchGetOrder(SNESLineSearch linesearch,SNESLineSearchOrder *order) 1052 { 1053 PetscFunctionBegin; 1054 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1055 PetscValidPointer(order, 2); 1056 *order = linesearch->order; 1057 PetscFunctionReturn(0); 1058 } 1059 1060 #undef __FUNCT__ 1061 #define __FUNCT__ "SNESLineSearchSetOrder" 1062 /*@ 1063 SNESLineSearchSetOrder - Sets the line search damping paramter. 1064 1065 Input Parameters: 1066 . linesearch - linesearch context. 1067 . order - The damping parameter. 1068 1069 Level: intermediate 1070 1071 Notes: 1072 Variable orders are supported by the following line searches: 1073 . bt - cubic and quadratic 1074 1075 .seealso: SNESLineSearchGetOrder() 1076 @*/ 1077 PetscErrorCode SNESLineSearchSetOrder(SNESLineSearch linesearch,SNESLineSearchOrder order) 1078 { 1079 PetscFunctionBegin; 1080 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1081 linesearch->order = order; 1082 PetscFunctionReturn(0); 1083 } 1084 1085 #undef __FUNCT__ 1086 #define __FUNCT__ "SNESLineSearchGetNorms" 1087 /*@ 1088 SNESLineSearchGetNorms - Gets the norms for for X, Y, and F. 1089 1090 Input Parameters: 1091 . linesearch - linesearch context. 1092 1093 Output Parameters: 1094 + xnorm - The norm of the current solution 1095 . fnorm - The norm of the current function 1096 - ynorm - The norm of the current update 1097 1098 Notes: 1099 This function is mainly called from SNES implementations. 1100 1101 Level: intermediate 1102 1103 .seealso: SNESLineSearchSetNorms() SNESLineSearchGetVecs() 1104 @*/ 1105 PetscErrorCode SNESLineSearchGetNorms(SNESLineSearch linesearch, PetscReal * xnorm, PetscReal * fnorm, PetscReal * ynorm) 1106 { 1107 PetscFunctionBegin; 1108 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1109 if (xnorm) { 1110 *xnorm = linesearch->xnorm; 1111 } 1112 if (fnorm) { 1113 *fnorm = linesearch->fnorm; 1114 } 1115 if (ynorm) { 1116 *ynorm = linesearch->ynorm; 1117 } 1118 PetscFunctionReturn(0); 1119 } 1120 1121 #undef __FUNCT__ 1122 #define __FUNCT__ "SNESLineSearchSetNorms" 1123 /*@ 1124 SNESLineSearchSetNorms - Gets the computed norms for for X, Y, and F. 1125 1126 Input Parameters: 1127 + linesearch - linesearch context. 1128 . xnorm - The norm of the current solution 1129 . fnorm - The norm of the current function 1130 - ynorm - The norm of the current update 1131 1132 Level: intermediate 1133 1134 .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs() 1135 @*/ 1136 PetscErrorCode SNESLineSearchSetNorms(SNESLineSearch linesearch, PetscReal xnorm, PetscReal fnorm, PetscReal ynorm) 1137 { 1138 PetscFunctionBegin; 1139 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1140 linesearch->xnorm = xnorm; 1141 linesearch->fnorm = fnorm; 1142 linesearch->ynorm = ynorm; 1143 PetscFunctionReturn(0); 1144 } 1145 1146 #undef __FUNCT__ 1147 #define __FUNCT__ "SNESLineSearchComputeNorms" 1148 /*@ 1149 SNESLineSearchComputeNorms - Computes the norms of X, F, and Y. 1150 1151 Input Parameters: 1152 . linesearch - linesearch context. 1153 1154 Options Database Keys: 1155 . -snes_linesearch_norms - turn norm computation on or off. 1156 1157 Level: intermediate 1158 1159 .seealso: SNESLineSearchGetNorms, SNESLineSearchSetNorms() 1160 @*/ 1161 PetscErrorCode SNESLineSearchComputeNorms(SNESLineSearch linesearch) 1162 { 1163 PetscErrorCode ierr; 1164 SNES snes; 1165 PetscFunctionBegin; 1166 if (linesearch->norms) { 1167 if (linesearch->ops->vinorm) { 1168 ierr = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr); 1169 ierr = VecNorm(linesearch->vec_sol, NORM_2, &linesearch->xnorm);CHKERRQ(ierr); 1170 ierr = VecNorm(linesearch->vec_update, NORM_2, &linesearch->ynorm);CHKERRQ(ierr); 1171 ierr = (*linesearch->ops->vinorm)(snes, linesearch->vec_func, linesearch->vec_sol, &linesearch->fnorm);CHKERRQ(ierr); 1172 } else { 1173 ierr = VecNormBegin(linesearch->vec_func, NORM_2, &linesearch->fnorm);CHKERRQ(ierr); 1174 ierr = VecNormBegin(linesearch->vec_sol, NORM_2, &linesearch->xnorm);CHKERRQ(ierr); 1175 ierr = VecNormBegin(linesearch->vec_update, NORM_2, &linesearch->ynorm);CHKERRQ(ierr); 1176 ierr = VecNormEnd(linesearch->vec_func, NORM_2, &linesearch->fnorm);CHKERRQ(ierr); 1177 ierr = VecNormEnd(linesearch->vec_sol, NORM_2, &linesearch->xnorm);CHKERRQ(ierr); 1178 ierr = VecNormEnd(linesearch->vec_update, NORM_2, &linesearch->ynorm);CHKERRQ(ierr); 1179 } 1180 } 1181 PetscFunctionReturn(0); 1182 } 1183 1184 #undef __FUNCT__ 1185 #define __FUNCT__ "SNESLineSearchGetVecs" 1186 /*@ 1187 SNESLineSearchGetVecs - Gets the vectors from the SNESLineSearch context 1188 1189 Input Parameters: 1190 . linesearch - linesearch context. 1191 1192 Output Parameters: 1193 + X - The old solution 1194 . F - The old function 1195 . Y - The search direction 1196 . W - The new solution 1197 - G - The new function 1198 1199 Level: intermediate 1200 1201 .seealso: SNESLineSearchGetNorms(), SNESLineSearchSetVecs() 1202 @*/ 1203 PetscErrorCode SNESLineSearchGetVecs(SNESLineSearch linesearch,Vec *X,Vec *F, Vec *Y,Vec *W,Vec *G) { 1204 PetscFunctionBegin; 1205 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1206 if (X) { 1207 PetscValidPointer(X, 2); 1208 *X = linesearch->vec_sol; 1209 } 1210 if (F) { 1211 PetscValidPointer(F, 3); 1212 *F = linesearch->vec_func; 1213 } 1214 if (Y) { 1215 PetscValidPointer(Y, 4); 1216 *Y = linesearch->vec_update; 1217 } 1218 if (W) { 1219 PetscValidPointer(W, 5); 1220 *W = linesearch->vec_sol_new; 1221 } 1222 if (G) { 1223 PetscValidPointer(G, 6); 1224 *G = linesearch->vec_func_new; 1225 } 1226 1227 PetscFunctionReturn(0); 1228 } 1229 1230 #undef __FUNCT__ 1231 #define __FUNCT__ "SNESLineSearchSetVecs" 1232 /*@ 1233 SNESLineSearchSetVecs - Sets the vectors on the SNESLineSearch context 1234 1235 Input Parameters: 1236 + linesearch - linesearch context. 1237 . X - The old solution 1238 . F - The old function 1239 . Y - The search direction 1240 . W - The new solution 1241 - G - The new function 1242 1243 Level: intermediate 1244 1245 .seealso: SNESLineSearchSetNorms(), SNESLineSearchGetVecs() 1246 @*/ 1247 PetscErrorCode SNESLineSearchSetVecs(SNESLineSearch linesearch,Vec X,Vec F,Vec Y,Vec W, Vec G) { 1248 PetscFunctionBegin; 1249 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1250 if (X) { 1251 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 1252 linesearch->vec_sol = X; 1253 } 1254 if (F) { 1255 PetscValidHeaderSpecific(F,VEC_CLASSID,3); 1256 linesearch->vec_func = F; 1257 } 1258 if (Y) { 1259 PetscValidHeaderSpecific(Y,VEC_CLASSID,4); 1260 linesearch->vec_update = Y; 1261 } 1262 if (W) { 1263 PetscValidHeaderSpecific(W,VEC_CLASSID,5); 1264 linesearch->vec_sol_new = W; 1265 } 1266 if (G) { 1267 PetscValidHeaderSpecific(G,VEC_CLASSID,6); 1268 linesearch->vec_func_new = G; 1269 } 1270 1271 PetscFunctionReturn(0); 1272 } 1273 1274 #undef __FUNCT__ 1275 #define __FUNCT__ "SNESLineSearchAppendOptionsPrefix" 1276 /*@C 1277 SNESLineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all 1278 SNES options in the database. 1279 1280 Logically Collective on SNESLineSearch 1281 1282 Input Parameters: 1283 + snes - the SNES context 1284 - prefix - the prefix to prepend to all option names 1285 1286 Notes: 1287 A hyphen (-) must NOT be given at the beginning of the prefix name. 1288 The first character of all runtime options is AUTOMATICALLY the hyphen. 1289 1290 Level: advanced 1291 1292 .keywords: SNESLineSearch, append, options, prefix, database 1293 1294 .seealso: SNESGetOptionsPrefix() 1295 @*/ 1296 PetscErrorCode SNESLineSearchAppendOptionsPrefix(SNESLineSearch linesearch,const char prefix[]) 1297 { 1298 PetscErrorCode ierr; 1299 1300 PetscFunctionBegin; 1301 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1302 ierr = PetscObjectAppendOptionsPrefix((PetscObject)linesearch,prefix);CHKERRQ(ierr); 1303 PetscFunctionReturn(0); 1304 } 1305 1306 #undef __FUNCT__ 1307 #define __FUNCT__ "SNESLineSearchGetOptionsPrefix" 1308 /*@C 1309 SNESLineSearchGetOptionsPrefix - Sets the prefix used for searching for all 1310 SNESLineSearch options in the database. 1311 1312 Not Collective 1313 1314 Input Parameter: 1315 . linesearch - the SNESLineSearch context 1316 1317 Output Parameter: 1318 . prefix - pointer to the prefix string used 1319 1320 Notes: On the fortran side, the user should pass in a string 'prefix' of 1321 sufficient length to hold the prefix. 1322 1323 Level: advanced 1324 1325 .keywords: SNESLineSearch, get, options, prefix, database 1326 1327 .seealso: SNESAppendOptionsPrefix() 1328 @*/ 1329 PetscErrorCode SNESLineSearchGetOptionsPrefix(SNESLineSearch linesearch,const char *prefix[]) 1330 { 1331 PetscErrorCode ierr; 1332 1333 PetscFunctionBegin; 1334 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1335 ierr = PetscObjectGetOptionsPrefix((PetscObject)linesearch,prefix);CHKERRQ(ierr); 1336 PetscFunctionReturn(0); 1337 } 1338 1339 #undef __FUNCT__ 1340 #define __FUNCT__ "SNESLineSearchGetWork" 1341 /*@ 1342 SNESLineSearchGetWork - Gets work vectors for the line search. 1343 1344 Input Parameter: 1345 + linesearch - the SNESLineSearch context 1346 - nwork - the number of work vectors 1347 1348 Level: developer 1349 1350 Notes: 1351 This is typically called at the beginning of a SNESLineSearch or SNESLineSearchShell implementation. 1352 1353 .keywords: SNESLineSearch, work, vector 1354 1355 .seealso: SNESDefaultGetWork() 1356 @*/ 1357 PetscErrorCode SNESLineSearchGetWork(SNESLineSearch linesearch, PetscInt nwork) 1358 { 1359 PetscErrorCode ierr; 1360 PetscFunctionBegin; 1361 if (linesearch->vec_sol) { 1362 ierr = VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work);CHKERRQ(ierr); 1363 } else { 1364 SETERRQ(((PetscObject)linesearch)->comm, PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!"); 1365 } 1366 PetscFunctionReturn(0); 1367 } 1368 1369 1370 #undef __FUNCT__ 1371 #define __FUNCT__ "SNESLineSearchGetSuccess" 1372 /*@ 1373 SNESLineSearchGetSuccess - Gets the success/failure status of the last line search application 1374 1375 Input Parameters: 1376 . linesearch - linesearch context. 1377 1378 Output Parameters: 1379 . success - The success or failure status. 1380 1381 Notes: 1382 This is typically called after SNESLineSearchApply in order to determine if the line-search failed 1383 (and set the SNES convergence accordingly). 1384 1385 Level: intermediate 1386 1387 .seealso: SNESLineSearchSetSuccess() 1388 @*/ 1389 PetscErrorCode SNESLineSearchGetSuccess(SNESLineSearch linesearch, PetscBool *success) 1390 { 1391 PetscFunctionBegin; 1392 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1393 PetscValidPointer(success, 2); 1394 if (success) { 1395 *success = linesearch->success; 1396 } 1397 PetscFunctionReturn(0); 1398 } 1399 1400 #undef __FUNCT__ 1401 #define __FUNCT__ "SNESLineSearchSetSuccess" 1402 /*@ 1403 SNESLineSearchSetSuccess - Sets the success/failure status of the last line search application 1404 1405 Input Parameters: 1406 + linesearch - linesearch context. 1407 - success - The success or failure status. 1408 1409 Notes: 1410 This is typically called in a SNESLineSearchApply() or SNESLineSearchShell implementation to set 1411 the success or failure of the line search method. 1412 1413 Level: intermediate 1414 1415 .seealso: SNESLineSearchGetSuccess() 1416 @*/ 1417 PetscErrorCode SNESLineSearchSetSuccess(SNESLineSearch linesearch, PetscBool success) 1418 { 1419 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1420 PetscFunctionBegin; 1421 linesearch->success = success; 1422 PetscFunctionReturn(0); 1423 } 1424 1425 #undef __FUNCT__ 1426 #define __FUNCT__ "SNESLineSearchSetVIFunctions" 1427 /*@C 1428 SNESLineSearchSetVIFunctions - Sets VI-specific functions for line search computation. 1429 1430 Input Parameters: 1431 + snes - nonlinear context obtained from SNESCreate() 1432 . projectfunc - function for projecting the function to the bounds 1433 - normfunc - function for computing the norm of an active set 1434 1435 Logically Collective on SNES 1436 1437 Calling sequence of projectfunc: 1438 .vb 1439 projectfunc (SNES snes, Vec X) 1440 .ve 1441 1442 Input parameters for projectfunc: 1443 + snes - nonlinear context 1444 - X - current solution 1445 1446 Output parameters for projectfunc: 1447 . X - Projected solution 1448 1449 Calling sequence of normfunc: 1450 .vb 1451 projectfunc (SNES snes, Vec X, Vec F, PetscScalar * fnorm) 1452 .ve 1453 1454 Input parameters for normfunc: 1455 + snes - nonlinear context 1456 . X - current solution 1457 - F - current residual 1458 1459 Output parameters for normfunc: 1460 . fnorm - VI-specific norm of the function 1461 1462 Notes: 1463 The VI solvers require projection of the solution to the feasible set. projectfunc should implement this. 1464 1465 The VI solvers require special evaluation of the function norm such that the norm is only calculated 1466 on the inactive set. This should be implemented by normfunc. 1467 1468 Level: developer 1469 1470 .keywords: SNES, line search, VI, nonlinear, set, line search 1471 1472 .seealso: SNESLineSearchGetVIFunctions(), SNESLineSearchSetPostCheck(), SNESLineSearchSetPreCheck() 1473 @*/ 1474 extern PetscErrorCode SNESLineSearchSetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc projectfunc, SNESLineSearchVINormFunc normfunc) 1475 { 1476 PetscFunctionBegin; 1477 PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 1478 if (projectfunc) linesearch->ops->viproject = projectfunc; 1479 if (normfunc) linesearch->ops->vinorm = normfunc; 1480 PetscFunctionReturn(0); 1481 } 1482 1483 #undef __FUNCT__ 1484 #define __FUNCT__ "SNESLineSearchGetVIFunctions" 1485 /*@C 1486 SNESLineSearchGetVIFunctions - Sets VI-specific functions for line search computation. 1487 1488 Input Parameters: 1489 . snes - nonlinear context obtained from SNESCreate() 1490 1491 Output Parameters: 1492 + projectfunc - function for projecting the function to the bounds 1493 - normfunc - function for computing the norm of an active set 1494 1495 Logically Collective on SNES 1496 1497 Level: developer 1498 1499 .keywords: SNES, line search, VI, nonlinear, get, line search 1500 1501 .seealso: SNESLineSearchSetVIFunctions(), SNESLineSearchGetPostCheck(), SNESLineSearchGetPreCheck() 1502 @*/ 1503 extern PetscErrorCode SNESLineSearchGetVIFunctions(SNESLineSearch linesearch, SNESLineSearchVIProjectFunc *projectfunc, SNESLineSearchVINormFunc *normfunc) 1504 { 1505 PetscFunctionBegin; 1506 if (projectfunc) *projectfunc = linesearch->ops->viproject; 1507 if (normfunc) *normfunc = linesearch->ops->vinorm; 1508 PetscFunctionReturn(0); 1509 } 1510 1511 #undef __FUNCT__ 1512 #define __FUNCT__ "SNESLineSearchRegister" 1513 /*@C 1514 SNESLineSearchRegister - See SNESLineSearchRegisterDynamic() 1515 1516 Level: advanced 1517 @*/ 1518 PetscErrorCode SNESLineSearchRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(SNESLineSearch)) 1519 { 1520 char fullname[PETSC_MAX_PATH_LEN]; 1521 PetscErrorCode ierr; 1522 1523 PetscFunctionBegin; 1524 ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr); 1525 ierr = PetscFListAdd(&SNESLineSearchList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr); 1526 PetscFunctionReturn(0); 1527 } 1528