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