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