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