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