1 #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 2 #include <petscdmshell.h> 3 #include <petscdraw.h> 4 #include <petscds.h> 5 #include <petscdmadaptor.h> 6 #include <petscconvest.h> 7 8 PetscBool SNESRegisterAllCalled = PETSC_FALSE; 9 PetscFunctionList SNESList = NULL; 10 11 /* Logging support */ 12 PetscClassId SNES_CLASSID, DMSNES_CLASSID; 13 PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NewtonALEval, SNES_NPCSolve, SNES_ObjectiveEval; 14 15 /*@ 16 SNESSetErrorIfNotConverged - Causes `SNESSolve()` to generate an error immediately if the solver has not converged. 17 18 Logically Collective 19 20 Input Parameters: 21 + snes - iterative context obtained from `SNESCreate()` 22 - flg - `PETSC_TRUE` indicates you want the error generated 23 24 Options Database Key: 25 . -snes_error_if_not_converged <true,false> - cause an immediate error condition and stop the program if the solver does not converge 26 27 Level: intermediate 28 29 Note: 30 Normally PETSc continues if a solver fails to converge, you can call `SNESGetConvergedReason()` after a `SNESSolve()` 31 to determine if it has converged. Otherwise the solution may be inaccurate or wrong 32 33 .seealso: [](ch_snes), `SNES`, `SNESGetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()` 34 @*/ 35 PetscErrorCode SNESSetErrorIfNotConverged(SNES snes, PetscBool flg) 36 { 37 PetscFunctionBegin; 38 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 39 PetscValidLogicalCollectiveBool(snes, flg, 2); 40 snes->errorifnotconverged = flg; 41 PetscFunctionReturn(PETSC_SUCCESS); 42 } 43 44 /*@ 45 SNESGetErrorIfNotConverged - Indicates if `SNESSolve()` will generate an error if the solver does not converge? 46 47 Not Collective 48 49 Input Parameter: 50 . snes - iterative context obtained from `SNESCreate()` 51 52 Output Parameter: 53 . flag - `PETSC_TRUE` if it will generate an error, else `PETSC_FALSE` 54 55 Level: intermediate 56 57 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()` 58 @*/ 59 PetscErrorCode SNESGetErrorIfNotConverged(SNES snes, PetscBool *flag) 60 { 61 PetscFunctionBegin; 62 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 63 PetscAssertPointer(flag, 2); 64 *flag = snes->errorifnotconverged; 65 PetscFunctionReturn(PETSC_SUCCESS); 66 } 67 68 /*@ 69 SNESSetAlwaysComputesFinalResidual - tells the `SNES` to always compute the residual (nonlinear function value) at the final solution 70 71 Logically Collective 72 73 Input Parameters: 74 + snes - the shell `SNES` 75 - flg - `PETSC_TRUE` to always compute the residual 76 77 Level: advanced 78 79 Note: 80 Some solvers (such as smoothers in a `SNESFAS`) do not need the residual computed at the final solution so skip computing it 81 to save time. 82 83 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESGetAlwaysComputesFinalResidual()` 84 @*/ 85 PetscErrorCode SNESSetAlwaysComputesFinalResidual(SNES snes, PetscBool flg) 86 { 87 PetscFunctionBegin; 88 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 89 snes->alwayscomputesfinalresidual = flg; 90 PetscFunctionReturn(PETSC_SUCCESS); 91 } 92 93 /*@ 94 SNESGetAlwaysComputesFinalResidual - checks if the `SNES` always computes the residual at the final solution 95 96 Logically Collective 97 98 Input Parameter: 99 . snes - the `SNES` context 100 101 Output Parameter: 102 . flg - `PETSC_TRUE` if the residual is computed 103 104 Level: advanced 105 106 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESSetAlwaysComputesFinalResidual()` 107 @*/ 108 PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg) 109 { 110 PetscFunctionBegin; 111 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 112 *flg = snes->alwayscomputesfinalresidual; 113 PetscFunctionReturn(PETSC_SUCCESS); 114 } 115 116 /*@ 117 SNESSetFunctionDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetFunction()` is not 118 in the functions domain. For example, a step with negative pressure. 119 120 Not Collective 121 122 Input Parameter: 123 . snes - the `SNES` context 124 125 Level: advanced 126 127 Notes: 128 This does not need to be called by all processes in the `SNES` MPI communicator. 129 130 If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 131 132 You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 133 134 You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 135 `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 136 137 You can call `SNESSetJacobianDomainError()` during a Jacobian computation to indicate the proposed solution is not in the domain. 138 139 Developer Note: 140 This value is used by `SNESCheckFunctionNorm()` to determine if the `SNESConvergedReason` is set to `SNES_DIVERGED_FUNCTION_DOMAIN` 141 142 .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`, 143 `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, 144 `SNES_DIVERGED_FUNCTION_DOMAIN` 145 @*/ 146 PetscErrorCode SNESSetFunctionDomainError(SNES snes) 147 { 148 PetscFunctionBegin; 149 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 150 snes->domainerror = PETSC_TRUE; 151 PetscFunctionReturn(PETSC_SUCCESS); 152 } 153 154 /*@ 155 SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation. 156 157 Logically Collective 158 159 Input Parameter: 160 . snes - the `SNES` context 161 162 Level: advanced 163 164 Notes: 165 If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN` 166 167 You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result). 168 169 You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or 170 `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()` 171 172 .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`, 173 `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()` 174 @*/ 175 PetscErrorCode SNESSetJacobianDomainError(SNES snes) 176 { 177 PetscFunctionBegin; 178 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 179 PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense"); 180 snes->jacobiandomainerror = PETSC_TRUE; 181 PetscFunctionReturn(PETSC_SUCCESS); 182 } 183 184 /*@ 185 SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` Jacobian domain error after 186 each Jacobian evaluation. By default, it checks for the Jacobian domain error in the debug mode, and does not check it in the optimized mode. 187 188 Logically Collective 189 190 Input Parameters: 191 + snes - the `SNES` context 192 - flg - indicates if or not to check Jacobian domain error after each Jacobian evaluation 193 194 Level: advanced 195 196 Note: 197 Checks require one extra parallel synchronization for each Jacobian evaluation 198 199 .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()` 200 @*/ 201 PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg) 202 { 203 PetscFunctionBegin; 204 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 205 snes->checkjacdomainerror = flg; 206 PetscFunctionReturn(PETSC_SUCCESS); 207 } 208 209 /*@ 210 SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation. 211 212 Logically Collective 213 214 Input Parameter: 215 . snes - the `SNES` context 216 217 Output Parameter: 218 . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation 219 220 Level: advanced 221 222 .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()` 223 @*/ 224 PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg) 225 { 226 PetscFunctionBegin; 227 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 228 PetscAssertPointer(flg, 2); 229 *flg = snes->checkjacdomainerror; 230 PetscFunctionReturn(PETSC_SUCCESS); 231 } 232 233 /*@ 234 SNESGetFunctionDomainError - Gets the status of the domain error after a call to `SNESComputeFunction()` 235 236 Not Collective, different MPI processes may return different values 237 238 Input Parameter: 239 . snes - the `SNES` context 240 241 Output Parameter: 242 . domainerror - Set to `PETSC_TRUE` if there's a domain error; `PETSC_FALSE` otherwise. 243 244 Level: developer 245 246 Notes: 247 The value will only be true on those MPI processes that called `SNESSetFunctionDomainError()` 248 249 The value is reset to `PETSC_FALSE` when `SNESCheckFunctionNorm()` is called. 250 251 .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()` 252 @*/ 253 PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror) 254 { 255 PetscFunctionBegin; 256 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 257 PetscAssertPointer(domainerror, 2); 258 *domainerror = snes->domainerror; 259 PetscFunctionReturn(PETSC_SUCCESS); 260 } 261 262 /*@ 263 SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()` 264 265 Not Collective, different MPI processes may return different values 266 267 Input Parameter: 268 . snes - the `SNES` context 269 270 Output Parameter: 271 . domainerror - Set to `PETSC_TRUE` if there's a Jacobian domain error; `PETSC_FALSE` otherwise. 272 273 Level: advanced 274 275 Notes: 276 The value will only be true on those MPI processes that called `SNESSetJacobianDomainError()` 277 278 The value is reset to `PETSC_FALSE` when `SNESCheckJacobianDomainerror()` is called but only `SNESSetCheckJacobianDomainError()` was called 279 280 .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`, `SNESGetFunctionDomainError()` 281 @*/ 282 PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror) 283 { 284 PetscFunctionBegin; 285 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 286 PetscAssertPointer(domainerror, 2); 287 *domainerror = snes->jacobiandomainerror; 288 PetscFunctionReturn(PETSC_SUCCESS); 289 } 290 291 /*@ 292 SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`. 293 294 Collective 295 296 Input Parameters: 297 + snes - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or 298 some related function before a call to `SNESLoad()`. 299 - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` 300 301 Level: intermediate 302 303 Note: 304 The `SNESType` is determined by the data in the file, any type set into the `SNES` before this call is ignored. 305 306 .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()` 307 @*/ 308 PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer) 309 { 310 PetscBool isbinary; 311 PetscInt classid; 312 char type[256]; 313 KSP ksp; 314 DM dm; 315 DMSNES dmsnes; 316 317 PetscFunctionBegin; 318 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 319 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 320 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 321 PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 322 323 PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT)); 324 PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file"); 325 PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR)); 326 PetscCall(SNESSetType(snes, type)); 327 PetscTryTypeMethod(snes, load, viewer); 328 PetscCall(SNESGetDM(snes, &dm)); 329 PetscCall(DMGetDMSNES(dm, &dmsnes)); 330 PetscCall(DMSNESLoad(dmsnes, viewer)); 331 PetscCall(SNESGetKSP(snes, &ksp)); 332 PetscCall(KSPLoad(ksp, viewer)); 333 PetscFunctionReturn(PETSC_SUCCESS); 334 } 335 336 #include <petscdraw.h> 337 #if defined(PETSC_HAVE_SAWS) 338 #include <petscviewersaws.h> 339 #endif 340 341 /*@ 342 SNESViewFromOptions - View a `SNES` based on values in the options database 343 344 Collective 345 346 Input Parameters: 347 + A - the `SNES` context 348 . obj - Optional object that provides the options prefix for the checks 349 - name - command line option 350 351 Level: intermediate 352 353 .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()` 354 @*/ 355 PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[]) 356 { 357 PetscFunctionBegin; 358 PetscValidHeaderSpecific(A, SNES_CLASSID, 1); 359 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 360 PetscFunctionReturn(PETSC_SUCCESS); 361 } 362 363 PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *); 364 365 /*@ 366 SNESView - Prints or visualizes the `SNES` data structure. 367 368 Collective 369 370 Input Parameters: 371 + snes - the `SNES` context 372 - viewer - the `PetscViewer` 373 374 Options Database Key: 375 . -snes_view - Calls `SNESView()` at end of `SNESSolve()` 376 377 Level: beginner 378 379 Notes: 380 The available visualization contexts include 381 + `PETSC_VIEWER_STDOUT_SELF` - standard output (default) 382 - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard 383 output where only the first processor opens 384 the file. All other processors send their 385 data to the first processor to print. 386 387 The available formats include 388 + `PETSC_VIEWER_DEFAULT` - standard output (default) 389 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM` 390 391 The user can open an alternative visualization context with 392 `PetscViewerASCIIOpen()` - output to a specified file. 393 394 In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer). 395 396 .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()` 397 @*/ 398 PetscErrorCode SNESView(SNES snes, PetscViewer viewer) 399 { 400 SNESKSPEW *kctx; 401 KSP ksp; 402 SNESLineSearch linesearch; 403 PetscBool isascii, isstring, isbinary, isdraw; 404 DMSNES dmsnes; 405 #if defined(PETSC_HAVE_SAWS) 406 PetscBool issaws; 407 #endif 408 409 PetscFunctionBegin; 410 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 411 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer)); 412 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 413 PetscCheckSameComm(snes, 1, viewer, 2); 414 415 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 416 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 417 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 418 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 419 #if defined(PETSC_HAVE_SAWS) 420 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 421 #endif 422 if (isascii) { 423 SNESNormSchedule normschedule; 424 DM dm; 425 SNESJacobianFn *cJ; 426 void *ctx; 427 const char *pre = ""; 428 429 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer)); 430 if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, " SNES has not been set up so information may be incomplete\n")); 431 if (snes->ops->view) { 432 PetscCall(PetscViewerASCIIPushTab(viewer)); 433 PetscUseTypeMethod(snes, view, viewer); 434 PetscCall(PetscViewerASCIIPopTab(viewer)); 435 } 436 if (snes->max_funcs == PETSC_UNLIMITED) { 437 PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=unlimited\n", snes->max_its)); 438 } else { 439 PetscCall(PetscViewerASCIIPrintf(viewer, " maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs)); 440 } 441 PetscCall(PetscViewerASCIIPrintf(viewer, " tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol)); 442 if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its)); 443 PetscCall(PetscViewerASCIIPrintf(viewer, " total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs)); 444 PetscCall(SNESGetNormSchedule(snes, &normschedule)); 445 if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " norm schedule %s\n", SNESNormSchedules[normschedule])); 446 if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence)); 447 if (snes->ksp_ewconv) { 448 kctx = (SNESKSPEW *)snes->kspconvctx; 449 if (kctx) { 450 PetscCall(PetscViewerASCIIPrintf(viewer, " Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version)); 451 PetscCall(PetscViewerASCIIPrintf(viewer, " rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold)); 452 PetscCall(PetscViewerASCIIPrintf(viewer, " gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2)); 453 } 454 } 455 if (snes->lagpreconditioner == -1) { 456 PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is never rebuilt\n")); 457 } else if (snes->lagpreconditioner > 1) { 458 PetscCall(PetscViewerASCIIPrintf(viewer, " Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner)); 459 } 460 if (snes->lagjacobian == -1) { 461 PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is never rebuilt\n")); 462 } else if (snes->lagjacobian > 1) { 463 PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian)); 464 } 465 PetscCall(SNESGetDM(snes, &dm)); 466 PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx)); 467 if (snes->mf_operator) { 468 PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing\n")); 469 pre = "Preconditioning "; 470 } 471 if (cJ == SNESComputeJacobianDefault) { 472 PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences one column at a time\n", pre)); 473 } else if (cJ == SNESComputeJacobianDefaultColor) { 474 PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using finite differences with coloring\n", pre)); 475 /* it slightly breaks data encapsulation for access the DMDA information directly */ 476 } else if (cJ == SNESComputeJacobian_DMDA) { 477 MatFDColoring fdcoloring; 478 PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring)); 479 if (fdcoloring) { 480 PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using colored finite differences on a DMDA\n", pre)); 481 } else { 482 PetscCall(PetscViewerASCIIPrintf(viewer, " %sJacobian is built using a DMDA local Jacobian\n", pre)); 483 } 484 } else if (snes->mf && !snes->mf_operator) { 485 PetscCall(PetscViewerASCIIPrintf(viewer, " Jacobian is applied matrix-free with differencing, no explicit Jacobian\n")); 486 } 487 } else if (isstring) { 488 const char *type; 489 PetscCall(SNESGetType(snes, &type)); 490 PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type)); 491 PetscTryTypeMethod(snes, view, viewer); 492 } else if (isbinary) { 493 PetscInt classid = SNES_FILE_CLASSID; 494 MPI_Comm comm; 495 PetscMPIInt rank; 496 char type[256]; 497 498 PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 499 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 500 if (rank == 0) { 501 PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT)); 502 PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type))); 503 PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR)); 504 } 505 PetscTryTypeMethod(snes, view, viewer); 506 } else if (isdraw) { 507 PetscDraw draw; 508 char str[36]; 509 PetscReal x, y, bottom, h; 510 511 PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 512 PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y)); 513 PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str))); 514 PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str))); 515 PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h)); 516 bottom = y - h; 517 PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom)); 518 PetscTryTypeMethod(snes, view, viewer); 519 #if defined(PETSC_HAVE_SAWS) 520 } else if (issaws) { 521 PetscMPIInt rank; 522 const char *name; 523 524 PetscCall(PetscObjectGetName((PetscObject)snes, &name)); 525 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 526 if (!((PetscObject)snes)->amsmem && rank == 0) { 527 char dir[1024]; 528 529 PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer)); 530 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name)); 531 PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT)); 532 if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE)); 533 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name)); 534 PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE)); 535 } 536 #endif 537 } 538 if (snes->linesearch) { 539 PetscCall(SNESGetLineSearch(snes, &linesearch)); 540 PetscCall(PetscViewerASCIIPushTab(viewer)); 541 PetscCall(SNESLineSearchView(linesearch, viewer)); 542 PetscCall(PetscViewerASCIIPopTab(viewer)); 543 } 544 if (snes->npc && snes->usesnpc) { 545 PetscCall(PetscViewerASCIIPushTab(viewer)); 546 PetscCall(SNESView(snes->npc, viewer)); 547 PetscCall(PetscViewerASCIIPopTab(viewer)); 548 } 549 PetscCall(PetscViewerASCIIPushTab(viewer)); 550 PetscCall(DMGetDMSNES(snes->dm, &dmsnes)); 551 PetscCall(DMSNESView(dmsnes, viewer)); 552 PetscCall(PetscViewerASCIIPopTab(viewer)); 553 if (snes->usesksp) { 554 PetscCall(SNESGetKSP(snes, &ksp)); 555 PetscCall(PetscViewerASCIIPushTab(viewer)); 556 PetscCall(KSPView(ksp, viewer)); 557 PetscCall(PetscViewerASCIIPopTab(viewer)); 558 } 559 if (isdraw) { 560 PetscDraw draw; 561 PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 562 PetscCall(PetscDrawPopCurrentPoint(draw)); 563 } 564 PetscFunctionReturn(PETSC_SUCCESS); 565 } 566 567 /* 568 We retain a list of functions that also take SNES command 569 line options. These are called at the end SNESSetFromOptions() 570 */ 571 #define MAXSETFROMOPTIONS 5 572 static PetscInt numberofsetfromoptions; 573 static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES); 574 575 /*@C 576 SNESAddOptionsChecker - Adds an additional function to check for `SNES` options. 577 578 Not Collective 579 580 Input Parameter: 581 . snescheck - function that checks for options 582 583 Calling sequence of `snescheck`: 584 . snes - the `SNES` object for which it is checking options 585 586 Level: developer 587 588 .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()` 589 @*/ 590 PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes)) 591 { 592 PetscFunctionBegin; 593 PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS); 594 othersetfromoptions[numberofsetfromoptions++] = snescheck; 595 PetscFunctionReturn(PETSC_SUCCESS); 596 } 597 598 static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version) 599 { 600 Mat J; 601 MatNullSpace nullsp; 602 603 PetscFunctionBegin; 604 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 605 606 if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) { 607 Mat A = snes->jacobian, B = snes->jacobian_pre; 608 PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func)); 609 } 610 611 PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2"); 612 if (version == 1) { 613 PetscCall(MatCreateSNESMF(snes, &J)); 614 PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 615 PetscCall(MatSetFromOptions(J)); 616 /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */ 617 } else /* if (version == 2) */ { 618 PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first"); 619 #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16) 620 PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J)); 621 #else 622 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)"); 623 #endif 624 } 625 626 /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */ 627 if (snes->jacobian) { 628 PetscCall(MatGetNullSpace(snes->jacobian, &nullsp)); 629 if (nullsp) PetscCall(MatSetNullSpace(J, nullsp)); 630 } 631 632 PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version)); 633 if (hasOperator) { 634 /* This version replaces the user provided Jacobian matrix with a 635 matrix-free version but still employs the user-provided matrix used for computing the preconditioner. */ 636 PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 637 } else { 638 /* This version replaces both the user-provided Jacobian and the user- 639 provided preconditioner Jacobian with the default matrix-free version. */ 640 if (snes->npcside == PC_LEFT && snes->npc) { 641 if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL)); 642 } else { 643 KSP ksp; 644 PC pc; 645 PetscBool match; 646 647 PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL)); 648 /* Force no preconditioner */ 649 PetscCall(SNESGetKSP(snes, &ksp)); 650 PetscCall(KSPGetPC(ksp, &pc)); 651 PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, "")); 652 if (!match) { 653 PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n")); 654 PetscCall(PCSetType(pc, PCNONE)); 655 } 656 } 657 } 658 PetscCall(MatDestroy(&J)); 659 PetscFunctionReturn(PETSC_SUCCESS); 660 } 661 662 static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx) 663 { 664 SNES snes = (SNES)ctx; 665 Vec Xfine, Xfine_named = NULL, Xcoarse; 666 667 PetscFunctionBegin; 668 if (PetscLogPrintInfo) { 669 PetscInt finelevel, coarselevel, fineclevel, coarseclevel; 670 PetscCall(DMGetRefineLevel(dmfine, &finelevel)); 671 PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel)); 672 PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel)); 673 PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel)); 674 PetscCall(PetscInfo(dmfine, "Restricting SNES solution vector from level %" PetscInt_FMT "-%" PetscInt_FMT " to level %" PetscInt_FMT "-%" PetscInt_FMT "\n", finelevel, fineclevel, coarselevel, coarseclevel)); 675 } 676 if (dmfine == snes->dm) Xfine = snes->vec_sol; 677 else { 678 PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 679 Xfine = Xfine_named; 680 } 681 PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 682 if (Inject) { 683 PetscCall(MatRestrict(Inject, Xfine, Xcoarse)); 684 } else { 685 PetscCall(MatRestrict(Restrict, Xfine, Xcoarse)); 686 PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale)); 687 } 688 PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse)); 689 if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named)); 690 PetscFunctionReturn(PETSC_SUCCESS); 691 } 692 693 static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx) 694 { 695 PetscFunctionBegin; 696 PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx)); 697 PetscFunctionReturn(PETSC_SUCCESS); 698 } 699 700 /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can 701 * safely call SNESGetDM() in their residual evaluation routine. */ 702 static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx) 703 { 704 SNES snes = (SNES)ctx; 705 DMSNES sdm; 706 Vec X, Xnamed = NULL; 707 DM dmsave; 708 void *ctxsave; 709 SNESJacobianFn *jac = NULL; 710 711 PetscFunctionBegin; 712 dmsave = snes->dm; 713 PetscCall(KSPGetDM(ksp, &snes->dm)); 714 if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */ 715 else { 716 PetscBool has; 717 718 /* We are on a coarser level, this vec was initialized using a DM restrict hook */ 719 PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has)); 720 PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol"); 721 PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 722 X = Xnamed; 723 PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave)); 724 /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */ 725 if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL)); 726 } 727 728 /* Compute the operators */ 729 PetscCall(DMGetDMSNES(snes->dm, &sdm)); 730 if (Xnamed && sdm->ops->computefunction) { 731 /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian. 732 We make sure of this here. Disable affine shift since it is for the finest level */ 733 Vec F, saverhs = snes->vec_rhs; 734 735 snes->vec_rhs = NULL; 736 PetscCall(DMGetGlobalVector(snes->dm, &F)); 737 PetscCall(SNESComputeFunction(snes, X, F)); 738 PetscCall(DMRestoreGlobalVector(snes->dm, &F)); 739 snes->vec_rhs = saverhs; 740 snes->nfuncs--; /* Do not log coarser level evaluations */ 741 } 742 /* Make sure KSP DM has the Jacobian computation routine */ 743 if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm)); 744 PetscCall(SNESComputeJacobian(snes, X, A, B)); 745 746 /* Put the previous context back */ 747 if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave)); 748 749 if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed)); 750 snes->dm = dmsave; 751 PetscFunctionReturn(PETSC_SUCCESS); 752 } 753 754 /*@ 755 SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()` 756 757 Collective 758 759 Input Parameter: 760 . snes - `SNES` object to configure 761 762 Level: developer 763 764 Note: 765 If the matrices do not yet exist it attempts to create them based on options previously set for the `SNES` such as `-snes_mf` 766 767 Developer Note: 768 The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by 769 `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the 770 logic that handles the matrix-free case is desirable. 771 772 .seealso: [](ch_snes), `SNES`, `SNESSetUp()` 773 @*/ 774 PetscErrorCode SNESSetUpMatrices(SNES snes) 775 { 776 DM dm; 777 DMSNES sdm; 778 779 PetscFunctionBegin; 780 PetscCall(SNESGetDM(snes, &dm)); 781 PetscCall(DMGetDMSNES(dm, &sdm)); 782 if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) { 783 Mat J; 784 void *functx; 785 PetscCall(MatCreateSNESMF(snes, &J)); 786 PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 787 PetscCall(MatSetFromOptions(J)); 788 PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 789 PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL)); 790 PetscCall(MatDestroy(&J)); 791 } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) { 792 Mat J, B; 793 PetscCall(MatCreateSNESMF(snes, &J)); 794 PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix)); 795 PetscCall(MatSetFromOptions(J)); 796 PetscCall(DMCreateMatrix(snes->dm, &B)); 797 /* sdm->computejacobian was already set to reach here */ 798 PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL)); 799 PetscCall(MatDestroy(&J)); 800 PetscCall(MatDestroy(&B)); 801 } else if (!snes->jacobian_pre) { 802 PetscDS prob; 803 Mat J, B; 804 PetscBool hasPrec = PETSC_FALSE; 805 806 J = snes->jacobian; 807 PetscCall(DMGetDS(dm, &prob)); 808 if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec)); 809 if (J) PetscCall(PetscObjectReference((PetscObject)J)); 810 else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J)); 811 PetscCall(DMCreateMatrix(snes->dm, &B)); 812 PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL)); 813 PetscCall(MatDestroy(&J)); 814 PetscCall(MatDestroy(&B)); 815 } 816 { 817 KSP ksp; 818 PetscCall(SNESGetKSP(snes, &ksp)); 819 PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes)); 820 PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 821 } 822 PetscFunctionReturn(PETSC_SUCCESS); 823 } 824 825 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscMonitorPauseFinal_Internal(PetscInt, void *); 826 827 static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes) 828 { 829 PetscFunctionBegin; 830 if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS); 831 PetscCall(PetscMonitorPauseFinal_Internal(snes->numbermonitors, snes->monitorcontext)); 832 PetscFunctionReturn(PETSC_SUCCESS); 833 } 834 835 /*@C 836 SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 837 838 Collective 839 840 Input Parameters: 841 + snes - `SNES` object you wish to monitor 842 . name - the monitor type one is seeking 843 . help - message indicating what monitoring is done 844 . manual - manual page for the monitor 845 . monitor - the monitor function, this must use a `PetscViewerFormat` as its context 846 - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `SNES` or `PetscViewer` objects 847 848 Calling sequence of `monitor`: 849 + snes - the nonlinear solver context 850 . it - the current iteration 851 . r - the current function norm 852 - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 853 854 Calling sequence of `monitorsetup`: 855 + snes - the nonlinear solver context 856 - vf - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use 857 858 Options Database Key: 859 . -name - trigger the use of this monitor in `SNESSetFromOptions()` 860 861 Level: advanced 862 863 .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, 864 `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 865 `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, 866 `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 867 `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 868 `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 869 `PetscOptionsFList()`, `PetscOptionsEList()` 870 @*/ 871 PetscErrorCode SNESMonitorSetFromOptions(SNES snes, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(SNES snes, PetscInt it, PetscReal r, PetscViewerAndFormat *vf), PetscErrorCode (*monitorsetup)(SNES snes, PetscViewerAndFormat *vf)) 872 { 873 PetscViewer viewer; 874 PetscViewerFormat format; 875 PetscBool flg; 876 877 PetscFunctionBegin; 878 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg)); 879 if (flg) { 880 PetscViewerAndFormat *vf; 881 PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf)); 882 PetscCall(PetscViewerDestroy(&viewer)); 883 if (monitorsetup) PetscCall((*monitorsetup)(snes, vf)); 884 PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy)); 885 } 886 PetscFunctionReturn(PETSC_SUCCESS); 887 } 888 889 PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix) 890 { 891 const char *api = print_api ? "SNESKSPSetParametersEW" : NULL; 892 893 PetscFunctionBegin; 894 PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP"); 895 PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL)); 896 PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL)); 897 kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max); 898 PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL)); 899 PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL)); 900 PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL)); 901 PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL)); 902 PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL)); 903 PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL)); 904 PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL)); 905 PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL)); 906 PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL)); 907 PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL)); 908 PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL)); 909 PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL)); 910 PetscOptionsEnd(); 911 PetscFunctionReturn(PETSC_SUCCESS); 912 } 913 914 /*@ 915 SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options. 916 917 Collective 918 919 Input Parameter: 920 . snes - the `SNES` context 921 922 Options Database Keys: 923 + -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list 924 . -snes_rtol <rtol> - relative decrease in tolerance norm from initial 925 . -snes_atol <abstol> - absolute tolerance of residual norm 926 . -snes_stol <stol> - convergence tolerance in terms of the norm of the change in the solution between steps 927 . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence 928 . -snes_max_it <max_it> - maximum number of iterations 929 . -snes_max_funcs <max_funcs> - maximum number of function evaluations 930 . -snes_force_iteration <force> - force `SNESSolve()` to take at least one iteration 931 . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none 932 . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops 933 . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild) 934 . -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve() 935 . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild) 936 . -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve() 937 . -snes_convergence_test <default,skip,correct_pressure> - convergence test in nonlinear solver. default `SNESConvergedDefault()`. skip `SNESConvergedSkip()` means continue iterating until max_it or some other criterion is reached, saving expense of convergence test. correct_pressure `SNESConvergedCorrectPressure()` has special handling of a pressure null space. 938 . -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout 939 . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration 940 . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration 941 . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration 942 . -snes_monitor_lg_residualnorm - plots residual norm at each iteration 943 . -snes_monitor_lg_range - plots residual norm at each iteration 944 . -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends 945 . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing 946 . -snes_fd_color - use finite differences with coloring to compute Jacobian 947 . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each `KSP` iteration 948 . -snes_converged_reason - print the reason for convergence/divergence after each solve 949 . -npc_snes_type <type> - the `SNES` type to use as a nonlinear preconditioner 950 . -snes_test_jacobian <optional threshold> - compare the user provided Jacobian with one computed via finite differences to check for errors. If a threshold is given, display only those entries whose difference is greater than the threshold. 951 - -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference between them to help users detect the location of errors in the user provided Jacobian. 952 953 Options Database Keys for Eisenstat-Walker method: 954 + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 955 . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 956 . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 957 . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 958 . -snes_ksp_ew_gamma <gamma> - Sets gamma 959 . -snes_ksp_ew_alpha <alpha> - Sets alpha 960 . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 961 - -snes_ksp_ew_threshold <threshold> - Sets threshold 962 963 Level: beginner 964 965 Notes: 966 To see all options, run your program with the -help option or consult the users manual 967 968 `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 969 and computing explicitly with 970 finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 971 972 .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring` 973 @*/ 974 PetscErrorCode SNESSetFromOptions(SNES snes) 975 { 976 PetscBool flg, pcset, persist, set; 977 PetscInt i, indx, lag, grids, max_its, max_funcs; 978 const char *deft = SNESNEWTONLS; 979 const char *convtests[] = {"default", "skip", "correct_pressure"}; 980 SNESKSPEW *kctx = NULL; 981 char type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256]; 982 PCSide pcside; 983 const char *optionsprefix; 984 PetscReal rtol, abstol, stol; 985 986 PetscFunctionBegin; 987 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 988 PetscCall(SNESRegisterAll()); 989 PetscObjectOptionsBegin((PetscObject)snes); 990 if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name; 991 PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg)); 992 if (flg) { 993 PetscCall(SNESSetType(snes, type)); 994 } else if (!((PetscObject)snes)->type_name) { 995 PetscCall(SNESSetType(snes, deft)); 996 } 997 998 abstol = snes->abstol; 999 rtol = snes->rtol; 1000 stol = snes->stol; 1001 max_its = snes->max_its; 1002 max_funcs = snes->max_funcs; 1003 PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL)); 1004 PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL)); 1005 PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL)); 1006 PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL)); 1007 PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL)); 1008 PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs)); 1009 1010 PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg)); 1011 if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol)); 1012 1013 PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg)); 1014 if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures)); 1015 1016 PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg)); 1017 if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures)); 1018 1019 PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL)); 1020 PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL)); 1021 PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL)); 1022 1023 PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg)); 1024 if (flg) { 1025 PetscCheck(lag != -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_USER, "Cannot set the lag to -1 from the command line since the preconditioner must be built as least once, perhaps you mean -2"); 1026 PetscCall(SNESSetLagPreconditioner(snes, lag)); 1027 } 1028 PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg)); 1029 if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist)); 1030 PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg)); 1031 if (flg) { 1032 PetscCheck(lag != -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_USER, "Cannot set the lag to -1 from the command line since the Jacobian must be built as least once, perhaps you mean -2"); 1033 PetscCall(SNESSetLagJacobian(snes, lag)); 1034 } 1035 PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg)); 1036 if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist)); 1037 1038 PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg)); 1039 if (flg) PetscCall(SNESSetGridSequence(snes, grids)); 1040 1041 PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg)); 1042 if (flg) { 1043 switch (indx) { 1044 case 0: 1045 PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL)); 1046 break; 1047 case 1: 1048 PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL)); 1049 break; 1050 case 2: 1051 PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL)); 1052 break; 1053 } 1054 } 1055 1056 PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg)); 1057 if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx)); 1058 1059 PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg)); 1060 if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx)); 1061 1062 kctx = (SNESKSPEW *)snes->kspconvctx; 1063 1064 PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL)); 1065 1066 PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 1067 PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_")); 1068 PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix)); 1069 1070 flg = PETSC_FALSE; 1071 PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set)); 1072 if (set && flg) PetscCall(SNESMonitorCancel(snes)); 1073 1074 PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp)); 1075 PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL)); 1076 PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL)); 1077 1078 PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp)); 1079 PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL)); 1080 PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL)); 1081 PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL)); 1082 PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL)); 1083 PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL)); 1084 PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL)); 1085 PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL)); 1086 1087 PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg)); 1088 if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename)); 1089 1090 flg = PETSC_FALSE; 1091 PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL)); 1092 if (flg) { 1093 PetscViewer ctx; 1094 1095 PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx)); 1096 PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscCtxDestroyFn *)PetscViewerDestroy)); 1097 } 1098 1099 PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 1100 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL)); 1101 flg = PETSC_FALSE; 1102 PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set)); 1103 if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes)); 1104 1105 flg = PETSC_FALSE; 1106 PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL)); 1107 if (flg) { 1108 void *functx; 1109 DM dm; 1110 PetscCall(SNESGetDM(snes, &dm)); 1111 PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 1112 PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 1113 PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx)); 1114 PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n")); 1115 } 1116 1117 flg = PETSC_FALSE; 1118 PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL)); 1119 if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL)); 1120 1121 flg = PETSC_FALSE; 1122 PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL)); 1123 if (flg) { 1124 DM dm; 1125 PetscCall(SNESGetDM(snes, &dm)); 1126 PetscCall(DMSNESUnsetJacobianContext_Internal(dm)); 1127 PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL)); 1128 PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n")); 1129 } 1130 1131 flg = PETSC_FALSE; 1132 PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg)); 1133 if (flg && snes->mf_operator) { 1134 snes->mf_operator = PETSC_TRUE; 1135 snes->mf = PETSC_TRUE; 1136 } 1137 flg = PETSC_FALSE; 1138 PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg)); 1139 if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE; 1140 PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL)); 1141 1142 PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference functions", "None", &snes->testFunc)); 1143 PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &snes->testJac)); 1144 1145 flg = PETSC_FALSE; 1146 PetscCall(SNESGetNPCSide(snes, &pcside)); 1147 PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg)); 1148 if (flg) PetscCall(SNESSetNPCSide(snes, pcside)); 1149 1150 #if defined(PETSC_HAVE_SAWS) 1151 /* 1152 Publish convergence information using SAWs 1153 */ 1154 flg = PETSC_FALSE; 1155 PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL)); 1156 if (flg) { 1157 void *ctx; 1158 PetscCall(SNESMonitorSAWsCreate(snes, &ctx)); 1159 PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy)); 1160 } 1161 #endif 1162 #if defined(PETSC_HAVE_SAWS) 1163 { 1164 PetscBool set; 1165 flg = PETSC_FALSE; 1166 PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set)); 1167 if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg)); 1168 } 1169 #endif 1170 1171 for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes)); 1172 1173 PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject); 1174 1175 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 1176 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject)); 1177 PetscOptionsEnd(); 1178 1179 if (snes->linesearch) { 1180 PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 1181 PetscCall(SNESLineSearchSetFromOptions(snes->linesearch)); 1182 } 1183 1184 if (snes->usesksp) { 1185 if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 1186 PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre)); 1187 PetscCall(KSPSetFromOptions(snes->ksp)); 1188 } 1189 1190 /* if user has set the SNES NPC type via options database, create it. */ 1191 PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 1192 PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset)); 1193 if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc)); 1194 if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc)); 1195 snes->setfromoptionscalled++; 1196 PetscFunctionReturn(PETSC_SUCCESS); 1197 } 1198 1199 /*@ 1200 SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called 1201 1202 Collective 1203 1204 Input Parameter: 1205 . snes - the `SNES` context 1206 1207 Level: advanced 1208 1209 .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()` 1210 @*/ 1211 PetscErrorCode SNESResetFromOptions(SNES snes) 1212 { 1213 PetscFunctionBegin; 1214 if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes)); 1215 PetscFunctionReturn(PETSC_SUCCESS); 1216 } 1217 1218 /*@C 1219 SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for 1220 the nonlinear solvers. 1221 1222 Logically Collective; No Fortran Support 1223 1224 Input Parameters: 1225 + snes - the `SNES` context 1226 . compute - function to compute the context 1227 - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence 1228 1229 Calling sequence of `compute`: 1230 + snes - the `SNES` context 1231 - ctx - context to be computed 1232 1233 Level: intermediate 1234 1235 Note: 1236 This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level. 1237 1238 Use `SNESSetApplicationContext()` to see the context immediately 1239 1240 .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn` 1241 @*/ 1242 PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy) 1243 { 1244 PetscFunctionBegin; 1245 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1246 snes->ops->usercompute = compute; 1247 snes->ops->ctxdestroy = destroy; 1248 PetscFunctionReturn(PETSC_SUCCESS); 1249 } 1250 1251 /*@ 1252 SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers. 1253 1254 Logically Collective 1255 1256 Input Parameters: 1257 + snes - the `SNES` context 1258 - ctx - the user context 1259 1260 Level: intermediate 1261 1262 Notes: 1263 Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function 1264 with `SNESGetApplicationContext()` 1265 1266 To provide a function that computes the context for you use `SNESSetComputeApplicationContext()` 1267 1268 Fortran Note: 1269 This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this 1270 function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for 1271 an example. 1272 1273 .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()` 1274 @*/ 1275 PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx) 1276 { 1277 KSP ksp; 1278 1279 PetscFunctionBegin; 1280 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1281 PetscCall(SNESGetKSP(snes, &ksp)); 1282 PetscCall(KSPSetApplicationContext(ksp, ctx)); 1283 snes->ctx = ctx; 1284 PetscFunctionReturn(PETSC_SUCCESS); 1285 } 1286 1287 /*@ 1288 SNESGetApplicationContext - Gets the user-defined context for the 1289 nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()` 1290 1291 Not Collective 1292 1293 Input Parameter: 1294 . snes - `SNES` context 1295 1296 Output Parameter: 1297 . ctx - user context 1298 1299 Level: intermediate 1300 1301 Fortran Notes: 1302 This only works when the context is a Fortran derived type (it cannot be a `PetscObject`) and you **must** write a Fortran interface definition for this 1303 function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example, 1304 .vb 1305 Interface SNESGetApplicationContext 1306 Subroutine SNESGetApplicationContext(snes,ctx,ierr) 1307 #include <petsc/finclude/petscsnes.h> 1308 use petscsnes 1309 SNES snes 1310 type(tUsertype), pointer :: ctx 1311 PetscErrorCode ierr 1312 End Subroutine 1313 End Interface SNESGetApplicationContext 1314 .ve 1315 1316 The prototype for `ctx` must be 1317 .vb 1318 type(tUsertype), pointer :: ctx 1319 .ve 1320 1321 .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()` 1322 @*/ 1323 PetscErrorCode SNESGetApplicationContext(SNES snes, PeCtx ctx) 1324 { 1325 PetscFunctionBegin; 1326 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1327 *(void **)ctx = snes->ctx; 1328 PetscFunctionReturn(PETSC_SUCCESS); 1329 } 1330 1331 /*@ 1332 SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian. 1333 1334 Logically Collective 1335 1336 Input Parameters: 1337 + snes - `SNES` context 1338 . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1339 - mf - use matrix-free for both the Amat and Pmat used by `SNESSetJacobian()`, both the Amat and Pmat set in `SNESSetJacobian()` will be ignored. With 1340 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available 1341 1342 Options Database Keys: 1343 + -snes_mf_operator - use matrix-free only for the mat operator 1344 . -snes_mf - use matrix-free for both the mat and pmat operator 1345 . -snes_fd_color - compute the Jacobian via coloring and finite differences. 1346 - -snes_fd - compute the Jacobian via finite differences (slow) 1347 1348 Level: intermediate 1349 1350 Note: 1351 `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`, 1352 and computing explicitly with 1353 finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object. 1354 1355 .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring` 1356 @*/ 1357 PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf) 1358 { 1359 PetscFunctionBegin; 1360 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1361 PetscValidLogicalCollectiveBool(snes, mf_operator, 2); 1362 PetscValidLogicalCollectiveBool(snes, mf, 3); 1363 snes->mf = mf_operator ? PETSC_TRUE : mf; 1364 snes->mf_operator = mf_operator; 1365 PetscFunctionReturn(PETSC_SUCCESS); 1366 } 1367 1368 /*@ 1369 SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian. 1370 1371 Not Collective, but the resulting flags will be the same on all MPI processes 1372 1373 Input Parameter: 1374 . snes - `SNES` context 1375 1376 Output Parameters: 1377 + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used 1378 - mf - use matrix-free for both the Amat and Pmat used by `SNESSetJacobian()`, both the Amat and Pmat set in `SNESSetJacobian()` will be ignored 1379 1380 Level: intermediate 1381 1382 .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()` 1383 @*/ 1384 PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf) 1385 { 1386 PetscFunctionBegin; 1387 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1388 if (mf) *mf = snes->mf; 1389 if (mf_operator) *mf_operator = snes->mf_operator; 1390 PetscFunctionReturn(PETSC_SUCCESS); 1391 } 1392 1393 /*@ 1394 SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()` 1395 1396 Not Collective 1397 1398 Input Parameter: 1399 . snes - `SNES` context 1400 1401 Output Parameter: 1402 . iter - iteration number 1403 1404 Level: intermediate 1405 1406 Notes: 1407 For example, during the computation of iteration 2 this would return 1. 1408 1409 This is useful for using lagged Jacobians (where one does not recompute the 1410 Jacobian at each `SNES` iteration). For example, the code 1411 .vb 1412 ierr = SNESGetIterationNumber(snes,&it); 1413 if (!(it % 2)) { 1414 [compute Jacobian here] 1415 } 1416 .ve 1417 can be used in your function that computes the Jacobian to cause the Jacobian to be 1418 recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()` 1419 1420 After the `SNES` solve is complete this will return the number of nonlinear iterations used. 1421 1422 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()` 1423 @*/ 1424 PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter) 1425 { 1426 PetscFunctionBegin; 1427 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1428 PetscAssertPointer(iter, 2); 1429 *iter = snes->iter; 1430 PetscFunctionReturn(PETSC_SUCCESS); 1431 } 1432 1433 /*@ 1434 SNESSetIterationNumber - Sets the current iteration number. 1435 1436 Not Collective 1437 1438 Input Parameters: 1439 + snes - `SNES` context 1440 - iter - iteration number 1441 1442 Level: developer 1443 1444 Note: 1445 This should only be called inside a `SNES` nonlinear solver. 1446 1447 .seealso: [](ch_snes), `SNESGetLinearSolveIterations()` 1448 @*/ 1449 PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter) 1450 { 1451 PetscFunctionBegin; 1452 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1453 PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes)); 1454 snes->iter = iter; 1455 PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes)); 1456 PetscFunctionReturn(PETSC_SUCCESS); 1457 } 1458 1459 /*@ 1460 SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps 1461 attempted by the nonlinear solver in the current or most recent `SNESSolve()` . 1462 1463 Not Collective 1464 1465 Input Parameter: 1466 . snes - `SNES` context 1467 1468 Output Parameter: 1469 . nfails - number of unsuccessful steps attempted 1470 1471 Level: intermediate 1472 1473 Note: 1474 This counter is reset to zero for each successive call to `SNESSolve()`. 1475 1476 .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1477 `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()` 1478 @*/ 1479 PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails) 1480 { 1481 PetscFunctionBegin; 1482 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1483 PetscAssertPointer(nfails, 2); 1484 *nfails = snes->numFailures; 1485 PetscFunctionReturn(PETSC_SUCCESS); 1486 } 1487 1488 /*@ 1489 SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps 1490 attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 1491 1492 Not Collective 1493 1494 Input Parameters: 1495 + snes - `SNES` context 1496 - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures 1497 1498 Options Database Key: 1499 . -snes_max_fail <n> - maximum number of unsuccessful steps allowed 1500 1501 Level: intermediate 1502 1503 Developer Note: 1504 The options database key is wrong for this function name 1505 1506 .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1507 `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 1508 @*/ 1509 PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails) 1510 { 1511 PetscFunctionBegin; 1512 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1513 1514 if (maxFails == PETSC_UNLIMITED) { 1515 snes->maxFailures = PETSC_INT_MAX; 1516 } else { 1517 PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 1518 snes->maxFailures = maxFails; 1519 } 1520 PetscFunctionReturn(PETSC_SUCCESS); 1521 } 1522 1523 /*@ 1524 SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps 1525 attempted by the nonlinear solver before it gives up and returns unconverged or generates an error 1526 1527 Not Collective 1528 1529 Input Parameter: 1530 . snes - `SNES` context 1531 1532 Output Parameter: 1533 . maxFails - maximum of unsuccessful steps 1534 1535 Level: intermediate 1536 1537 .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, 1538 `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()` 1539 @*/ 1540 PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails) 1541 { 1542 PetscFunctionBegin; 1543 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1544 PetscAssertPointer(maxFails, 2); 1545 *maxFails = snes->maxFailures; 1546 PetscFunctionReturn(PETSC_SUCCESS); 1547 } 1548 1549 /*@ 1550 SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations 1551 done by the `SNES` object in the current or most recent `SNESSolve()` 1552 1553 Not Collective 1554 1555 Input Parameter: 1556 . snes - `SNES` context 1557 1558 Output Parameter: 1559 . nfuncs - number of evaluations 1560 1561 Level: intermediate 1562 1563 Note: 1564 Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used. 1565 1566 .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()` 1567 @*/ 1568 PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs) 1569 { 1570 PetscFunctionBegin; 1571 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1572 PetscAssertPointer(nfuncs, 2); 1573 *nfuncs = snes->nfuncs; 1574 PetscFunctionReturn(PETSC_SUCCESS); 1575 } 1576 1577 /*@ 1578 SNESGetLinearSolveFailures - Gets the number of failed (non-converged) 1579 linear solvers in the current or most recent `SNESSolve()` 1580 1581 Not Collective 1582 1583 Input Parameter: 1584 . snes - `SNES` context 1585 1586 Output Parameter: 1587 . nfails - number of failed solves 1588 1589 Options Database Key: 1590 . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 1591 1592 Level: intermediate 1593 1594 Note: 1595 This counter is reset to zero for each successive call to `SNESSolve()`. 1596 1597 .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()` 1598 @*/ 1599 PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails) 1600 { 1601 PetscFunctionBegin; 1602 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1603 PetscAssertPointer(nfails, 2); 1604 *nfails = snes->numLinearSolveFailures; 1605 PetscFunctionReturn(PETSC_SUCCESS); 1606 } 1607 1608 /*@ 1609 SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts 1610 allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE` 1611 1612 Logically Collective 1613 1614 Input Parameters: 1615 + snes - `SNES` context 1616 - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures 1617 1618 Options Database Key: 1619 . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 1620 1621 Level: intermediate 1622 1623 Note: 1624 By default this is 0; that is `SNES` returns on the first failed linear solve 1625 1626 Developer Note: 1627 The options database key is wrong for this function name 1628 1629 .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()` 1630 @*/ 1631 PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails) 1632 { 1633 PetscFunctionBegin; 1634 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1635 PetscValidLogicalCollectiveInt(snes, maxFails, 2); 1636 1637 if (maxFails == PETSC_UNLIMITED) { 1638 snes->maxLinearSolveFailures = PETSC_INT_MAX; 1639 } else { 1640 PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 1641 snes->maxLinearSolveFailures = maxFails; 1642 } 1643 PetscFunctionReturn(PETSC_SUCCESS); 1644 } 1645 1646 /*@ 1647 SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that 1648 are allowed before `SNES` returns as unsuccessful 1649 1650 Not Collective 1651 1652 Input Parameter: 1653 . snes - `SNES` context 1654 1655 Output Parameter: 1656 . maxFails - maximum of unsuccessful solves allowed 1657 1658 Level: intermediate 1659 1660 Note: 1661 By default this is 1; that is `SNES` returns on the first failed linear solve 1662 1663 .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, 1664 @*/ 1665 PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails) 1666 { 1667 PetscFunctionBegin; 1668 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1669 PetscAssertPointer(maxFails, 2); 1670 *maxFails = snes->maxLinearSolveFailures; 1671 PetscFunctionReturn(PETSC_SUCCESS); 1672 } 1673 1674 /*@ 1675 SNESGetLinearSolveIterations - Gets the total number of linear iterations 1676 used by the nonlinear solver in the most recent `SNESSolve()` 1677 1678 Not Collective 1679 1680 Input Parameter: 1681 . snes - `SNES` context 1682 1683 Output Parameter: 1684 . lits - number of linear iterations 1685 1686 Level: intermediate 1687 1688 Notes: 1689 This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used. 1690 1691 If the linear solver fails inside the `SNESSolve()` the iterations for that call to the linear solver are not included. If you wish to count them 1692 then call `KSPGetIterationNumber()` after the failed solve. 1693 1694 .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()` 1695 @*/ 1696 PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits) 1697 { 1698 PetscFunctionBegin; 1699 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1700 PetscAssertPointer(lits, 2); 1701 *lits = snes->linear_its; 1702 PetscFunctionReturn(PETSC_SUCCESS); 1703 } 1704 1705 /*@ 1706 SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations 1707 are reset every time `SNESSolve()` is called. 1708 1709 Logically Collective 1710 1711 Input Parameters: 1712 + snes - `SNES` context 1713 - reset - whether to reset the counters or not, defaults to `PETSC_TRUE` 1714 1715 Level: developer 1716 1717 .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 1718 @*/ 1719 PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset) 1720 { 1721 PetscFunctionBegin; 1722 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1723 PetscValidLogicalCollectiveBool(snes, reset, 2); 1724 snes->counters_reset = reset; 1725 PetscFunctionReturn(PETSC_SUCCESS); 1726 } 1727 1728 /*@ 1729 SNESResetCounters - Reset counters for linear iterations and function evaluations. 1730 1731 Logically Collective 1732 1733 Input Parameters: 1734 . snes - `SNES` context 1735 1736 Level: developer 1737 1738 Note: 1739 It honors the flag set with `SNESSetCountersReset()` 1740 1741 .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()` 1742 @*/ 1743 PetscErrorCode SNESResetCounters(SNES snes) 1744 { 1745 PetscFunctionBegin; 1746 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1747 if (snes->counters_reset) { 1748 snes->nfuncs = 0; 1749 snes->linear_its = 0; 1750 snes->numFailures = 0; 1751 } 1752 PetscFunctionReturn(PETSC_SUCCESS); 1753 } 1754 1755 /*@ 1756 SNESSetKSP - Sets a `KSP` context for the `SNES` object to use 1757 1758 Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm` 1759 1760 Input Parameters: 1761 + snes - the `SNES` context 1762 - ksp - the `KSP` context 1763 1764 Level: developer 1765 1766 Notes: 1767 The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()` 1768 so this routine is rarely needed. 1769 1770 The `KSP` object that is already in the `SNES` object has its reference count 1771 decreased by one when this is called. 1772 1773 .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()` 1774 @*/ 1775 PetscErrorCode SNESSetKSP(SNES snes, KSP ksp) 1776 { 1777 PetscFunctionBegin; 1778 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1779 PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2); 1780 PetscCheckSameComm(snes, 1, ksp, 2); 1781 PetscCall(PetscObjectReference((PetscObject)ksp)); 1782 if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp)); 1783 snes->ksp = ksp; 1784 PetscFunctionReturn(PETSC_SUCCESS); 1785 } 1786 1787 /*@ 1788 SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they 1789 currently contain default values 1790 1791 Collective 1792 1793 Input Parameter: 1794 . snes - the `SNES` object 1795 1796 Level: developer 1797 1798 Developer Note: 1799 This is called by all the `SNESCreate_XXX()` routines. 1800 1801 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`, 1802 `PetscObjectParameterSetDefault()` 1803 @*/ 1804 PetscErrorCode SNESParametersInitialize(SNES snes) 1805 { 1806 PetscObjectParameterSetDefault(snes, max_its, 50); 1807 PetscObjectParameterSetDefault(snes, max_funcs, 10000); 1808 PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 1809 PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50); 1810 PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8); 1811 PetscObjectParameterSetDefault(snes, divtol, 1.e4); 1812 return PETSC_SUCCESS; 1813 } 1814 1815 /*@ 1816 SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves 1817 1818 Collective 1819 1820 Input Parameter: 1821 . comm - MPI communicator 1822 1823 Output Parameter: 1824 . outsnes - the new `SNES` context 1825 1826 Options Database Keys: 1827 + -snes_mf - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner 1828 . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()` 1829 . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring 1830 - -snes_fd - Uses (slow!) finite differences to compute Jacobian 1831 1832 Level: beginner 1833 1834 Developer Notes: 1835 `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is 1836 unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the 1837 particular method does use `KSP` and regulates if the information about the `KSP` is printed 1838 in `SNESView()`. 1839 1840 `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused 1841 by help messages about meaningless `SNES` options. 1842 1843 `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed. 1844 1845 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 1846 @*/ 1847 PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes) 1848 { 1849 SNES snes; 1850 SNESKSPEW *kctx; 1851 1852 PetscFunctionBegin; 1853 PetscAssertPointer(outsnes, 2); 1854 PetscCall(SNESInitializePackage()); 1855 1856 PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView)); 1857 snes->ops->converged = SNESConvergedDefault; 1858 snes->usesksp = PETSC_TRUE; 1859 snes->norm = 0.0; 1860 snes->xnorm = 0.0; 1861 snes->ynorm = 0.0; 1862 snes->normschedule = SNES_NORM_ALWAYS; 1863 snes->functype = SNES_FUNCTION_DEFAULT; 1864 snes->ttol = 0.0; 1865 1866 snes->rnorm0 = 0; 1867 snes->nfuncs = 0; 1868 snes->numFailures = 0; 1869 snes->maxFailures = 1; 1870 snes->linear_its = 0; 1871 snes->lagjacobian = 1; 1872 snes->jac_iter = 0; 1873 snes->lagjac_persist = PETSC_FALSE; 1874 snes->lagpreconditioner = 1; 1875 snes->pre_iter = 0; 1876 snes->lagpre_persist = PETSC_FALSE; 1877 snes->numbermonitors = 0; 1878 snes->numberreasonviews = 0; 1879 snes->data = NULL; 1880 snes->setupcalled = PETSC_FALSE; 1881 snes->ksp_ewconv = PETSC_FALSE; 1882 snes->nwork = 0; 1883 snes->work = NULL; 1884 snes->nvwork = 0; 1885 snes->vwork = NULL; 1886 snes->conv_hist_len = 0; 1887 snes->conv_hist_max = 0; 1888 snes->conv_hist = NULL; 1889 snes->conv_hist_its = NULL; 1890 snes->conv_hist_reset = PETSC_TRUE; 1891 snes->counters_reset = PETSC_TRUE; 1892 snes->vec_func_init_set = PETSC_FALSE; 1893 snes->reason = SNES_CONVERGED_ITERATING; 1894 snes->npcside = PC_RIGHT; 1895 snes->setfromoptionscalled = 0; 1896 1897 snes->mf = PETSC_FALSE; 1898 snes->mf_operator = PETSC_FALSE; 1899 snes->mf_version = 1; 1900 1901 snes->numLinearSolveFailures = 0; 1902 snes->maxLinearSolveFailures = 1; 1903 1904 snes->vizerotolerance = 1.e-8; 1905 snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE; 1906 1907 /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */ 1908 snes->alwayscomputesfinalresidual = PETSC_FALSE; 1909 1910 /* Create context to compute Eisenstat-Walker relative tolerance for KSP */ 1911 PetscCall(PetscNew(&kctx)); 1912 1913 snes->kspconvctx = kctx; 1914 kctx->version = 2; 1915 kctx->rtol_0 = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but 1916 this was too large for some test cases */ 1917 kctx->rtol_last = 0.0; 1918 kctx->rtol_max = 0.9; 1919 kctx->gamma = 1.0; 1920 kctx->alpha = 0.5 * (1.0 + PetscSqrtReal(5.0)); 1921 kctx->alpha2 = kctx->alpha; 1922 kctx->threshold = 0.1; 1923 kctx->lresid_last = 0.0; 1924 kctx->norm_last = 0.0; 1925 1926 kctx->rk_last = 0.0; 1927 kctx->rk_last_2 = 0.0; 1928 kctx->rtol_last_2 = 0.0; 1929 kctx->v4_p1 = 0.1; 1930 kctx->v4_p2 = 0.4; 1931 kctx->v4_p3 = 0.7; 1932 kctx->v4_m1 = 0.8; 1933 kctx->v4_m2 = 0.5; 1934 kctx->v4_m3 = 0.1; 1935 kctx->v4_m4 = 0.5; 1936 1937 PetscCall(SNESParametersInitialize(snes)); 1938 *outsnes = snes; 1939 PetscFunctionReturn(PETSC_SUCCESS); 1940 } 1941 1942 /*@C 1943 SNESSetFunction - Sets the function evaluation routine and function 1944 vector for use by the `SNES` routines in solving systems of nonlinear 1945 equations. 1946 1947 Logically Collective 1948 1949 Input Parameters: 1950 + snes - the `SNES` context 1951 . r - vector to store function values, may be `NULL` 1952 . f - function evaluation routine; for calling sequence see `SNESFunctionFn` 1953 - ctx - [optional] user-defined context for private data for the 1954 function evaluation routine (may be `NULL`) 1955 1956 Level: beginner 1957 1958 .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn` 1959 @*/ 1960 PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx) 1961 { 1962 DM dm; 1963 1964 PetscFunctionBegin; 1965 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1966 if (r) { 1967 PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1968 PetscCheckSameComm(snes, 1, r, 2); 1969 PetscCall(PetscObjectReference((PetscObject)r)); 1970 PetscCall(VecDestroy(&snes->vec_func)); 1971 snes->vec_func = r; 1972 } 1973 PetscCall(SNESGetDM(snes, &dm)); 1974 PetscCall(DMSNESSetFunction(dm, f, ctx)); 1975 if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 1976 PetscFunctionReturn(PETSC_SUCCESS); 1977 } 1978 1979 /*@C 1980 SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`. 1981 1982 Logically Collective 1983 1984 Input Parameters: 1985 + snes - the `SNES` context 1986 - f - vector to store function value 1987 1988 Level: developer 1989 1990 Notes: 1991 This should not be modified during the solution procedure. 1992 1993 This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning. 1994 1995 .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()` 1996 @*/ 1997 PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f) 1998 { 1999 Vec vec_func; 2000 2001 PetscFunctionBegin; 2002 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2003 PetscValidHeaderSpecific(f, VEC_CLASSID, 2); 2004 PetscCheckSameComm(snes, 1, f, 2); 2005 if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 2006 snes->vec_func_init_set = PETSC_FALSE; 2007 PetscFunctionReturn(PETSC_SUCCESS); 2008 } 2009 PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL)); 2010 PetscCall(VecCopy(f, vec_func)); 2011 2012 snes->vec_func_init_set = PETSC_TRUE; 2013 PetscFunctionReturn(PETSC_SUCCESS); 2014 } 2015 2016 /*@ 2017 SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring 2018 of the `SNES` method, when norms are computed in the solving process 2019 2020 Logically Collective 2021 2022 Input Parameters: 2023 + snes - the `SNES` context 2024 - normschedule - the frequency of norm computation 2025 2026 Options Database Key: 2027 . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule 2028 2029 Level: advanced 2030 2031 Notes: 2032 Only certain `SNES` methods support certain `SNESNormSchedules`. Most require evaluation 2033 of the nonlinear function and the taking of its norm at every iteration to 2034 even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 2035 `SNESNGS` and the like do not require the norm of the function to be computed, and therefore 2036 may either be monitored for convergence or not. As these are often used as nonlinear 2037 preconditioners, monitoring the norm of their error is not a useful enterprise within 2038 their solution. 2039 2040 .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()` 2041 @*/ 2042 PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule) 2043 { 2044 PetscFunctionBegin; 2045 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2046 snes->normschedule = normschedule; 2047 PetscFunctionReturn(PETSC_SUCCESS); 2048 } 2049 2050 /*@ 2051 SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring 2052 of the `SNES` method. 2053 2054 Logically Collective 2055 2056 Input Parameters: 2057 + snes - the `SNES` context 2058 - normschedule - the type of the norm used 2059 2060 Level: advanced 2061 2062 .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2063 @*/ 2064 PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule) 2065 { 2066 PetscFunctionBegin; 2067 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2068 *normschedule = snes->normschedule; 2069 PetscFunctionReturn(PETSC_SUCCESS); 2070 } 2071 2072 /*@ 2073 SNESSetFunctionNorm - Sets the last computed residual norm. 2074 2075 Logically Collective 2076 2077 Input Parameters: 2078 + snes - the `SNES` context 2079 - norm - the value of the norm 2080 2081 Level: developer 2082 2083 .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2084 @*/ 2085 PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm) 2086 { 2087 PetscFunctionBegin; 2088 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2089 snes->norm = norm; 2090 PetscFunctionReturn(PETSC_SUCCESS); 2091 } 2092 2093 /*@ 2094 SNESGetFunctionNorm - Gets the last computed norm of the residual 2095 2096 Not Collective 2097 2098 Input Parameter: 2099 . snes - the `SNES` context 2100 2101 Output Parameter: 2102 . norm - the last computed residual norm 2103 2104 Level: developer 2105 2106 .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2107 @*/ 2108 PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm) 2109 { 2110 PetscFunctionBegin; 2111 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2112 PetscAssertPointer(norm, 2); 2113 *norm = snes->norm; 2114 PetscFunctionReturn(PETSC_SUCCESS); 2115 } 2116 2117 /*@ 2118 SNESGetUpdateNorm - Gets the last computed norm of the solution update 2119 2120 Not Collective 2121 2122 Input Parameter: 2123 . snes - the `SNES` context 2124 2125 Output Parameter: 2126 . ynorm - the last computed update norm 2127 2128 Level: developer 2129 2130 Note: 2131 The new solution is the current solution plus the update, so this norm is an indication of the size of the update 2132 2133 .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()` 2134 @*/ 2135 PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm) 2136 { 2137 PetscFunctionBegin; 2138 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2139 PetscAssertPointer(ynorm, 2); 2140 *ynorm = snes->ynorm; 2141 PetscFunctionReturn(PETSC_SUCCESS); 2142 } 2143 2144 /*@ 2145 SNESGetSolutionNorm - Gets the last computed norm of the solution 2146 2147 Not Collective 2148 2149 Input Parameter: 2150 . snes - the `SNES` context 2151 2152 Output Parameter: 2153 . xnorm - the last computed solution norm 2154 2155 Level: developer 2156 2157 .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()` 2158 @*/ 2159 PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm) 2160 { 2161 PetscFunctionBegin; 2162 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2163 PetscAssertPointer(xnorm, 2); 2164 *xnorm = snes->xnorm; 2165 PetscFunctionReturn(PETSC_SUCCESS); 2166 } 2167 2168 /*@ 2169 SNESSetFunctionType - Sets the `SNESFunctionType` 2170 of the `SNES` method. 2171 2172 Logically Collective 2173 2174 Input Parameters: 2175 + snes - the `SNES` context 2176 - type - the function type 2177 2178 Level: developer 2179 2180 Values of the function type\: 2181 + `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType` 2182 . `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()` 2183 - `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()` 2184 2185 Note: 2186 Different `SNESType`s use this value in different ways 2187 2188 .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2189 @*/ 2190 PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type) 2191 { 2192 PetscFunctionBegin; 2193 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2194 snes->functype = type; 2195 PetscFunctionReturn(PETSC_SUCCESS); 2196 } 2197 2198 /*@ 2199 SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()` 2200 of the SNES method. 2201 2202 Logically Collective 2203 2204 Input Parameters: 2205 + snes - the `SNES` context 2206 - type - the type of the function evaluation, see `SNESSetFunctionType()` 2207 2208 Level: advanced 2209 2210 .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule` 2211 @*/ 2212 PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type) 2213 { 2214 PetscFunctionBegin; 2215 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2216 *type = snes->functype; 2217 PetscFunctionReturn(PETSC_SUCCESS); 2218 } 2219 2220 /*@C 2221 SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for 2222 use with composed nonlinear solvers. 2223 2224 Input Parameters: 2225 + snes - the `SNES` context, usually of the `SNESType` `SNESNGS` 2226 . f - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence 2227 - ctx - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`) 2228 2229 Level: intermediate 2230 2231 Note: 2232 The `SNESNGS` routines are used by the composed nonlinear solver to generate 2233 a problem appropriate update to the solution, particularly `SNESFAS`. 2234 2235 .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn` 2236 @*/ 2237 PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx) 2238 { 2239 DM dm; 2240 2241 PetscFunctionBegin; 2242 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2243 PetscCall(SNESGetDM(snes, &dm)); 2244 PetscCall(DMSNESSetNGS(dm, f, ctx)); 2245 PetscFunctionReturn(PETSC_SUCCESS); 2246 } 2247 2248 /* 2249 This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be 2250 changed during the KSPSolve() 2251 */ 2252 PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx) 2253 { 2254 DM dm; 2255 DMSNES sdm; 2256 2257 PetscFunctionBegin; 2258 PetscCall(SNESGetDM(snes, &dm)); 2259 PetscCall(DMGetDMSNES(dm, &sdm)); 2260 /* A(x)*x - b(x) */ 2261 if (sdm->ops->computepfunction) { 2262 PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 2263 PetscCall(VecScale(f, -1.0)); 2264 /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */ 2265 if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard)); 2266 PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 2267 PetscCall(MatMultAdd(snes->picard, x, f, f)); 2268 } else { 2269 PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx)); 2270 PetscCall(MatMult(snes->picard, x, f)); 2271 } 2272 PetscFunctionReturn(PETSC_SUCCESS); 2273 } 2274 2275 PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx) 2276 { 2277 DM dm; 2278 DMSNES sdm; 2279 2280 PetscFunctionBegin; 2281 PetscCall(SNESGetDM(snes, &dm)); 2282 PetscCall(DMGetDMSNES(dm, &sdm)); 2283 /* A(x)*x - b(x) */ 2284 if (sdm->ops->computepfunction) { 2285 PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx)); 2286 PetscCall(VecScale(f, -1.0)); 2287 PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 2288 PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f)); 2289 } else { 2290 PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx)); 2291 PetscCall(MatMult(snes->jacobian_pre, x, f)); 2292 } 2293 PetscFunctionReturn(PETSC_SUCCESS); 2294 } 2295 2296 PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx) 2297 { 2298 PetscFunctionBegin; 2299 /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2300 /* must assembly if matrix-free to get the last SNES solution */ 2301 PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 2302 PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 2303 PetscFunctionReturn(PETSC_SUCCESS); 2304 } 2305 2306 /*@C 2307 SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization) 2308 2309 Logically Collective 2310 2311 Input Parameters: 2312 + snes - the `SNES` context 2313 . r - vector to store function values, may be `NULL` 2314 . bp - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn` 2315 . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed 2316 . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`) 2317 . J - function to compute matrix values, for the calling sequence see `SNESJacobianFn` 2318 - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 2319 2320 Level: intermediate 2321 2322 Notes: 2323 It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use 2324 an approximate Newton solver. This interface is provided to allow porting/testing a previous Picard based code in PETSc before converting it to approximate Newton. 2325 2326 One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both 2327 2328 Solves the equation $A(x) x = bp(x) - b$ via the defect correction algorithm $A(x^{n}) (x^{n+1} - x^{n}) = bp(x^{n}) + b - A(x^{n})x^{n}$. 2329 When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration. 2330 2331 Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner. 2332 2333 We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 2334 the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$ 2335 2336 There is some controversity over the definition of a Picard iteration for nonlinear systems but almost everyone agrees that it involves a linear solve and some 2337 believe it is the iteration $A(x^{n}) x^{n+1} = b(x^{n})$ hence we use the name Picard. If anyone has an authoritative reference that defines the Picard iteration 2338 different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-). 2339 2340 When used with `-snes_mf_operator` this will run matrix-free Newton's method where the matrix-vector product is of the true Jacobian of $A(x)x - bp(x) - b$ and 2341 $A(x^{n})$ is used to build the preconditioner 2342 2343 When used with `-snes_fd` this will compute the true Jacobian (very slowly one column at a time) and thus represent Newton's method. 2344 2345 When used with `-snes_fd_coloring` this will compute the Jacobian via coloring and thus represent a faster implementation of Newton's method. But the 2346 the nonzero structure of the Jacobian is, in general larger than that of the Picard matrix $A$ so you must provide in $A$ the needed nonzero structure for the correct 2347 coloring. When using `DMDA` this may mean creating the matrix $A$ with `DMCreateMatrix()` using a wider stencil than strictly needed for $A$ or with a `DMDA_STENCIL_BOX`. 2348 See the comment in src/snes/tutorials/ex15.c. 2349 2350 .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, 2351 `SNESFunctionFn`, `SNESJacobianFn` 2352 @*/ 2353 PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 2354 { 2355 DM dm; 2356 2357 PetscFunctionBegin; 2358 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2359 PetscCall(SNESGetDM(snes, &dm)); 2360 PetscCall(DMSNESSetPicard(dm, bp, J, ctx)); 2361 PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx)); 2362 PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx)); 2363 PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx)); 2364 PetscFunctionReturn(PETSC_SUCCESS); 2365 } 2366 2367 /*@C 2368 SNESGetPicard - Returns the context for the Picard iteration 2369 2370 Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet. 2371 2372 Input Parameter: 2373 . snes - the `SNES` context 2374 2375 Output Parameters: 2376 + r - the function (or `NULL`) 2377 . f - the function (or `NULL`); for calling sequence see `SNESFunctionFn` 2378 . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`) 2379 . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`) 2380 . J - the function for matrix evaluation (or `NULL`); for calling sequence see `SNESJacobianFn` 2381 - ctx - the function context (or `NULL`) 2382 2383 Level: advanced 2384 2385 .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn` 2386 @*/ 2387 PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 2388 { 2389 DM dm; 2390 2391 PetscFunctionBegin; 2392 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2393 PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 2394 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 2395 PetscCall(SNESGetDM(snes, &dm)); 2396 PetscCall(DMSNESGetPicard(dm, f, J, ctx)); 2397 PetscFunctionReturn(PETSC_SUCCESS); 2398 } 2399 2400 /*@C 2401 SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem 2402 2403 Logically Collective 2404 2405 Input Parameters: 2406 + snes - the `SNES` context 2407 . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence 2408 - ctx - [optional] user-defined context for private data for the 2409 function evaluation routine (may be `NULL`) 2410 2411 Level: intermediate 2412 2413 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn` 2414 @*/ 2415 PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx) 2416 { 2417 PetscFunctionBegin; 2418 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2419 if (func) snes->ops->computeinitialguess = func; 2420 if (ctx) snes->initialguessP = ctx; 2421 PetscFunctionReturn(PETSC_SUCCESS); 2422 } 2423 2424 /*@C 2425 SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set 2426 it assumes a zero right-hand side. 2427 2428 Logically Collective 2429 2430 Input Parameter: 2431 . snes - the `SNES` context 2432 2433 Output Parameter: 2434 . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector 2435 2436 Level: intermediate 2437 2438 .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()` 2439 @*/ 2440 PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs) 2441 { 2442 PetscFunctionBegin; 2443 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2444 PetscAssertPointer(rhs, 2); 2445 *rhs = snes->vec_rhs; 2446 PetscFunctionReturn(PETSC_SUCCESS); 2447 } 2448 2449 /*@ 2450 SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 2451 2452 Collective 2453 2454 Input Parameters: 2455 + snes - the `SNES` context 2456 - x - input vector 2457 2458 Output Parameter: 2459 . y - function vector, as set by `SNESSetFunction()` 2460 2461 Level: developer 2462 2463 Notes: 2464 `SNESComputeFunction()` is typically used within nonlinear solvers 2465 implementations, so users would not generally call this routine themselves. 2466 2467 When solving for $F(x) = b$, this routine computes $y = F(x) - b$. 2468 2469 .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()` 2470 @*/ 2471 PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y) 2472 { 2473 DM dm; 2474 DMSNES sdm; 2475 2476 PetscFunctionBegin; 2477 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2478 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2479 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2480 PetscCheckSameComm(snes, 1, x, 2); 2481 PetscCheckSameComm(snes, 1, y, 3); 2482 PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2483 2484 PetscCall(SNESGetDM(snes, &dm)); 2485 PetscCall(DMGetDMSNES(dm, &sdm)); 2486 PetscCheck(sdm->ops->computefunction || snes->vec_rhs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetFunction() or SNESSetDM() before SNESComputeFunction(), likely called from SNESSolve()."); 2487 if (sdm->ops->computefunction) { 2488 if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 2489 PetscCall(VecLockReadPush(x)); 2490 /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2491 snes->domainerror = PETSC_FALSE; 2492 { 2493 void *ctx; 2494 SNESFunctionFn *computefunction; 2495 PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx)); 2496 PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx)); 2497 } 2498 PetscCall(VecLockReadPop(x)); 2499 if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2500 } else /* if (snes->vec_rhs) */ { 2501 PetscCall(MatMult(snes->jacobian, x, y)); 2502 } 2503 if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs)); 2504 snes->nfuncs++; 2505 /* 2506 domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2507 propagate the value to all processes 2508 */ 2509 PetscCall(VecFlag(y, snes->domainerror)); 2510 PetscFunctionReturn(PETSC_SUCCESS); 2511 } 2512 2513 /*@ 2514 SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`. 2515 2516 Collective 2517 2518 Input Parameters: 2519 + snes - the `SNES` context 2520 - x - input vector 2521 2522 Output Parameter: 2523 . y - output vector 2524 2525 Level: developer 2526 2527 Notes: 2528 `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()` 2529 so users would not generally call this routine themselves. 2530 2531 Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()` 2532 while `SNESComputeFunction()` does. As such, this routine cannot be used with `MatMFFDSetBase()` with a provided F function value even if it applies the 2533 same function as `SNESComputeFunction()` if a `SNESSolve()` right-hand side vector is use because the two functions difference would include this right hand side function. 2534 2535 .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()` 2536 @*/ 2537 PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y) 2538 { 2539 DM dm; 2540 DMSNES sdm; 2541 2542 PetscFunctionBegin; 2543 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2544 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2545 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2546 PetscCheckSameComm(snes, 1, x, 2); 2547 PetscCheckSameComm(snes, 1, y, 3); 2548 PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2549 2550 PetscCall(SNESGetDM(snes, &dm)); 2551 PetscCall(DMGetDMSNES(dm, &sdm)); 2552 PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0)); 2553 PetscCall(VecLockReadPush(x)); 2554 /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */ 2555 snes->domainerror = PETSC_FALSE; 2556 PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx)); 2557 PetscCall(VecLockReadPop(x)); 2558 PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0)); 2559 snes->nfuncs++; 2560 /* 2561 domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2562 propagate the value to all processes 2563 */ 2564 PetscCall(VecFlag(y, snes->domainerror)); 2565 PetscFunctionReturn(PETSC_SUCCESS); 2566 } 2567 2568 /*@ 2569 SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2570 2571 Collective 2572 2573 Input Parameters: 2574 + snes - the `SNES` context 2575 . x - input vector 2576 - b - rhs vector 2577 2578 Output Parameter: 2579 . x - new solution vector 2580 2581 Level: developer 2582 2583 Note: 2584 `SNESComputeNGS()` is typically used within composed nonlinear solver 2585 implementations, so most users would not generally call this routine 2586 themselves. 2587 2588 .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS` 2589 @*/ 2590 PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x) 2591 { 2592 DM dm; 2593 DMSNES sdm; 2594 2595 PetscFunctionBegin; 2596 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2597 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 2598 if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 2599 PetscCheckSameComm(snes, 1, x, 3); 2600 if (b) PetscCheckSameComm(snes, 1, b, 2); 2601 if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE)); 2602 PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0)); 2603 PetscCall(SNESGetDM(snes, &dm)); 2604 PetscCall(DMGetDMSNES(dm, &sdm)); 2605 PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 2606 if (b) PetscCall(VecLockReadPush(b)); 2607 PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx)); 2608 if (b) PetscCall(VecLockReadPop(b)); 2609 PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0)); 2610 PetscFunctionReturn(PETSC_SUCCESS); 2611 } 2612 2613 static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G) 2614 { 2615 Vec X; 2616 PetscScalar *g; 2617 PetscReal f, f2; 2618 PetscInt low, high, N, i; 2619 PetscBool flg; 2620 PetscReal h = .5 * PETSC_SQRT_MACHINE_EPSILON; 2621 2622 PetscFunctionBegin; 2623 PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg)); 2624 PetscCall(VecDuplicate(Xin, &X)); 2625 PetscCall(VecCopy(Xin, X)); 2626 PetscCall(VecGetSize(X, &N)); 2627 PetscCall(VecGetOwnershipRange(X, &low, &high)); 2628 PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE)); 2629 PetscCall(VecGetArray(G, &g)); 2630 for (i = 0; i < N; i++) { 2631 PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2632 PetscCall(VecAssemblyBegin(X)); 2633 PetscCall(VecAssemblyEnd(X)); 2634 PetscCall(SNESComputeObjective(snes, X, &f)); 2635 PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES)); 2636 PetscCall(VecAssemblyBegin(X)); 2637 PetscCall(VecAssemblyEnd(X)); 2638 PetscCall(SNESComputeObjective(snes, X, &f2)); 2639 PetscCall(VecSetValue(X, i, -h, ADD_VALUES)); 2640 PetscCall(VecAssemblyBegin(X)); 2641 PetscCall(VecAssemblyEnd(X)); 2642 if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h); 2643 } 2644 PetscCall(VecRestoreArray(G, &g)); 2645 PetscCall(VecDestroy(&X)); 2646 PetscFunctionReturn(PETSC_SUCCESS); 2647 } 2648 2649 /*@ 2650 SNESTestFunction - Computes the difference between the computed and finite-difference functions 2651 2652 Collective 2653 2654 Input Parameter: 2655 . snes - the `SNES` context 2656 2657 Options Database Keys: 2658 + -snes_test_function - compare the user provided function with one compute via finite differences to check for errors. 2659 - -snes_test_function_view - display the user provided function, the finite difference function and the difference 2660 2661 Level: developer 2662 2663 .seealso: [](ch_snes), `SNESTestJacobian()`, `SNESSetFunction()`, `SNESComputeFunction()` 2664 @*/ 2665 PetscErrorCode SNESTestFunction(SNES snes) 2666 { 2667 Vec x, g1, g2, g3; 2668 PetscBool complete_print = PETSC_FALSE; 2669 PetscReal hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm; 2670 PetscScalar dot; 2671 MPI_Comm comm; 2672 PetscViewer viewer, mviewer; 2673 PetscViewerFormat format; 2674 PetscInt tabs; 2675 static PetscBool directionsprinted = PETSC_FALSE; 2676 SNESObjectiveFn *objective; 2677 2678 PetscFunctionBegin; 2679 PetscCall(SNESGetObjective(snes, &objective, NULL)); 2680 if (!objective) PetscFunctionReturn(PETSC_SUCCESS); 2681 2682 PetscObjectOptionsBegin((PetscObject)snes); 2683 PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print)); 2684 PetscOptionsEnd(); 2685 2686 PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2687 PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2688 PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2689 PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2690 PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Function -------------\n")); 2691 if (!complete_print && !directionsprinted) { 2692 PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n")); 2693 PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference function entries greater than <threshold>.\n")); 2694 } 2695 if (!directionsprinted) { 2696 PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n")); 2697 PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Function is probably correct.\n")); 2698 directionsprinted = PETSC_TRUE; 2699 } 2700 if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2701 2702 PetscCall(SNESGetSolution(snes, &x)); 2703 PetscCall(VecDuplicate(x, &g1)); 2704 PetscCall(VecDuplicate(x, &g2)); 2705 PetscCall(VecDuplicate(x, &g3)); 2706 PetscCall(SNESComputeFunction(snes, x, g1)); 2707 PetscCall(SNESComputeFunction_FD(snes, x, g2)); 2708 2709 PetscCall(VecNorm(g2, NORM_2, &fdnorm)); 2710 PetscCall(VecNorm(g1, NORM_2, &hcnorm)); 2711 PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax)); 2712 PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax)); 2713 PetscCall(VecDot(g1, g2, &dot)); 2714 PetscCall(VecCopy(g1, g3)); 2715 PetscCall(VecAXPY(g3, -1.0, g2)); 2716 PetscCall(VecNorm(g3, NORM_2, &diffnorm)); 2717 PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax)); 2718 PetscCall(PetscViewerASCIIPrintf(viewer, " ||Ffd|| %g, ||F|| = %g, angle cosine = (Ffd'F)/||Ffd||||F|| = %g\n", (double)fdnorm, (double)hcnorm, (double)(PetscRealPart(dot) / (fdnorm * hcnorm)))); 2719 PetscCall(PetscViewerASCIIPrintf(viewer, " 2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm)); 2720 PetscCall(PetscViewerASCIIPrintf(viewer, " max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax)); 2721 2722 if (complete_print) { 2723 PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded function ----------\n")); 2724 PetscCall(VecView(g1, mviewer)); 2725 PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference function ----------\n")); 2726 PetscCall(VecView(g2, mviewer)); 2727 PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference function ----------\n")); 2728 PetscCall(VecView(g3, mviewer)); 2729 } 2730 PetscCall(VecDestroy(&g1)); 2731 PetscCall(VecDestroy(&g2)); 2732 PetscCall(VecDestroy(&g3)); 2733 2734 if (complete_print) { 2735 PetscCall(PetscViewerPopFormat(mviewer)); 2736 PetscCall(PetscViewerDestroy(&mviewer)); 2737 } 2738 PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2739 PetscFunctionReturn(PETSC_SUCCESS); 2740 } 2741 2742 /*@ 2743 SNESTestJacobian - Computes the difference between the computed and finite-difference Jacobians 2744 2745 Collective 2746 2747 Input Parameter: 2748 . snes - the `SNES` context 2749 2750 Output Parameters: 2751 + Jnorm - the Frobenius norm of the computed Jacobian, or `NULL` 2752 - diffNorm - the Frobenius norm of the difference of the computed and finite-difference Jacobians, or `NULL` 2753 2754 Options Database Keys: 2755 + -snes_test_jacobian <optional threshold> - compare the user provided Jacobian with one compute via finite differences to check for errors. If a threshold is given, display only those entries whose difference is greater than the threshold. 2756 - -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference 2757 2758 Level: developer 2759 2760 Note: 2761 Directions and norms are printed to stdout if `diffNorm` is `NULL`. 2762 2763 .seealso: [](ch_snes), `SNESTestFunction()`, `SNESSetJacobian()`, `SNESComputeJacobian()` 2764 @*/ 2765 PetscErrorCode SNESTestJacobian(SNES snes, PetscReal *Jnorm, PetscReal *diffNorm) 2766 { 2767 Mat A, B, C, D, jacobian; 2768 Vec x = snes->vec_sol, f; 2769 PetscReal nrm, gnorm; 2770 PetscReal threshold = 1.e-5; 2771 MatType mattype; 2772 PetscInt m, n, M, N; 2773 void *functx; 2774 PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, flg, istranspose; 2775 PetscBool silent = diffNorm != PETSC_NULLPTR ? PETSC_TRUE : PETSC_FALSE; 2776 PetscViewer viewer, mviewer; 2777 MPI_Comm comm; 2778 PetscInt tabs; 2779 static PetscBool directionsprinted = PETSC_FALSE; 2780 PetscViewerFormat format; 2781 2782 PetscFunctionBegin; 2783 PetscObjectOptionsBegin((PetscObject)snes); 2784 PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 2785 PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 2786 PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 2787 PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 2788 PetscCall(PetscOptionsReal("-snes_test_jacobian_display_threshold", "Display difference between hand-coded and finite difference Jacobians which exceed input threshold", "None", threshold, &threshold, &threshold_print)); 2789 PetscOptionsEnd(); 2790 2791 PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2792 PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2793 PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2794 PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2795 if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 2796 if (!complete_print && !silent && !directionsprinted) { 2797 PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 2798 PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 2799 } 2800 if (!directionsprinted && !silent) { 2801 PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 2802 PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 2803 directionsprinted = PETSC_TRUE; 2804 } 2805 if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2806 2807 PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 2808 if (!flg) jacobian = snes->jacobian; 2809 else jacobian = snes->jacobian_pre; 2810 2811 if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL)); 2812 else PetscCall(PetscObjectReference((PetscObject)x)); 2813 PetscCall(VecDuplicate(x, &f)); 2814 2815 /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 2816 PetscCall(SNESComputeFunction(snes, x, f)); 2817 PetscCall(VecDestroy(&f)); 2818 PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 2819 while (jacobian) { 2820 Mat JT = NULL, Jsave = NULL; 2821 2822 if (istranspose) { 2823 PetscCall(MatCreateTranspose(jacobian, &JT)); 2824 Jsave = jacobian; 2825 jacobian = JT; 2826 } 2827 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 2828 if (flg) { 2829 A = jacobian; 2830 PetscCall(PetscObjectReference((PetscObject)A)); 2831 } else { 2832 PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 2833 } 2834 2835 PetscCall(MatGetType(A, &mattype)); 2836 PetscCall(MatGetSize(A, &M, &N)); 2837 PetscCall(MatGetLocalSize(A, &m, &n)); 2838 PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 2839 PetscCall(MatSetType(B, mattype)); 2840 PetscCall(MatSetSizes(B, m, n, M, N)); 2841 PetscCall(MatSetBlockSizesFromMats(B, A, A)); 2842 PetscCall(MatSetUp(B)); 2843 PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2844 2845 PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 2846 PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 2847 2848 PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 2849 PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 2850 PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 2851 PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 2852 PetscCall(MatDestroy(&D)); 2853 if (!gnorm) gnorm = 1; /* just in case */ 2854 if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 2855 if (complete_print) { 2856 PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 2857 PetscCall(MatView(A, mviewer)); 2858 PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 2859 PetscCall(MatView(B, mviewer)); 2860 } 2861 2862 if (threshold_print || complete_print) { 2863 PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2864 PetscScalar *cvals; 2865 const PetscInt *bcols; 2866 const PetscScalar *bvals; 2867 2868 PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 2869 PetscCall(MatSetType(C, mattype)); 2870 PetscCall(MatSetSizes(C, m, n, M, N)); 2871 PetscCall(MatSetBlockSizesFromMats(C, A, A)); 2872 PetscCall(MatSetUp(C)); 2873 PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2874 2875 PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 2876 PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2877 2878 for (row = Istart; row < Iend; row++) { 2879 PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 2880 PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2881 for (j = 0, cncols = 0; j < bncols; j++) { 2882 if (PetscAbsScalar(bvals[j]) > threshold) { 2883 ccols[cncols] = bcols[j]; 2884 cvals[cncols] = bvals[j]; 2885 cncols += 1; 2886 } 2887 } 2888 if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 2889 PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 2890 PetscCall(PetscFree2(ccols, cvals)); 2891 } 2892 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 2893 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 2894 PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 2895 PetscCall(MatView(C, complete_print ? mviewer : viewer)); 2896 PetscCall(MatDestroy(&C)); 2897 } 2898 PetscCall(MatDestroy(&A)); 2899 PetscCall(MatDestroy(&B)); 2900 PetscCall(MatDestroy(&JT)); 2901 if (Jsave) jacobian = Jsave; 2902 if (jacobian != snes->jacobian_pre) { 2903 jacobian = snes->jacobian_pre; 2904 if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 2905 } else jacobian = NULL; 2906 } 2907 PetscCall(VecDestroy(&x)); 2908 if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2909 if (mviewer) PetscCall(PetscViewerDestroy(&mviewer)); 2910 PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2911 2912 if (Jnorm) *Jnorm = gnorm; 2913 if (diffNorm) *diffNorm = nrm; 2914 PetscFunctionReturn(PETSC_SUCCESS); 2915 } 2916 2917 /*@ 2918 SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 2919 2920 Collective 2921 2922 Input Parameters: 2923 + snes - the `SNES` context 2924 - X - input vector 2925 2926 Output Parameters: 2927 + A - Jacobian matrix 2928 - B - optional matrix for building the preconditioner, usually the same as `A` 2929 2930 Options Database Keys: 2931 + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 2932 . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2933 . -snes_test_jacobian <optional threshold> - compare the user provided Jacobian with one compute via finite differences to check for errors. If a threshold is given, display only those entries whose difference is greater than the threshold. 2934 . -snes_test_jacobian_view - display the user provided Jacobian, the finite difference Jacobian and the difference between them to help users detect the location of errors in the user provided Jacobian 2935 . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2936 . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2937 . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 2938 . -snes_compare_operator - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner 2939 . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2940 . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2941 . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2942 . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2943 . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2944 . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2945 - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2946 2947 Level: developer 2948 2949 Note: 2950 Most users should not need to explicitly call this routine, as it 2951 is used internally within the nonlinear solvers. 2952 2953 Developer Note: 2954 This has duplicative ways of checking the accuracy of the user provided Jacobian (see the options above). This is for historical reasons, the routine `SNESTestJacobian()` use to used 2955 with the `SNESType` of test that has been removed. 2956 2957 .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 2958 @*/ 2959 PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2960 { 2961 PetscBool flag; 2962 DM dm; 2963 DMSNES sdm; 2964 KSP ksp; 2965 2966 PetscFunctionBegin; 2967 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2968 PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2969 PetscCheckSameComm(snes, 1, X, 2); 2970 PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 2971 PetscCall(SNESGetDM(snes, &dm)); 2972 PetscCall(DMGetDMSNES(dm, &sdm)); 2973 2974 /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2975 if (snes->lagjacobian == -2) { 2976 snes->lagjacobian = -1; 2977 2978 PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2979 } else if (snes->lagjacobian == -1) { 2980 PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 2981 PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2982 if (flag) { 2983 PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 2984 PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2985 } 2986 PetscFunctionReturn(PETSC_SUCCESS); 2987 } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 2988 PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 2989 PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2990 if (flag) { 2991 PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 2992 PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2993 } 2994 PetscFunctionReturn(PETSC_SUCCESS); 2995 } 2996 if (snes->npc && snes->npcside == PC_LEFT) { 2997 PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 2998 PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2999 PetscFunctionReturn(PETSC_SUCCESS); 3000 } 3001 3002 PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 3003 PetscCall(VecLockReadPush(X)); 3004 { 3005 void *ctx; 3006 SNESJacobianFn *J; 3007 PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 3008 PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 3009 } 3010 PetscCall(VecLockReadPop(X)); 3011 PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 3012 3013 /* attach latest linearization point to the matrix used to construct the preconditioner */ 3014 PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 3015 3016 /* the next line ensures that snes->ksp exists */ 3017 PetscCall(SNESGetKSP(snes, &ksp)); 3018 if (snes->lagpreconditioner == -2) { 3019 PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 3020 PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 3021 snes->lagpreconditioner = -1; 3022 } else if (snes->lagpreconditioner == -1) { 3023 PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 3024 PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 3025 } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 3026 PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 3027 PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 3028 } else { 3029 PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 3030 PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 3031 } 3032 3033 /* monkey business to allow testing Jacobians in multilevel solvers. 3034 This is needed because the SNESTestXXX interface does not accept vectors and matrices */ 3035 { 3036 Vec xsave = snes->vec_sol; 3037 Mat jacobiansave = snes->jacobian; 3038 Mat jacobian_presave = snes->jacobian_pre; 3039 3040 snes->vec_sol = X; 3041 snes->jacobian = A; 3042 snes->jacobian_pre = B; 3043 if (snes->testFunc) PetscCall(SNESTestFunction(snes)); 3044 if (snes->testJac) PetscCall(SNESTestJacobian(snes, NULL, NULL)); 3045 3046 snes->vec_sol = xsave; 3047 snes->jacobian = jacobiansave; 3048 snes->jacobian_pre = jacobian_presave; 3049 } 3050 3051 { 3052 PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 3053 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 3054 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 3055 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 3056 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 3057 if (flag || flag_draw || flag_contour) { 3058 Mat Bexp_mine = NULL, Bexp, FDexp; 3059 PetscViewer vdraw, vstdout; 3060 PetscBool flg; 3061 if (flag_operator) { 3062 PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 3063 Bexp = Bexp_mine; 3064 } else { 3065 /* See if the matrix used to construct the preconditioner can be viewed and added directly */ 3066 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, "")); 3067 if (flg) Bexp = B; 3068 else { 3069 /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 3070 PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 3071 Bexp = Bexp_mine; 3072 } 3073 } 3074 PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 3075 PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 3076 PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 3077 if (flag_draw || flag_contour) { 3078 PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 3079 if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 3080 } else vdraw = NULL; 3081 PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 3082 if (flag) PetscCall(MatView(Bexp, vstdout)); 3083 if (vdraw) PetscCall(MatView(Bexp, vdraw)); 3084 PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 3085 if (flag) PetscCall(MatView(FDexp, vstdout)); 3086 if (vdraw) PetscCall(MatView(FDexp, vdraw)); 3087 PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 3088 PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 3089 if (flag) PetscCall(MatView(FDexp, vstdout)); 3090 if (vdraw) { /* Always use contour for the difference */ 3091 PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 3092 PetscCall(MatView(FDexp, vdraw)); 3093 PetscCall(PetscViewerPopFormat(vdraw)); 3094 } 3095 if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 3096 PetscCall(PetscViewerDestroy(&vdraw)); 3097 PetscCall(MatDestroy(&Bexp_mine)); 3098 PetscCall(MatDestroy(&FDexp)); 3099 } 3100 } 3101 { 3102 PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 3103 PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 3104 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 3105 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 3106 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 3107 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 3108 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 3109 if (flag_threshold) { 3110 PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 3111 PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 3112 } 3113 if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 3114 Mat Bfd; 3115 PetscViewer vdraw, vstdout; 3116 MatColoring coloring; 3117 ISColoring iscoloring; 3118 MatFDColoring matfdcoloring; 3119 SNESFunctionFn *func; 3120 void *funcctx; 3121 PetscReal norm1, norm2, normmax; 3122 3123 PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 3124 PetscCall(MatColoringCreate(Bfd, &coloring)); 3125 PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 3126 PetscCall(MatColoringSetFromOptions(coloring)); 3127 PetscCall(MatColoringApply(coloring, &iscoloring)); 3128 PetscCall(MatColoringDestroy(&coloring)); 3129 PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 3130 PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 3131 PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 3132 PetscCall(ISColoringDestroy(&iscoloring)); 3133 3134 /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 3135 PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 3136 PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)func, funcctx)); 3137 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 3138 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 3139 PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 3140 PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 3141 PetscCall(MatFDColoringDestroy(&matfdcoloring)); 3142 3143 PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 3144 if (flag_draw || flag_contour) { 3145 PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 3146 if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 3147 } else vdraw = NULL; 3148 PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 3149 if (flag_display) PetscCall(MatView(B, vstdout)); 3150 if (vdraw) PetscCall(MatView(B, vdraw)); 3151 PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 3152 if (flag_display) PetscCall(MatView(Bfd, vstdout)); 3153 if (vdraw) PetscCall(MatView(Bfd, vdraw)); 3154 PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 3155 PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 3156 PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 3157 PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 3158 PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 3159 if (flag_display) PetscCall(MatView(Bfd, vstdout)); 3160 if (vdraw) { /* Always use contour for the difference */ 3161 PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 3162 PetscCall(MatView(Bfd, vdraw)); 3163 PetscCall(PetscViewerPopFormat(vdraw)); 3164 } 3165 if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 3166 3167 if (flag_threshold) { 3168 PetscInt bs, rstart, rend, i; 3169 PetscCall(MatGetBlockSize(B, &bs)); 3170 PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 3171 for (i = rstart; i < rend; i++) { 3172 const PetscScalar *ba, *ca; 3173 const PetscInt *bj, *cj; 3174 PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 3175 PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 3176 PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 3177 PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 3178 PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 3179 for (j = 0; j < bn; j++) { 3180 PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 3181 if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 3182 maxentrycol = bj[j]; 3183 maxentry = PetscRealPart(ba[j]); 3184 } 3185 if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 3186 maxdiffcol = bj[j]; 3187 maxdiff = PetscRealPart(ca[j]); 3188 } 3189 if (rdiff > maxrdiff) { 3190 maxrdiffcol = bj[j]; 3191 maxrdiff = rdiff; 3192 } 3193 } 3194 if (maxrdiff > 1) { 3195 PetscCall(PetscViewerASCIIPrintf(vstdout, "row %" PetscInt_FMT " (maxentry=%g at %" PetscInt_FMT ", maxdiff=%g at %" PetscInt_FMT ", maxrdiff=%g at %" PetscInt_FMT "):", i, (double)maxentry, maxentrycol, (double)maxdiff, maxdiffcol, (double)maxrdiff, maxrdiffcol)); 3196 for (j = 0; j < bn; j++) { 3197 PetscReal rdiff; 3198 rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 3199 if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 3200 } 3201 PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 3202 } 3203 PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 3204 PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 3205 } 3206 } 3207 PetscCall(PetscViewerDestroy(&vdraw)); 3208 PetscCall(MatDestroy(&Bfd)); 3209 } 3210 } 3211 PetscFunctionReturn(PETSC_SUCCESS); 3212 } 3213 3214 /*@C 3215 SNESSetJacobian - Sets the function to compute Jacobian as well as the 3216 location to store the matrix. 3217 3218 Logically Collective 3219 3220 Input Parameters: 3221 + snes - the `SNES` context 3222 . Amat - the matrix that defines the (approximate) Jacobian 3223 . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 3224 . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details 3225 - ctx - [optional] user-defined context for private data for the 3226 Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3227 3228 Level: beginner 3229 3230 Notes: 3231 If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 3232 each matrix. 3233 3234 If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3235 space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3236 3237 If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3238 must be a `MatFDColoring`. 3239 3240 Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3241 example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3242 3243 .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 3244 `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn` 3245 @*/ 3246 PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 3247 { 3248 DM dm; 3249 3250 PetscFunctionBegin; 3251 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3252 if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3253 if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3254 if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3255 if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 3256 PetscCall(SNESGetDM(snes, &dm)); 3257 PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3258 if (Amat) { 3259 PetscCall(PetscObjectReference((PetscObject)Amat)); 3260 PetscCall(MatDestroy(&snes->jacobian)); 3261 3262 snes->jacobian = Amat; 3263 } 3264 if (Pmat) { 3265 PetscCall(PetscObjectReference((PetscObject)Pmat)); 3266 PetscCall(MatDestroy(&snes->jacobian_pre)); 3267 3268 snes->jacobian_pre = Pmat; 3269 } 3270 PetscFunctionReturn(PETSC_SUCCESS); 3271 } 3272 3273 /*@C 3274 SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3275 provided context for evaluating the Jacobian. 3276 3277 Not Collective, but `Mat` object will be parallel if `SNES` is 3278 3279 Input Parameter: 3280 . snes - the nonlinear solver context 3281 3282 Output Parameters: 3283 + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3284 . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 3285 . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn` 3286 - ctx - location to stash Jacobian ctx (or `NULL`) 3287 3288 Level: advanced 3289 3290 .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()` 3291 @*/ 3292 PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 3293 { 3294 DM dm; 3295 3296 PetscFunctionBegin; 3297 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3298 if (Amat) *Amat = snes->jacobian; 3299 if (Pmat) *Pmat = snes->jacobian_pre; 3300 PetscCall(SNESGetDM(snes, &dm)); 3301 PetscCall(DMSNESGetJacobian(dm, J, ctx)); 3302 PetscFunctionReturn(PETSC_SUCCESS); 3303 } 3304 3305 static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3306 { 3307 DM dm; 3308 DMSNES sdm; 3309 3310 PetscFunctionBegin; 3311 PetscCall(SNESGetDM(snes, &dm)); 3312 PetscCall(DMGetDMSNES(dm, &sdm)); 3313 if (!sdm->ops->computejacobian && snes->jacobian_pre) { 3314 DM dm; 3315 PetscBool isdense, ismf; 3316 3317 PetscCall(SNESGetDM(snes, &dm)); 3318 PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 3319 PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 3320 if (isdense) { 3321 PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 3322 } else if (!ismf) { 3323 PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 3324 } 3325 } 3326 PetscFunctionReturn(PETSC_SUCCESS); 3327 } 3328 3329 /*@ 3330 SNESSetUp - Sets up the internal data structures for the later use 3331 of a nonlinear solver `SNESSolve()`. 3332 3333 Collective 3334 3335 Input Parameter: 3336 . snes - the `SNES` context 3337 3338 Level: advanced 3339 3340 Note: 3341 For basic use of the `SNES` solvers the user does not need to explicitly call 3342 `SNESSetUp()`, since these actions will automatically occur during 3343 the call to `SNESSolve()`. However, if one wishes to control this 3344 phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3345 and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3346 3347 .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()` 3348 @*/ 3349 PetscErrorCode SNESSetUp(SNES snes) 3350 { 3351 DM dm; 3352 DMSNES sdm; 3353 SNESLineSearch linesearch, pclinesearch; 3354 void *lsprectx, *lspostctx; 3355 PetscBool mf_operator, mf; 3356 Vec f, fpc; 3357 void *funcctx; 3358 void *jacctx, *appctx; 3359 Mat j, jpre; 3360 PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 3361 PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 3362 SNESFunctionFn *func; 3363 SNESJacobianFn *jac; 3364 3365 PetscFunctionBegin; 3366 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3367 if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3368 PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 3369 3370 if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 3371 3372 PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 3373 3374 PetscCall(SNESGetDM(snes, &dm)); 3375 PetscCall(DMGetDMSNES(dm, &sdm)); 3376 PetscCall(SNESSetDefaultComputeJacobian(snes)); 3377 3378 if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3379 3380 if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3381 3382 if (snes->linesearch) { 3383 PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 3384 PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3385 } 3386 3387 PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3388 if (snes->npc && snes->npcside == PC_LEFT) { 3389 snes->mf = PETSC_TRUE; 3390 snes->mf_operator = PETSC_FALSE; 3391 } 3392 3393 if (snes->npc) { 3394 /* copy the DM over */ 3395 PetscCall(SNESGetDM(snes, &dm)); 3396 PetscCall(SNESSetDM(snes->npc, dm)); 3397 3398 PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 3399 PetscCall(VecDuplicate(f, &fpc)); 3400 PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 3401 PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 3402 PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 3403 PetscCall(SNESGetApplicationContext(snes, &appctx)); 3404 PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 3405 PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 3406 PetscCall(VecDestroy(&fpc)); 3407 3408 /* copy the function pointers over */ 3409 PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 3410 3411 /* default to 1 iteration */ 3412 PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3413 if (snes->npcside == PC_RIGHT) { 3414 PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3415 } else { 3416 PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3417 } 3418 PetscCall(SNESSetFromOptions(snes->npc)); 3419 3420 /* copy the line search context over */ 3421 if (snes->linesearch && snes->npc->linesearch) { 3422 PetscCall(SNESGetLineSearch(snes, &linesearch)); 3423 PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 3424 PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 3425 PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 3426 PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 3427 PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 3428 PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 3429 } 3430 } 3431 if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 3432 if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx)); 3433 3434 snes->jac_iter = 0; 3435 snes->pre_iter = 0; 3436 3437 PetscTryTypeMethod(snes, setup); 3438 3439 PetscCall(SNESSetDefaultComputeJacobian(snes)); 3440 3441 if (snes->npc && snes->npcside == PC_LEFT) { 3442 if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3443 if (snes->linesearch) { 3444 PetscCall(SNESGetLineSearch(snes, &linesearch)); 3445 PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 3446 } 3447 } 3448 } 3449 PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 3450 snes->setupcalled = PETSC_TRUE; 3451 PetscFunctionReturn(PETSC_SUCCESS); 3452 } 3453 3454 /*@ 3455 SNESReset - Resets a `SNES` context to the state it was in before `SNESSetUp()` was called and removes any allocated `Vec` and `Mat` from its data structures 3456 3457 Collective 3458 3459 Input Parameter: 3460 . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 3461 3462 Level: intermediate 3463 3464 Notes: 3465 Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain. 3466 3467 Call this if you wish to reuse a `SNES` but with different size vectors 3468 3469 Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3470 3471 .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 3472 @*/ 3473 PetscErrorCode SNESReset(SNES snes) 3474 { 3475 PetscFunctionBegin; 3476 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3477 if (snes->ops->ctxdestroy && snes->ctx) { 3478 PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx)); 3479 snes->ctx = NULL; 3480 } 3481 if (snes->npc) PetscCall(SNESReset(snes->npc)); 3482 3483 PetscTryTypeMethod(snes, reset); 3484 if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 3485 3486 if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 3487 3488 PetscCall(VecDestroy(&snes->vec_rhs)); 3489 PetscCall(VecDestroy(&snes->vec_sol)); 3490 PetscCall(VecDestroy(&snes->vec_sol_update)); 3491 PetscCall(VecDestroy(&snes->vec_func)); 3492 PetscCall(MatDestroy(&snes->jacobian)); 3493 PetscCall(MatDestroy(&snes->jacobian_pre)); 3494 PetscCall(MatDestroy(&snes->picard)); 3495 PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 3496 PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3497 3498 snes->alwayscomputesfinalresidual = PETSC_FALSE; 3499 3500 snes->nwork = snes->nvwork = 0; 3501 snes->setupcalled = PETSC_FALSE; 3502 PetscFunctionReturn(PETSC_SUCCESS); 3503 } 3504 3505 /*@ 3506 SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also 3507 removes the default viewer. 3508 3509 Collective 3510 3511 Input Parameter: 3512 . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 3513 3514 Level: intermediate 3515 3516 .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3517 @*/ 3518 PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3519 { 3520 PetscInt i; 3521 3522 PetscFunctionBegin; 3523 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3524 for (i = 0; i < snes->numberreasonviews; i++) { 3525 if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3526 } 3527 snes->numberreasonviews = 0; 3528 PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 3529 PetscFunctionReturn(PETSC_SUCCESS); 3530 } 3531 3532 /*@ 3533 SNESDestroy - Destroys the nonlinear solver context that was created 3534 with `SNESCreate()`. 3535 3536 Collective 3537 3538 Input Parameter: 3539 . snes - the `SNES` context 3540 3541 Level: beginner 3542 3543 .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 3544 @*/ 3545 PetscErrorCode SNESDestroy(SNES *snes) 3546 { 3547 DM dm; 3548 3549 PetscFunctionBegin; 3550 if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3551 PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3552 if (--((PetscObject)*snes)->refct > 0) { 3553 *snes = NULL; 3554 PetscFunctionReturn(PETSC_SUCCESS); 3555 } 3556 3557 PetscCall(SNESReset(*snes)); 3558 PetscCall(SNESDestroy(&(*snes)->npc)); 3559 3560 /* if memory was published with SAWs then destroy it */ 3561 PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3562 PetscTryTypeMethod(*snes, destroy); 3563 3564 dm = (*snes)->dm; 3565 while (dm) { 3566 PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 3567 PetscCall(DMGetCoarseDM(dm, &dm)); 3568 } 3569 3570 PetscCall(DMDestroy(&(*snes)->dm)); 3571 PetscCall(KSPDestroy(&(*snes)->ksp)); 3572 PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 3573 3574 PetscCall(PetscFree((*snes)->kspconvctx)); 3575 if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP)); 3576 if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3577 PetscCall(SNESMonitorCancel(*snes)); 3578 PetscCall(SNESConvergedReasonViewCancel(*snes)); 3579 PetscCall(PetscHeaderDestroy(snes)); 3580 PetscFunctionReturn(PETSC_SUCCESS); 3581 } 3582 3583 /* ----------- Routines to set solver parameters ---------- */ 3584 3585 /*@ 3586 SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`. 3587 3588 Logically Collective 3589 3590 Input Parameters: 3591 + snes - the `SNES` context 3592 - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3593 the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3594 3595 Options Database Keys: 3596 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 3597 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3598 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 3599 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3600 3601 Level: intermediate 3602 3603 Notes: 3604 The default is 1 3605 3606 The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3607 3608 `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3609 3610 .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3611 `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3612 @*/ 3613 PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3614 { 3615 PetscFunctionBegin; 3616 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3617 PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 3618 PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3619 PetscValidLogicalCollectiveInt(snes, lag, 2); 3620 snes->lagpreconditioner = lag; 3621 PetscFunctionReturn(PETSC_SUCCESS); 3622 } 3623 3624 /*@ 3625 SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3626 3627 Logically Collective 3628 3629 Input Parameters: 3630 + snes - the `SNES` context 3631 - steps - the number of refinements to do, defaults to 0 3632 3633 Options Database Key: 3634 . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3635 3636 Level: intermediate 3637 3638 Notes: 3639 Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement. 3640 3641 Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3642 3643 .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 3644 `SNESSetDM()`, `SNESSolve()` 3645 @*/ 3646 PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3647 { 3648 PetscFunctionBegin; 3649 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3650 PetscValidLogicalCollectiveInt(snes, steps, 2); 3651 snes->gridsequence = steps; 3652 PetscFunctionReturn(PETSC_SUCCESS); 3653 } 3654 3655 /*@ 3656 SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3657 3658 Logically Collective 3659 3660 Input Parameter: 3661 . snes - the `SNES` context 3662 3663 Output Parameter: 3664 . steps - the number of refinements to do, defaults to 0 3665 3666 Level: intermediate 3667 3668 .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3669 @*/ 3670 PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3671 { 3672 PetscFunctionBegin; 3673 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3674 *steps = snes->gridsequence; 3675 PetscFunctionReturn(PETSC_SUCCESS); 3676 } 3677 3678 /*@ 3679 SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3680 3681 Not Collective 3682 3683 Input Parameter: 3684 . snes - the `SNES` context 3685 3686 Output Parameter: 3687 . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3688 the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3689 3690 Level: intermediate 3691 3692 Notes: 3693 The default is 1 3694 3695 The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3696 3697 .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3698 @*/ 3699 PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3700 { 3701 PetscFunctionBegin; 3702 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3703 *lag = snes->lagpreconditioner; 3704 PetscFunctionReturn(PETSC_SUCCESS); 3705 } 3706 3707 /*@ 3708 SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3709 often the preconditioner is rebuilt. 3710 3711 Logically Collective 3712 3713 Input Parameters: 3714 + snes - the `SNES` context 3715 - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3716 the Jacobian is built etc. -2 means rebuild at next chance but then never again 3717 3718 Options Database Keys: 3719 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 3720 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3721 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 3722 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3723 3724 Level: intermediate 3725 3726 Notes: 3727 The default is 1 3728 3729 The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3730 3731 If -1 is used before the very first nonlinear solve the CODE WILL FAIL! because no Jacobian is used, use -2 to indicate you want it recomputed 3732 at the next Newton step but never again (unless it is reset to another value) 3733 3734 .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3735 @*/ 3736 PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3737 { 3738 PetscFunctionBegin; 3739 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3740 PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 3741 PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3742 PetscValidLogicalCollectiveInt(snes, lag, 2); 3743 snes->lagjacobian = lag; 3744 PetscFunctionReturn(PETSC_SUCCESS); 3745 } 3746 3747 /*@ 3748 SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3749 3750 Not Collective 3751 3752 Input Parameter: 3753 . snes - the `SNES` context 3754 3755 Output Parameter: 3756 . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3757 the Jacobian is built etc. 3758 3759 Level: intermediate 3760 3761 Notes: 3762 The default is 1 3763 3764 The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3765 3766 .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3767 3768 @*/ 3769 PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3770 { 3771 PetscFunctionBegin; 3772 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3773 *lag = snes->lagjacobian; 3774 PetscFunctionReturn(PETSC_SUCCESS); 3775 } 3776 3777 /*@ 3778 SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 3779 3780 Logically collective 3781 3782 Input Parameters: 3783 + snes - the `SNES` context 3784 - flg - jacobian lagging persists if true 3785 3786 Options Database Keys: 3787 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 3788 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3789 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 3790 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3791 3792 Level: advanced 3793 3794 Notes: 3795 Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3796 3797 This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 3798 several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 3799 timesteps may present huge efficiency gains. 3800 3801 .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 3802 @*/ 3803 PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3804 { 3805 PetscFunctionBegin; 3806 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3807 PetscValidLogicalCollectiveBool(snes, flg, 2); 3808 snes->lagjac_persist = flg; 3809 PetscFunctionReturn(PETSC_SUCCESS); 3810 } 3811 3812 /*@ 3813 SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 3814 3815 Logically Collective 3816 3817 Input Parameters: 3818 + snes - the `SNES` context 3819 - flg - preconditioner lagging persists if true 3820 3821 Options Database Keys: 3822 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 3823 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3824 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 3825 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3826 3827 Level: developer 3828 3829 Notes: 3830 Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3831 3832 This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 3833 by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 3834 several timesteps may present huge efficiency gains. 3835 3836 .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 3837 @*/ 3838 PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3839 { 3840 PetscFunctionBegin; 3841 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3842 PetscValidLogicalCollectiveBool(snes, flg, 2); 3843 snes->lagpre_persist = flg; 3844 PetscFunctionReturn(PETSC_SUCCESS); 3845 } 3846 3847 /*@ 3848 SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3849 3850 Logically Collective 3851 3852 Input Parameters: 3853 + snes - the `SNES` context 3854 - force - `PETSC_TRUE` require at least one iteration 3855 3856 Options Database Key: 3857 . -snes_force_iteration <force> - Sets forcing an iteration 3858 3859 Level: intermediate 3860 3861 Note: 3862 This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3863 3864 .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()` 3865 @*/ 3866 PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3867 { 3868 PetscFunctionBegin; 3869 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3870 snes->forceiteration = force; 3871 PetscFunctionReturn(PETSC_SUCCESS); 3872 } 3873 3874 /*@ 3875 SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 3876 3877 Logically Collective 3878 3879 Input Parameter: 3880 . snes - the `SNES` context 3881 3882 Output Parameter: 3883 . force - `PETSC_TRUE` requires at least one iteration. 3884 3885 Level: intermediate 3886 3887 .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()` 3888 @*/ 3889 PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3890 { 3891 PetscFunctionBegin; 3892 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3893 *force = snes->forceiteration; 3894 PetscFunctionReturn(PETSC_SUCCESS); 3895 } 3896 3897 /*@ 3898 SNESSetTolerances - Sets various parameters used in `SNES` convergence tests. 3899 3900 Logically Collective 3901 3902 Input Parameters: 3903 + snes - the `SNES` context 3904 . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $ 3905 . rtol - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $ 3906 . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 3907 . maxit - the maximum number of iterations allowed in the solver, default 50. 3908 - maxf - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000 3909 3910 Options Database Keys: 3911 + -snes_atol <abstol> - Sets `abstol` 3912 . -snes_rtol <rtol> - Sets `rtol` 3913 . -snes_stol <stol> - Sets `stol` 3914 . -snes_max_it <maxit> - Sets `maxit` 3915 - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum) 3916 3917 Level: intermediate 3918 3919 Note: 3920 All parameters must be non-negative 3921 3922 Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`. 3923 The default value is the value in the object when its type is set. 3924 3925 Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations. 3926 3927 Fortran Note: 3928 Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL` 3929 3930 .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 3931 @*/ 3932 PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3933 { 3934 PetscFunctionBegin; 3935 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3936 PetscValidLogicalCollectiveReal(snes, abstol, 2); 3937 PetscValidLogicalCollectiveReal(snes, rtol, 3); 3938 PetscValidLogicalCollectiveReal(snes, stol, 4); 3939 PetscValidLogicalCollectiveInt(snes, maxit, 5); 3940 PetscValidLogicalCollectiveInt(snes, maxf, 6); 3941 3942 if (abstol == (PetscReal)PETSC_DETERMINE) { 3943 snes->abstol = snes->default_abstol; 3944 } else if (abstol != (PetscReal)PETSC_CURRENT) { 3945 PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3946 snes->abstol = abstol; 3947 } 3948 3949 if (rtol == (PetscReal)PETSC_DETERMINE) { 3950 snes->rtol = snes->default_rtol; 3951 } else if (rtol != (PetscReal)PETSC_CURRENT) { 3952 PetscCheck(rtol >= 0.0 && 1.0 > rtol, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative and less than 1.0", (double)rtol); 3953 snes->rtol = rtol; 3954 } 3955 3956 if (stol == (PetscReal)PETSC_DETERMINE) { 3957 snes->stol = snes->default_stol; 3958 } else if (stol != (PetscReal)PETSC_CURRENT) { 3959 PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3960 snes->stol = stol; 3961 } 3962 3963 if (maxit == PETSC_DETERMINE) { 3964 snes->max_its = snes->default_max_its; 3965 } else if (maxit == PETSC_UNLIMITED) { 3966 snes->max_its = PETSC_INT_MAX; 3967 } else if (maxit != PETSC_CURRENT) { 3968 PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3969 snes->max_its = maxit; 3970 } 3971 3972 if (maxf == PETSC_DETERMINE) { 3973 snes->max_funcs = snes->default_max_funcs; 3974 } else if (maxf == PETSC_UNLIMITED || maxf == -1) { 3975 snes->max_funcs = PETSC_UNLIMITED; 3976 } else if (maxf != PETSC_CURRENT) { 3977 PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf); 3978 snes->max_funcs = maxf; 3979 } 3980 PetscFunctionReturn(PETSC_SUCCESS); 3981 } 3982 3983 /*@ 3984 SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3985 3986 Logically Collective 3987 3988 Input Parameters: 3989 + snes - the `SNES` context 3990 - divtol - the divergence tolerance. Use `PETSC_UNLIMITED` to deactivate the test. If the residual norm $ F(x^n) \ge divtol * F(x^0) $ the solver 3991 is stopped due to divergence. 3992 3993 Options Database Key: 3994 . -snes_divergence_tolerance <divtol> - Sets `divtol` 3995 3996 Level: intermediate 3997 3998 Notes: 3999 Use `PETSC_DETERMINE` to use the default value from when the object's type was set. 4000 4001 Fortran Note: 4002 Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL` 4003 4004 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()` 4005 @*/ 4006 PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 4007 { 4008 PetscFunctionBegin; 4009 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4010 PetscValidLogicalCollectiveReal(snes, divtol, 2); 4011 4012 if (divtol == (PetscReal)PETSC_DETERMINE) { 4013 snes->divtol = snes->default_divtol; 4014 } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) { 4015 snes->divtol = PETSC_UNLIMITED; 4016 } else if (divtol != (PetscReal)PETSC_CURRENT) { 4017 PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol); 4018 snes->divtol = divtol; 4019 } 4020 PetscFunctionReturn(PETSC_SUCCESS); 4021 } 4022 4023 /*@ 4024 SNESGetTolerances - Gets various parameters used in `SNES` convergence tests. 4025 4026 Not Collective 4027 4028 Input Parameter: 4029 . snes - the `SNES` context 4030 4031 Output Parameters: 4032 + atol - the absolute convergence tolerance 4033 . rtol - the relative convergence tolerance 4034 . stol - convergence tolerance in terms of the norm of the change in the solution between steps 4035 . maxit - the maximum number of iterations allowed 4036 - maxf - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound 4037 4038 Level: intermediate 4039 4040 Notes: 4041 See `SNESSetTolerances()` for details on the parameters. 4042 4043 The user can specify `NULL` for any parameter that is not needed. 4044 4045 .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 4046 @*/ 4047 PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 4048 { 4049 PetscFunctionBegin; 4050 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4051 if (atol) *atol = snes->abstol; 4052 if (rtol) *rtol = snes->rtol; 4053 if (stol) *stol = snes->stol; 4054 if (maxit) *maxit = snes->max_its; 4055 if (maxf) *maxf = snes->max_funcs; 4056 PetscFunctionReturn(PETSC_SUCCESS); 4057 } 4058 4059 /*@ 4060 SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 4061 4062 Not Collective 4063 4064 Input Parameters: 4065 + snes - the `SNES` context 4066 - divtol - divergence tolerance 4067 4068 Level: intermediate 4069 4070 .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 4071 @*/ 4072 PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 4073 { 4074 PetscFunctionBegin; 4075 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4076 if (divtol) *divtol = snes->divtol; 4077 PetscFunctionReturn(PETSC_SUCCESS); 4078 } 4079 4080 PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 4081 4082 PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 4083 { 4084 PetscDrawLG lg; 4085 PetscReal x, y, per; 4086 PetscViewer v = (PetscViewer)monctx; 4087 static PetscReal prev; /* should be in the context */ 4088 PetscDraw draw; 4089 4090 PetscFunctionBegin; 4091 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 4092 PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 4093 if (!n) PetscCall(PetscDrawLGReset(lg)); 4094 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4095 PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 4096 x = (PetscReal)n; 4097 if (rnorm > 0.0) y = PetscLog10Real(rnorm); 4098 else y = -15.0; 4099 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4100 if (n < 20 || !(n % 5) || snes->reason) { 4101 PetscCall(PetscDrawLGDraw(lg)); 4102 PetscCall(PetscDrawLGSave(lg)); 4103 } 4104 4105 PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 4106 if (!n) PetscCall(PetscDrawLGReset(lg)); 4107 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4108 PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 4109 PetscCall(SNESMonitorRange_Private(snes, n, &per)); 4110 x = (PetscReal)n; 4111 y = 100.0 * per; 4112 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4113 if (n < 20 || !(n % 5) || snes->reason) { 4114 PetscCall(PetscDrawLGDraw(lg)); 4115 PetscCall(PetscDrawLGSave(lg)); 4116 } 4117 4118 PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 4119 if (!n) { 4120 prev = rnorm; 4121 PetscCall(PetscDrawLGReset(lg)); 4122 } 4123 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4124 PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 4125 x = (PetscReal)n; 4126 y = (prev - rnorm) / prev; 4127 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4128 if (n < 20 || !(n % 5) || snes->reason) { 4129 PetscCall(PetscDrawLGDraw(lg)); 4130 PetscCall(PetscDrawLGSave(lg)); 4131 } 4132 4133 PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 4134 if (!n) PetscCall(PetscDrawLGReset(lg)); 4135 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4136 PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 4137 x = (PetscReal)n; 4138 y = (prev - rnorm) / (prev * per); 4139 if (n > 2) { /*skip initial crazy value */ 4140 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4141 } 4142 if (n < 20 || !(n % 5) || snes->reason) { 4143 PetscCall(PetscDrawLGDraw(lg)); 4144 PetscCall(PetscDrawLGSave(lg)); 4145 } 4146 prev = rnorm; 4147 PetscFunctionReturn(PETSC_SUCCESS); 4148 } 4149 4150 /*@ 4151 SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 4152 4153 Collective 4154 4155 Input Parameters: 4156 + snes - the `SNES` context 4157 . it - current iteration 4158 . xnorm - 2-norm of current iterate 4159 . snorm - 2-norm of current step 4160 - fnorm - 2-norm of function 4161 4162 Level: developer 4163 4164 Note: 4165 This routine is called by the `SNESSolve()` implementations. 4166 It does not typically need to be called by the user. 4167 4168 .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 4169 @*/ 4170 PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 4171 { 4172 PetscFunctionBegin; 4173 if (!snes->reason) { 4174 if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 4175 if (it == snes->max_its && !snes->reason) { 4176 if (snes->normschedule == SNES_NORM_ALWAYS) { 4177 PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 4178 snes->reason = SNES_DIVERGED_MAX_IT; 4179 } else snes->reason = SNES_CONVERGED_ITS; 4180 } 4181 } 4182 PetscFunctionReturn(PETSC_SUCCESS); 4183 } 4184 4185 /*@ 4186 SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database 4187 4188 Collective 4189 4190 Input Parameters: 4191 + snes - nonlinear solver context obtained from `SNESCreate()` 4192 . iter - current iteration number 4193 - rnorm - current relative norm of the residual 4194 4195 Level: developer 4196 4197 Note: 4198 This routine is called by the `SNESSolve()` implementations. 4199 It does not typically need to be called by the user. 4200 4201 .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4202 @*/ 4203 PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4204 { 4205 PetscInt i, n = snes->numbermonitors; 4206 4207 PetscFunctionBegin; 4208 PetscCall(VecLockReadPush(snes->vec_sol)); 4209 for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 4210 PetscCall(VecLockReadPop(snes->vec_sol)); 4211 PetscFunctionReturn(PETSC_SUCCESS); 4212 } 4213 4214 /* ------------ Routines to set performance monitoring options ----------- */ 4215 4216 /*MC 4217 SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4218 4219 Synopsis: 4220 #include <petscsnes.h> 4221 PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4222 4223 Collective 4224 4225 Input Parameters: 4226 + snes - the `SNES` context 4227 . its - iteration number 4228 . norm - 2-norm function value (may be estimated) 4229 - mctx - [optional] monitoring context 4230 4231 Level: advanced 4232 4233 .seealso: [](ch_snes), `SNESMonitorSet()` 4234 M*/ 4235 4236 /*@C 4237 SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 4238 iteration of the `SNES` nonlinear solver to display the iteration's 4239 progress. 4240 4241 Logically Collective 4242 4243 Input Parameters: 4244 + snes - the `SNES` context 4245 . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4246 . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 4247 - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4248 4249 Options Database Keys: 4250 + -snes_monitor - sets `SNESMonitorDefault()` 4251 . -snes_monitor draw::draw_lg - sets line graph monitor, 4252 - -snes_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to `SNESMonitorSet()`, but does not cancel those set via 4253 the options database. 4254 4255 Level: intermediate 4256 4257 Note: 4258 Several different monitoring routines may be set by calling 4259 `SNESMonitorSet()` multiple times; all will be called in the 4260 order in which they were set. 4261 4262 Fortran Note: 4263 Only a single monitor function can be set for each `SNES` object 4264 4265 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn` 4266 @*/ 4267 PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy) 4268 { 4269 PetscFunctionBegin; 4270 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4271 for (PetscInt i = 0; i < snes->numbermonitors; i++) { 4272 PetscBool identical; 4273 4274 PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, mctx, monitordestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 4275 if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4276 } 4277 PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 4278 snes->monitor[snes->numbermonitors] = f; 4279 snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4280 snes->monitorcontext[snes->numbermonitors++] = mctx; 4281 PetscFunctionReturn(PETSC_SUCCESS); 4282 } 4283 4284 /*@ 4285 SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 4286 4287 Logically Collective 4288 4289 Input Parameter: 4290 . snes - the `SNES` context 4291 4292 Options Database Key: 4293 . -snes_monitor_cancel - cancels all monitors that have been hardwired 4294 into a code by calls to `SNESMonitorSet()`, but does not cancel those 4295 set via the options database 4296 4297 Level: intermediate 4298 4299 Note: 4300 There is no way to clear one specific monitor from a `SNES` object. 4301 4302 .seealso: [](ch_snes), `SNES`, `SNESMonitorDefault()`, `SNESMonitorSet()` 4303 @*/ 4304 PetscErrorCode SNESMonitorCancel(SNES snes) 4305 { 4306 PetscInt i; 4307 4308 PetscFunctionBegin; 4309 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4310 for (i = 0; i < snes->numbermonitors; i++) { 4311 if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4312 } 4313 snes->numbermonitors = 0; 4314 PetscFunctionReturn(PETSC_SUCCESS); 4315 } 4316 4317 /*MC 4318 SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4319 4320 Synopsis: 4321 #include <petscsnes.h> 4322 PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4323 4324 Collective 4325 4326 Input Parameters: 4327 + snes - the `SNES` context 4328 . it - current iteration (0 is the first and is before any Newton step) 4329 . xnorm - 2-norm of current iterate 4330 . gnorm - 2-norm of current step 4331 . f - 2-norm of function 4332 - cctx - [optional] convergence context 4333 4334 Output Parameter: 4335 . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4336 4337 Level: intermediate 4338 4339 .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 4340 M*/ 4341 4342 /*@C 4343 SNESSetConvergenceTest - Sets the function that is to be used 4344 to test for convergence of the nonlinear iterative solution. 4345 4346 Logically Collective 4347 4348 Input Parameters: 4349 + snes - the `SNES` context 4350 . SNESConvergenceTestFunction - routine to test for convergence 4351 . cctx - [optional] context for private data for the convergence routine (may be `NULL`) 4352 - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 4353 4354 Level: advanced 4355 4356 .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 4357 @*/ 4358 PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *)) 4359 { 4360 PetscFunctionBegin; 4361 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4362 if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 4363 if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP)); 4364 snes->ops->converged = SNESConvergenceTestFunction; 4365 snes->ops->convergeddestroy = destroy; 4366 snes->cnvP = cctx; 4367 PetscFunctionReturn(PETSC_SUCCESS); 4368 } 4369 4370 /*@ 4371 SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation 4372 4373 Not Collective 4374 4375 Input Parameter: 4376 . snes - the `SNES` context 4377 4378 Output Parameter: 4379 . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4380 4381 Options Database Key: 4382 . -snes_converged_reason - prints the reason to standard out 4383 4384 Level: intermediate 4385 4386 Note: 4387 Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4388 4389 .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4390 @*/ 4391 PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4392 { 4393 PetscFunctionBegin; 4394 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4395 PetscAssertPointer(reason, 2); 4396 *reason = snes->reason; 4397 PetscFunctionReturn(PETSC_SUCCESS); 4398 } 4399 4400 /*@C 4401 SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4402 4403 Not Collective 4404 4405 Input Parameter: 4406 . snes - the `SNES` context 4407 4408 Output Parameter: 4409 . strreason - a human readable string that describes `SNES` converged reason 4410 4411 Level: beginner 4412 4413 .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4414 @*/ 4415 PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4416 { 4417 PetscFunctionBegin; 4418 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4419 PetscAssertPointer(strreason, 2); 4420 *strreason = SNESConvergedReasons[snes->reason]; 4421 PetscFunctionReturn(PETSC_SUCCESS); 4422 } 4423 4424 /*@ 4425 SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 4426 4427 Not Collective 4428 4429 Input Parameters: 4430 + snes - the `SNES` context 4431 - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 4432 manual pages for the individual convergence tests for complete lists 4433 4434 Level: developer 4435 4436 Developer Note: 4437 Called inside the various `SNESSolve()` implementations 4438 4439 .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 4440 @*/ 4441 PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4442 { 4443 PetscFunctionBegin; 4444 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4445 PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 4446 snes->reason = reason; 4447 PetscFunctionReturn(PETSC_SUCCESS); 4448 } 4449 4450 /*@ 4451 SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4452 4453 Logically Collective 4454 4455 Input Parameters: 4456 + snes - iterative context obtained from `SNESCreate()` 4457 . a - array to hold history, this array will contain the function norms computed at each step 4458 . its - integer array holds the number of linear iterations for each solve. 4459 . na - size of `a` and `its` 4460 - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4461 else it continues storing new values for new nonlinear solves after the old ones 4462 4463 Level: intermediate 4464 4465 Notes: 4466 If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` (or, deprecated, `PETSC_DEFAULT`) then a 4467 default array of length 1,000 is allocated. 4468 4469 This routine is useful, e.g., when running a code for purposes 4470 of accurate performance monitoring, when no I/O should be done 4471 during the section of code that is being timed. 4472 4473 If the arrays run out of space after a number of iterations then the later values are not saved in the history 4474 4475 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4476 @*/ 4477 PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4478 { 4479 PetscFunctionBegin; 4480 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4481 if (a) PetscAssertPointer(a, 2); 4482 if (its) PetscAssertPointer(its, 3); 4483 if (!a) { 4484 if (na == PETSC_DECIDE) na = 1000; 4485 PetscCall(PetscCalloc2(na, &a, na, &its)); 4486 snes->conv_hist_alloc = PETSC_TRUE; 4487 } 4488 snes->conv_hist = a; 4489 snes->conv_hist_its = its; 4490 snes->conv_hist_max = (size_t)na; 4491 snes->conv_hist_len = 0; 4492 snes->conv_hist_reset = reset; 4493 PetscFunctionReturn(PETSC_SUCCESS); 4494 } 4495 4496 #if defined(PETSC_HAVE_MATLAB) 4497 #include <engine.h> /* MATLAB include file */ 4498 #include <mex.h> /* MATLAB include file */ 4499 4500 PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4501 { 4502 mxArray *mat; 4503 PetscInt i; 4504 PetscReal *ar; 4505 4506 mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4507 ar = (PetscReal *)mxGetData(mat); 4508 for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 4509 return mat; 4510 } 4511 #endif 4512 4513 /*@C 4514 SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4515 4516 Not Collective 4517 4518 Input Parameter: 4519 . snes - iterative context obtained from `SNESCreate()` 4520 4521 Output Parameters: 4522 + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4523 . its - integer array holds the number of linear iterations (or 4524 negative if not converged) for each solve. 4525 - na - size of `a` and `its` 4526 4527 Level: intermediate 4528 4529 Note: 4530 This routine is useful, e.g., when running a code for purposes 4531 of accurate performance monitoring, when no I/O should be done 4532 during the section of code that is being timed. 4533 4534 Fortran Notes: 4535 Return the arrays with ``SNESRestoreConvergenceHistory()` 4536 4537 Use the arguments 4538 .vb 4539 PetscReal, pointer :: a(:) 4540 PetscInt, pointer :: its(:) 4541 .ve 4542 4543 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4544 @*/ 4545 PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4546 { 4547 PetscFunctionBegin; 4548 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4549 if (a) *a = snes->conv_hist; 4550 if (its) *its = snes->conv_hist_its; 4551 if (na) *na = (PetscInt)snes->conv_hist_len; 4552 PetscFunctionReturn(PETSC_SUCCESS); 4553 } 4554 4555 /*@C 4556 SNESSetUpdate - Sets the general-purpose update function called 4557 at the beginning of every iteration of the nonlinear solve. Specifically 4558 it is called just before the Jacobian is "evaluated" and after the function 4559 evaluation. 4560 4561 Logically Collective 4562 4563 Input Parameters: 4564 + snes - The nonlinear solver context 4565 - func - The update function; for calling sequence see `SNESUpdateFn` 4566 4567 Level: advanced 4568 4569 Notes: 4570 This is NOT what one uses to update the ghost points before a function evaluation, that should be done at the beginning of your function provided 4571 to `SNESSetFunction()`, or `SNESSetPicard()` 4572 This is not used by most users, and it is intended to provide a general hook that is run 4573 right before the direction step is computed. 4574 4575 Users are free to modify the current residual vector, 4576 the current linearization point, or any other vector associated to the specific solver used. 4577 If such modifications take place, it is the user responsibility to update all the relevant 4578 vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like 4579 .vb 4580 PetscErrorCode update(SNES snes, PetscInt iteration) 4581 { 4582 PetscFunctionBeginUser; 4583 if (iteration > 0) { 4584 // update the model parameters here 4585 Vec x,f; 4586 PetscCall(SNESGetSolution(snes,&x)); 4587 PetcCall(SNESGetFunction(snes,&f,NULL,NULL)); 4588 PetscCall(SNESComputeFunction(snes,x,f)); 4589 } 4590 PetscFunctionReturn(PETSC_SUCCESS); 4591 } 4592 .ve 4593 4594 There are a variety of function hooks one many set that are called at different stages of the nonlinear solution process, see the functions listed below. 4595 4596 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 4597 `SNESMonitorSet()` 4598 @*/ 4599 PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func) 4600 { 4601 PetscFunctionBegin; 4602 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4603 snes->ops->update = func; 4604 PetscFunctionReturn(PETSC_SUCCESS); 4605 } 4606 4607 /*@ 4608 SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 4609 4610 Collective 4611 4612 Input Parameters: 4613 + snes - iterative context obtained from `SNESCreate()` 4614 - viewer - the viewer to display the reason 4615 4616 Options Database Keys: 4617 + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4618 - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4619 4620 Level: beginner 4621 4622 Note: 4623 To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4624 use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 4625 4626 .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4627 `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4628 `SNESConvergedReasonViewFromOptions()`, 4629 `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 4630 @*/ 4631 PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4632 { 4633 PetscViewerFormat format; 4634 PetscBool isAscii; 4635 4636 PetscFunctionBegin; 4637 if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 4638 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 4639 if (isAscii) { 4640 PetscCall(PetscViewerGetFormat(viewer, &format)); 4641 PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1)); 4642 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 4643 DM dm; 4644 Vec u; 4645 PetscDS prob; 4646 PetscInt Nf, f; 4647 PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 4648 void **exactCtx; 4649 PetscReal error; 4650 4651 PetscCall(SNESGetDM(snes, &dm)); 4652 PetscCall(SNESGetSolution(snes, &u)); 4653 PetscCall(DMGetDS(dm, &prob)); 4654 PetscCall(PetscDSGetNumFields(prob, &Nf)); 4655 PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 4656 for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 4657 PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 4658 PetscCall(PetscFree2(exactSol, exactCtx)); 4659 if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 4660 else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 4661 } 4662 if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 4663 if (((PetscObject)snes)->prefix) { 4664 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 4665 } else { 4666 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 4667 } 4668 } else if (snes->reason <= 0) { 4669 if (((PetscObject)snes)->prefix) { 4670 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve did not converge due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 4671 } else { 4672 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 4673 } 4674 } 4675 PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1)); 4676 } 4677 PetscFunctionReturn(PETSC_SUCCESS); 4678 } 4679 4680 /*@C 4681 SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4682 end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4683 4684 Logically Collective 4685 4686 Input Parameters: 4687 + snes - the `SNES` context 4688 . f - the `SNESConvergedReason` view function 4689 . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 4690 - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4691 4692 Calling sequence of `f`: 4693 + snes - the `SNES` context 4694 - vctx - [optional] context for private data for the function 4695 4696 Options Database Keys: 4697 + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4698 - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4699 calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4700 4701 Level: intermediate 4702 4703 Note: 4704 Several different converged reason view routines may be set by calling 4705 `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4706 order in which they were set. 4707 4708 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`, 4709 `PetscCtxDestroyFn` 4710 @*/ 4711 PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy) 4712 { 4713 PetscFunctionBegin; 4714 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4715 for (PetscInt i = 0; i < snes->numberreasonviews; i++) { 4716 PetscBool identical; 4717 4718 PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 4719 if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4720 } 4721 PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4722 snes->reasonview[snes->numberreasonviews] = f; 4723 snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4724 snes->reasonviewcontext[snes->numberreasonviews++] = vctx; 4725 PetscFunctionReturn(PETSC_SUCCESS); 4726 } 4727 4728 /*@ 4729 SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 4730 All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist. 4731 4732 Collective 4733 4734 Input Parameter: 4735 . snes - the `SNES` object 4736 4737 Level: advanced 4738 4739 .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4740 `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 4741 @*/ 4742 PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4743 { 4744 static PetscBool incall = PETSC_FALSE; 4745 4746 PetscFunctionBegin; 4747 if (incall) PetscFunctionReturn(PETSC_SUCCESS); 4748 incall = PETSC_TRUE; 4749 4750 /* All user-provided viewers are called first, if they exist. */ 4751 for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4752 4753 /* Call PETSc default routine if users ask for it */ 4754 if (snes->convergedreasonviewer) { 4755 PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat)); 4756 PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer)); 4757 PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer)); 4758 } 4759 incall = PETSC_FALSE; 4760 PetscFunctionReturn(PETSC_SUCCESS); 4761 } 4762 4763 /*@ 4764 SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object 4765 4766 Collective 4767 4768 Input Parameters: 4769 + snes - the `SNES` context 4770 . b - the constant part of the equation $F(x) = b$, or `NULL` to use zero. 4771 - x - the solution vector. 4772 4773 Level: beginner 4774 4775 Note: 4776 The user should initialize the vector, `x`, with the initial guess 4777 for the nonlinear solve prior to calling `SNESSolve()` . 4778 4779 .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4780 `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4781 `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()` 4782 @*/ 4783 PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4784 { 4785 PetscBool flg; 4786 PetscInt grid; 4787 Vec xcreated = NULL; 4788 DM dm; 4789 4790 PetscFunctionBegin; 4791 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4792 if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4793 if (x) PetscCheckSameComm(snes, 1, x, 3); 4794 if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4795 if (b) PetscCheckSameComm(snes, 1, b, 2); 4796 4797 /* High level operations using the nonlinear solver */ 4798 { 4799 PetscViewer viewer; 4800 PetscViewerFormat format; 4801 PetscInt num; 4802 PetscBool flg; 4803 static PetscBool incall = PETSC_FALSE; 4804 4805 if (!incall) { 4806 /* Estimate the convergence rate of the discretization */ 4807 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 4808 if (flg) { 4809 PetscConvEst conv; 4810 DM dm; 4811 PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 4812 PetscInt Nf; 4813 4814 incall = PETSC_TRUE; 4815 PetscCall(SNESGetDM(snes, &dm)); 4816 PetscCall(DMGetNumFields(dm, &Nf)); 4817 PetscCall(PetscCalloc1(Nf, &alpha)); 4818 PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 4819 PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 4820 PetscCall(PetscConvEstSetFromOptions(conv)); 4821 PetscCall(PetscConvEstSetUp(conv)); 4822 PetscCall(PetscConvEstGetConvRate(conv, alpha)); 4823 PetscCall(PetscViewerPushFormat(viewer, format)); 4824 PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 4825 PetscCall(PetscViewerPopFormat(viewer)); 4826 PetscCall(PetscViewerDestroy(&viewer)); 4827 PetscCall(PetscConvEstDestroy(&conv)); 4828 PetscCall(PetscFree(alpha)); 4829 incall = PETSC_FALSE; 4830 } 4831 /* Adaptively refine the initial grid */ 4832 num = 1; 4833 PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 4834 if (flg) { 4835 DMAdaptor adaptor; 4836 4837 incall = PETSC_TRUE; 4838 PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4839 PetscCall(DMAdaptorSetSolver(adaptor, snes)); 4840 PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 4841 PetscCall(DMAdaptorSetFromOptions(adaptor)); 4842 PetscCall(DMAdaptorSetUp(adaptor)); 4843 PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 4844 PetscCall(DMAdaptorDestroy(&adaptor)); 4845 incall = PETSC_FALSE; 4846 } 4847 /* Use grid sequencing to adapt */ 4848 num = 0; 4849 PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 4850 if (num) { 4851 DMAdaptor adaptor; 4852 const char *prefix; 4853 4854 incall = PETSC_TRUE; 4855 PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4856 PetscCall(SNESGetOptionsPrefix(snes, &prefix)); 4857 PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix)); 4858 PetscCall(DMAdaptorSetSolver(adaptor, snes)); 4859 PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 4860 PetscCall(DMAdaptorSetFromOptions(adaptor)); 4861 PetscCall(DMAdaptorSetUp(adaptor)); 4862 PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view")); 4863 PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 4864 PetscCall(DMAdaptorDestroy(&adaptor)); 4865 incall = PETSC_FALSE; 4866 } 4867 } 4868 } 4869 if (!x) x = snes->vec_sol; 4870 if (!x) { 4871 PetscCall(SNESGetDM(snes, &dm)); 4872 PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4873 x = xcreated; 4874 } 4875 PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4876 4877 for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4878 for (grid = 0; grid < snes->gridsequence + 1; grid++) { 4879 /* set solution vector */ 4880 if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 4881 PetscCall(VecDestroy(&snes->vec_sol)); 4882 snes->vec_sol = x; 4883 PetscCall(SNESGetDM(snes, &dm)); 4884 4885 /* set affine vector if provided */ 4886 if (b) PetscCall(PetscObjectReference((PetscObject)b)); 4887 PetscCall(VecDestroy(&snes->vec_rhs)); 4888 snes->vec_rhs = b; 4889 4890 if (snes->vec_rhs) PetscCheck(snes->vec_func != snes->vec_rhs, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Right hand side vector cannot be function vector"); 4891 PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4892 PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector"); 4893 if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 4894 PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 4895 PetscCall(SNESSetUp(snes)); 4896 4897 if (!grid) { 4898 if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4899 } 4900 4901 if (snes->conv_hist_reset) snes->conv_hist_len = 0; 4902 PetscCall(SNESResetCounters(snes)); 4903 snes->reason = SNES_CONVERGED_ITERATING; 4904 PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4905 PetscUseTypeMethod(snes, solve); 4906 PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 4907 PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4908 snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 4909 4910 if (snes->lagjac_persist) snes->jac_iter += snes->iter; 4911 if (snes->lagpre_persist) snes->pre_iter += snes->iter; 4912 4913 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 4914 if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4915 /* Call converged reason views. This may involve user-provided viewers as well */ 4916 PetscCall(SNESConvergedReasonViewFromOptions(snes)); 4917 4918 if (snes->errorifnotconverged) { 4919 if (snes->reason < 0) PetscCall(SNESMonitorCancel(snes)); 4920 PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 4921 } 4922 if (snes->reason < 0) break; 4923 if (grid < snes->gridsequence) { 4924 DM fine; 4925 Vec xnew; 4926 Mat interp; 4927 4928 PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 4929 PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 4930 PetscCall(DMGetCoordinatesLocalSetUp(fine)); 4931 PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 4932 PetscCall(DMCreateGlobalVector(fine, &xnew)); 4933 PetscCall(MatInterpolate(interp, x, xnew)); 4934 PetscCall(DMInterpolate(snes->dm, interp, fine)); 4935 PetscCall(MatDestroy(&interp)); 4936 x = xnew; 4937 4938 PetscCall(SNESReset(snes)); 4939 PetscCall(SNESSetDM(snes, fine)); 4940 PetscCall(SNESResetFromOptions(snes)); 4941 PetscCall(DMDestroy(&fine)); 4942 PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4943 } 4944 } 4945 PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 4946 PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 4947 PetscCall(DMMonitor(snes->dm)); 4948 PetscCall(SNESMonitorPauseFinal_Internal(snes)); 4949 4950 PetscCall(VecDestroy(&xcreated)); 4951 PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 4952 PetscFunctionReturn(PETSC_SUCCESS); 4953 } 4954 4955 /* --------- Internal routines for SNES Package --------- */ 4956 4957 /*@ 4958 SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES` 4959 4960 Collective 4961 4962 Input Parameters: 4963 + snes - the `SNES` context 4964 - type - a known method 4965 4966 Options Database Key: 4967 . -snes_type <type> - Sets the method; use -help for a list 4968 of available methods (for instance, newtonls or newtontr) 4969 4970 Level: intermediate 4971 4972 Notes: 4973 See `SNESType` for available methods (for instance) 4974 + `SNESNEWTONLS` - Newton's method with line search 4975 (systems of nonlinear equations) 4976 - `SNESNEWTONTR` - Newton's method with trust region 4977 (systems of nonlinear equations) 4978 4979 Normally, it is best to use the `SNESSetFromOptions()` command and then 4980 set the `SNES` solver type from the options database rather than by using 4981 this routine. Using the options database provides the user with 4982 maximum flexibility in evaluating the many nonlinear solvers. 4983 The `SNESSetType()` routine is provided for those situations where it 4984 is necessary to set the nonlinear solver independently of the command 4985 line or options database. This might be the case, for example, when 4986 the choice of solver changes during the execution of the program, 4987 and the user's application is taking responsibility for choosing the 4988 appropriate method. 4989 4990 Developer Note: 4991 `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4992 the constructor in that list and calls it to create the specific object. 4993 4994 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 4995 @*/ 4996 PetscErrorCode SNESSetType(SNES snes, SNESType type) 4997 { 4998 PetscBool match; 4999 PetscErrorCode (*r)(SNES); 5000 5001 PetscFunctionBegin; 5002 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5003 PetscAssertPointer(type, 2); 5004 5005 PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 5006 if (match) PetscFunctionReturn(PETSC_SUCCESS); 5007 5008 PetscCall(PetscFunctionListFind(SNESList, type, &r)); 5009 PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 5010 /* Destroy the previous private SNES context */ 5011 PetscTryTypeMethod(snes, destroy); 5012 /* Reinitialize type-specific function pointers in SNESOps structure */ 5013 snes->ops->reset = NULL; 5014 snes->ops->setup = NULL; 5015 snes->ops->solve = NULL; 5016 snes->ops->view = NULL; 5017 snes->ops->setfromoptions = NULL; 5018 snes->ops->destroy = NULL; 5019 5020 /* It may happen the user has customized the line search before calling SNESSetType */ 5021 if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5022 5023 /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 5024 snes->setupcalled = PETSC_FALSE; 5025 5026 PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 5027 PetscCall((*r)(snes)); 5028 PetscFunctionReturn(PETSC_SUCCESS); 5029 } 5030 5031 /*@ 5032 SNESGetType - Gets the `SNES` method type and name (as a string). 5033 5034 Not Collective 5035 5036 Input Parameter: 5037 . snes - nonlinear solver context 5038 5039 Output Parameter: 5040 . type - `SNES` method (a character string) 5041 5042 Level: intermediate 5043 5044 .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 5045 @*/ 5046 PetscErrorCode SNESGetType(SNES snes, SNESType *type) 5047 { 5048 PetscFunctionBegin; 5049 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5050 PetscAssertPointer(type, 2); 5051 *type = ((PetscObject)snes)->type_name; 5052 PetscFunctionReturn(PETSC_SUCCESS); 5053 } 5054 5055 /*@ 5056 SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 5057 5058 Logically Collective 5059 5060 Input Parameters: 5061 + snes - the `SNES` context obtained from `SNESCreate()` 5062 - u - the solution vector 5063 5064 Level: beginner 5065 5066 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 5067 @*/ 5068 PetscErrorCode SNESSetSolution(SNES snes, Vec u) 5069 { 5070 DM dm; 5071 5072 PetscFunctionBegin; 5073 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5074 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 5075 PetscCall(PetscObjectReference((PetscObject)u)); 5076 PetscCall(VecDestroy(&snes->vec_sol)); 5077 5078 snes->vec_sol = u; 5079 5080 PetscCall(SNESGetDM(snes, &dm)); 5081 PetscCall(DMShellSetGlobalVector(dm, u)); 5082 PetscFunctionReturn(PETSC_SUCCESS); 5083 } 5084 5085 /*@ 5086 SNESGetSolution - Returns the vector where the approximate solution is 5087 stored. This is the fine grid solution when using `SNESSetGridSequence()`. 5088 5089 Not Collective, but `x` is parallel if `snes` is parallel 5090 5091 Input Parameter: 5092 . snes - the `SNES` context 5093 5094 Output Parameter: 5095 . x - the solution 5096 5097 Level: intermediate 5098 5099 .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 5100 @*/ 5101 PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 5102 { 5103 PetscFunctionBegin; 5104 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5105 PetscAssertPointer(x, 2); 5106 *x = snes->vec_sol; 5107 PetscFunctionReturn(PETSC_SUCCESS); 5108 } 5109 5110 /*@ 5111 SNESGetSolutionUpdate - Returns the vector where the solution update is 5112 stored. 5113 5114 Not Collective, but `x` is parallel if `snes` is parallel 5115 5116 Input Parameter: 5117 . snes - the `SNES` context 5118 5119 Output Parameter: 5120 . x - the solution update 5121 5122 Level: advanced 5123 5124 .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 5125 @*/ 5126 PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 5127 { 5128 PetscFunctionBegin; 5129 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5130 PetscAssertPointer(x, 2); 5131 *x = snes->vec_sol_update; 5132 PetscFunctionReturn(PETSC_SUCCESS); 5133 } 5134 5135 /*@C 5136 SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 5137 5138 Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 5139 5140 Input Parameter: 5141 . snes - the `SNES` context 5142 5143 Output Parameters: 5144 + r - the vector that is used to store residuals (or `NULL` if you don't want it) 5145 . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn` 5146 - ctx - the function context (or `NULL` if you don't want it) 5147 5148 Level: advanced 5149 5150 Note: 5151 The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 5152 5153 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn` 5154 @*/ 5155 PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx) 5156 { 5157 DM dm; 5158 5159 PetscFunctionBegin; 5160 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5161 if (r) { 5162 if (!snes->vec_func) { 5163 if (snes->vec_rhs) { 5164 PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 5165 } else if (snes->vec_sol) { 5166 PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 5167 } else if (snes->dm) { 5168 PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 5169 } 5170 } 5171 *r = snes->vec_func; 5172 } 5173 PetscCall(SNESGetDM(snes, &dm)); 5174 PetscCall(DMSNESGetFunction(dm, f, ctx)); 5175 PetscFunctionReturn(PETSC_SUCCESS); 5176 } 5177 5178 /*@C 5179 SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5180 5181 Input Parameter: 5182 . snes - the `SNES` context 5183 5184 Output Parameters: 5185 + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence 5186 - ctx - the function context (or `NULL`) 5187 5188 Level: advanced 5189 5190 .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn` 5191 @*/ 5192 PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx) 5193 { 5194 DM dm; 5195 5196 PetscFunctionBegin; 5197 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5198 PetscCall(SNESGetDM(snes, &dm)); 5199 PetscCall(DMSNESGetNGS(dm, f, ctx)); 5200 PetscFunctionReturn(PETSC_SUCCESS); 5201 } 5202 5203 /*@ 5204 SNESSetOptionsPrefix - Sets the prefix used for searching for all 5205 `SNES` options in the database. 5206 5207 Logically Collective 5208 5209 Input Parameters: 5210 + snes - the `SNES` context 5211 - prefix - the prefix to prepend to all option names 5212 5213 Level: advanced 5214 5215 Note: 5216 A hyphen (-) must NOT be given at the beginning of the prefix name. 5217 The first character of all runtime options is AUTOMATICALLY the hyphen. 5218 5219 .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 5220 @*/ 5221 PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5222 { 5223 PetscFunctionBegin; 5224 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5225 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 5226 if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 5227 if (snes->linesearch) { 5228 PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 5229 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 5230 } 5231 PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 5232 PetscFunctionReturn(PETSC_SUCCESS); 5233 } 5234 5235 /*@ 5236 SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5237 `SNES` options in the database. 5238 5239 Logically Collective 5240 5241 Input Parameters: 5242 + snes - the `SNES` context 5243 - prefix - the prefix to prepend to all option names 5244 5245 Level: advanced 5246 5247 Note: 5248 A hyphen (-) must NOT be given at the beginning of the prefix name. 5249 The first character of all runtime options is AUTOMATICALLY the hyphen. 5250 5251 .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 5252 @*/ 5253 PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5254 { 5255 PetscFunctionBegin; 5256 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5257 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 5258 if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 5259 if (snes->linesearch) { 5260 PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 5261 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 5262 } 5263 PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 5264 PetscFunctionReturn(PETSC_SUCCESS); 5265 } 5266 5267 /*@ 5268 SNESGetOptionsPrefix - Gets the prefix used for searching for all 5269 `SNES` options in the database. 5270 5271 Not Collective 5272 5273 Input Parameter: 5274 . snes - the `SNES` context 5275 5276 Output Parameter: 5277 . prefix - pointer to the prefix string used 5278 5279 Level: advanced 5280 5281 .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 5282 @*/ 5283 PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5284 { 5285 PetscFunctionBegin; 5286 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5287 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 5288 PetscFunctionReturn(PETSC_SUCCESS); 5289 } 5290 5291 /*@C 5292 SNESRegister - Adds a method to the nonlinear solver package. 5293 5294 Not Collective 5295 5296 Input Parameters: 5297 + sname - name of a new user-defined solver 5298 - function - routine to create method context 5299 5300 Level: advanced 5301 5302 Note: 5303 `SNESRegister()` may be called multiple times to add several user-defined solvers. 5304 5305 Example Usage: 5306 .vb 5307 SNESRegister("my_solver", MySolverCreate); 5308 .ve 5309 5310 Then, your solver can be chosen with the procedural interface via 5311 .vb 5312 SNESSetType(snes, "my_solver") 5313 .ve 5314 or at runtime via the option 5315 .vb 5316 -snes_type my_solver 5317 .ve 5318 5319 .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 5320 @*/ 5321 PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5322 { 5323 PetscFunctionBegin; 5324 PetscCall(SNESInitializePackage()); 5325 PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 5326 PetscFunctionReturn(PETSC_SUCCESS); 5327 } 5328 5329 PetscErrorCode SNESTestLocalMin(SNES snes) 5330 { 5331 PetscInt N, i, j; 5332 Vec u, uh, fh; 5333 PetscScalar value; 5334 PetscReal norm; 5335 5336 PetscFunctionBegin; 5337 PetscCall(SNESGetSolution(snes, &u)); 5338 PetscCall(VecDuplicate(u, &uh)); 5339 PetscCall(VecDuplicate(u, &fh)); 5340 5341 /* currently only works for sequential */ 5342 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 5343 PetscCall(VecGetSize(u, &N)); 5344 for (i = 0; i < N; i++) { 5345 PetscCall(VecCopy(u, uh)); 5346 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5347 for (j = -10; j < 11; j++) { 5348 value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 5349 PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5350 PetscCall(SNESComputeFunction(snes, uh, fh)); 5351 PetscCall(VecNorm(fh, NORM_2, &norm)); 5352 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5353 value = -value; 5354 PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5355 } 5356 } 5357 PetscCall(VecDestroy(&uh)); 5358 PetscCall(VecDestroy(&fh)); 5359 PetscFunctionReturn(PETSC_SUCCESS); 5360 } 5361 5362 /*@ 5363 SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 5364 computing relative tolerance for linear solvers within an inexact 5365 Newton method. 5366 5367 Logically Collective 5368 5369 Input Parameters: 5370 + snes - `SNES` context 5371 - flag - `PETSC_TRUE` or `PETSC_FALSE` 5372 5373 Options Database Keys: 5374 + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 5375 . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 5376 . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 5377 . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 5378 . -snes_ksp_ew_gamma <gamma> - Sets gamma 5379 . -snes_ksp_ew_alpha <alpha> - Sets alpha 5380 . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 5381 - -snes_ksp_ew_threshold <threshold> - Sets threshold 5382 5383 Level: advanced 5384 5385 Note: 5386 The default is to use a constant relative tolerance for 5387 the inner linear solvers. Alternatively, one can use the 5388 Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance 5389 is reset at each Newton iteration according progress of the nonlinear 5390 solver. 5391 5392 .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 5393 @*/ 5394 PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5395 { 5396 PetscFunctionBegin; 5397 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5398 PetscValidLogicalCollectiveBool(snes, flag, 2); 5399 snes->ksp_ewconv = flag; 5400 PetscFunctionReturn(PETSC_SUCCESS); 5401 } 5402 5403 /*@ 5404 SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 5405 for computing relative tolerance for linear solvers within an 5406 inexact Newton method. 5407 5408 Not Collective 5409 5410 Input Parameter: 5411 . snes - `SNES` context 5412 5413 Output Parameter: 5414 . flag - `PETSC_TRUE` or `PETSC_FALSE` 5415 5416 Level: advanced 5417 5418 .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 5419 @*/ 5420 PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5421 { 5422 PetscFunctionBegin; 5423 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5424 PetscAssertPointer(flag, 2); 5425 *flag = snes->ksp_ewconv; 5426 PetscFunctionReturn(PETSC_SUCCESS); 5427 } 5428 5429 /*@ 5430 SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 5431 convergence criteria for the linear solvers within an inexact 5432 Newton method. 5433 5434 Logically Collective 5435 5436 Input Parameters: 5437 + snes - `SNES` context 5438 . version - version 1, 2 (default is 2), 3 or 4 5439 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 5440 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5441 . gamma - multiplicative factor for version 2 rtol computation 5442 (0 <= gamma2 <= 1) 5443 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 5444 . alpha2 - power for safeguard 5445 - threshold - threshold for imposing safeguard (0 < threshold < 1) 5446 5447 Level: advanced 5448 5449 Notes: 5450 Version 3 was contributed by Luis Chacon, June 2006. 5451 5452 Use `PETSC_CURRENT` to retain the default for any of the parameters. 5453 5454 .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 5455 @*/ 5456 PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5457 { 5458 SNESKSPEW *kctx; 5459 5460 PetscFunctionBegin; 5461 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5462 kctx = (SNESKSPEW *)snes->kspconvctx; 5463 PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5464 PetscValidLogicalCollectiveInt(snes, version, 2); 5465 PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5466 PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5467 PetscValidLogicalCollectiveReal(snes, gamma, 5); 5468 PetscValidLogicalCollectiveReal(snes, alpha, 6); 5469 PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5470 PetscValidLogicalCollectiveReal(snes, threshold, 8); 5471 5472 if (version != PETSC_CURRENT) kctx->version = version; 5473 if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0; 5474 if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max; 5475 if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma; 5476 if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha; 5477 if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2; 5478 if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold; 5479 5480 PetscCheck(kctx->version >= 1 && kctx->version <= 4, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only versions 1 to 4 are supported: %" PetscInt_FMT, kctx->version); 5481 PetscCheck(kctx->rtol_0 >= 0.0 && kctx->rtol_0 < 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "0.0 <= rtol_0 < 1.0: %g", (double)kctx->rtol_0); 5482 PetscCheck(kctx->rtol_max >= 0.0 && kctx->rtol_max < 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "0.0 <= rtol_max (%g) < 1.0", (double)kctx->rtol_max); 5483 PetscCheck(kctx->gamma >= 0.0 && kctx->gamma <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "0.0 <= gamma (%g) <= 1.0", (double)kctx->gamma); 5484 PetscCheck(kctx->alpha > 1.0 && kctx->alpha <= 2.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "1.0 < alpha (%g) <= 2.0", (double)kctx->alpha); 5485 PetscCheck(kctx->threshold > 0.0 && kctx->threshold < 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "0.0 < threshold (%g) < 1.0", (double)kctx->threshold); 5486 PetscFunctionReturn(PETSC_SUCCESS); 5487 } 5488 5489 /*@ 5490 SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 5491 convergence criteria for the linear solvers within an inexact 5492 Newton method. 5493 5494 Not Collective 5495 5496 Input Parameter: 5497 . snes - `SNES` context 5498 5499 Output Parameters: 5500 + version - version 1, 2 (default is 2), 3 or 4 5501 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 5502 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5503 . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 5504 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 5505 . alpha2 - power for safeguard 5506 - threshold - threshold for imposing safeguard (0 < threshold < 1) 5507 5508 Level: advanced 5509 5510 .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 5511 @*/ 5512 PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5513 { 5514 SNESKSPEW *kctx; 5515 5516 PetscFunctionBegin; 5517 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5518 kctx = (SNESKSPEW *)snes->kspconvctx; 5519 PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5520 if (version) *version = kctx->version; 5521 if (rtol_0) *rtol_0 = kctx->rtol_0; 5522 if (rtol_max) *rtol_max = kctx->rtol_max; 5523 if (gamma) *gamma = kctx->gamma; 5524 if (alpha) *alpha = kctx->alpha; 5525 if (alpha2) *alpha2 = kctx->alpha2; 5526 if (threshold) *threshold = kctx->threshold; 5527 PetscFunctionReturn(PETSC_SUCCESS); 5528 } 5529 5530 PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5531 { 5532 SNES snes = (SNES)ctx; 5533 SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 5534 PetscReal rtol = PETSC_CURRENT, stol; 5535 5536 PetscFunctionBegin; 5537 if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 5538 if (!snes->iter) { 5539 rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 5540 PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 5541 } else { 5542 PetscCheck(kctx->version >= 1 && kctx->version <= 4, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only versions 1-4 are supported: %" PetscInt_FMT, kctx->version); 5543 if (kctx->version == 1) { 5544 rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 5545 stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 5546 if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 5547 } else if (kctx->version == 2) { 5548 rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 5549 stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 5550 if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 5551 } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 5552 rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 5553 /* safeguard: avoid sharp decrease of rtol */ 5554 stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 5555 stol = PetscMax(rtol, stol); 5556 rtol = PetscMin(kctx->rtol_0, stol); 5557 /* safeguard: avoid oversolving */ 5558 stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 5559 stol = PetscMax(rtol, stol); 5560 rtol = PetscMin(kctx->rtol_0, stol); 5561 } else /* if (kctx->version == 4) */ { 5562 /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 5563 PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 5564 PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 5565 PetscReal rk = ared / pred; 5566 if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 5567 else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 5568 else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 5569 else rtol = kctx->v4_m2 * kctx->rtol_last; 5570 5571 if (kctx->rtol_last_2 > kctx->v4_m3 && kctx->rtol_last > kctx->v4_m3 && kctx->rk_last_2 < kctx->v4_p1 && kctx->rk_last < kctx->v4_p1) rtol = kctx->v4_m4 * kctx->rtol_last; 5572 kctx->rtol_last_2 = kctx->rtol_last; 5573 kctx->rk_last_2 = kctx->rk_last; 5574 kctx->rk_last = rk; 5575 } 5576 } 5577 /* safeguard: avoid rtol greater than rtol_max */ 5578 rtol = PetscMin(rtol, kctx->rtol_max); 5579 PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT)); 5580 PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 5581 PetscFunctionReturn(PETSC_SUCCESS); 5582 } 5583 5584 PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5585 { 5586 SNES snes = (SNES)ctx; 5587 SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 5588 PCSide pcside; 5589 Vec lres; 5590 5591 PetscFunctionBegin; 5592 if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 5593 PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 5594 kctx->norm_last = snes->norm; 5595 if (kctx->version == 1 || kctx->version == 4) { 5596 PC pc; 5597 PetscBool getRes; 5598 5599 PetscCall(KSPGetPC(ksp, &pc)); 5600 PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 5601 if (!getRes) { 5602 KSPNormType normtype; 5603 5604 PetscCall(KSPGetNormType(ksp, &normtype)); 5605 getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 5606 } 5607 PetscCall(KSPGetPCSide(ksp, &pcside)); 5608 if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 5609 PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 5610 } else { 5611 /* KSP residual is preconditioned residual */ 5612 /* compute true linear residual norm */ 5613 Mat J; 5614 PetscCall(KSPGetOperators(ksp, &J, NULL)); 5615 PetscCall(VecDuplicate(b, &lres)); 5616 PetscCall(MatMult(J, x, lres)); 5617 PetscCall(VecAYPX(lres, -1.0, b)); 5618 PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 5619 PetscCall(VecDestroy(&lres)); 5620 } 5621 } 5622 PetscFunctionReturn(PETSC_SUCCESS); 5623 } 5624 5625 /*@ 5626 SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5627 5628 Not Collective, but if `snes` is parallel, then `ksp` is parallel 5629 5630 Input Parameter: 5631 . snes - the `SNES` context 5632 5633 Output Parameter: 5634 . ksp - the `KSP` context 5635 5636 Level: beginner 5637 5638 Notes: 5639 The user can then directly manipulate the `KSP` context to set various 5640 options, etc. Likewise, the user can then extract and manipulate the 5641 `PC` contexts as well. 5642 5643 Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function, changes to that `KSP` will have no effect. 5644 5645 .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5646 @*/ 5647 PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5648 { 5649 PetscFunctionBegin; 5650 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5651 PetscAssertPointer(ksp, 2); 5652 5653 if (!snes->ksp) { 5654 PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 5655 PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5656 5657 PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 5658 PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5659 5660 PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 5661 PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5662 } 5663 *ksp = snes->ksp; 5664 PetscFunctionReturn(PETSC_SUCCESS); 5665 } 5666 5667 #include <petsc/private/dmimpl.h> 5668 /*@ 5669 SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners 5670 5671 Logically Collective 5672 5673 Input Parameters: 5674 + snes - the nonlinear solver context 5675 - dm - the `DM`, cannot be `NULL` 5676 5677 Level: intermediate 5678 5679 Note: 5680 A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5681 even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5682 problems using the same function space. 5683 5684 .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 5685 @*/ 5686 PetscErrorCode SNESSetDM(SNES snes, DM dm) 5687 { 5688 KSP ksp; 5689 DMSNES sdm; 5690 5691 PetscFunctionBegin; 5692 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5693 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 5694 PetscCall(PetscObjectReference((PetscObject)dm)); 5695 if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 5696 if (snes->dm->dmsnes && !dm->dmsnes) { 5697 PetscCall(DMCopyDMSNES(snes->dm, dm)); 5698 PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5699 if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 5700 } 5701 PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 5702 PetscCall(DMDestroy(&snes->dm)); 5703 } 5704 snes->dm = dm; 5705 snes->dmAuto = PETSC_FALSE; 5706 5707 PetscCall(SNESGetKSP(snes, &ksp)); 5708 PetscCall(KSPSetDM(ksp, dm)); 5709 PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5710 if (snes->npc) { 5711 PetscCall(SNESSetDM(snes->npc, snes->dm)); 5712 PetscCall(SNESSetNPCSide(snes, snes->npcside)); 5713 } 5714 PetscFunctionReturn(PETSC_SUCCESS); 5715 } 5716 5717 /*@ 5718 SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners 5719 5720 Not Collective but `dm` obtained is parallel on `snes` 5721 5722 Input Parameter: 5723 . snes - the `SNES` context 5724 5725 Output Parameter: 5726 . dm - the `DM` 5727 5728 Level: intermediate 5729 5730 .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 5731 @*/ 5732 PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5733 { 5734 PetscFunctionBegin; 5735 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5736 if (!snes->dm) { 5737 PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5738 snes->dmAuto = PETSC_TRUE; 5739 } 5740 *dm = snes->dm; 5741 PetscFunctionReturn(PETSC_SUCCESS); 5742 } 5743 5744 /*@ 5745 SNESSetNPC - Sets the nonlinear preconditioner to be used. 5746 5747 Collective 5748 5749 Input Parameters: 5750 + snes - iterative context obtained from `SNESCreate()` 5751 - npc - the `SNES` nonlinear preconditioner object 5752 5753 Options Database Key: 5754 . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5755 5756 Level: developer 5757 5758 Notes: 5759 This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API. 5760 5761 Only some `SNESType` can use a nonlinear preconditioner 5762 5763 .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 5764 @*/ 5765 PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5766 { 5767 PetscFunctionBegin; 5768 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5769 PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5770 PetscCheckSameComm(snes, 1, npc, 2); 5771 PetscCall(PetscObjectReference((PetscObject)npc)); 5772 PetscCall(SNESDestroy(&snes->npc)); 5773 snes->npc = npc; 5774 PetscFunctionReturn(PETSC_SUCCESS); 5775 } 5776 5777 /*@ 5778 SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 5779 5780 Not Collective; but any changes to the obtained the `pc` object must be applied collectively 5781 5782 Input Parameter: 5783 . snes - iterative context obtained from `SNESCreate()` 5784 5785 Output Parameter: 5786 . pc - the `SNES` preconditioner context 5787 5788 Options Database Key: 5789 . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5790 5791 Level: advanced 5792 5793 Notes: 5794 If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will 5795 be used as the nonlinear preconditioner for the current `SNES`. 5796 5797 The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 5798 `SNES`. These may be overwritten if needed. 5799 5800 Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner 5801 5802 .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 5803 @*/ 5804 PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5805 { 5806 const char *optionsprefix; 5807 5808 PetscFunctionBegin; 5809 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5810 PetscAssertPointer(pc, 2); 5811 if (!snes->npc) { 5812 void *ctx; 5813 5814 PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 5815 PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 5816 PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 5817 PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 5818 PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5819 if (snes->ops->usercompute) { 5820 PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy)); 5821 } else { 5822 PetscCall(SNESGetApplicationContext(snes, &ctx)); 5823 PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5824 } 5825 PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 5826 } 5827 *pc = snes->npc; 5828 PetscFunctionReturn(PETSC_SUCCESS); 5829 } 5830 5831 /*@ 5832 SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES` 5833 5834 Not Collective 5835 5836 Input Parameter: 5837 . snes - iterative context obtained from `SNESCreate()` 5838 5839 Output Parameter: 5840 . has_npc - whether the `SNES` has a nonlinear preconditioner or not 5841 5842 Level: developer 5843 5844 .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 5845 @*/ 5846 PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5847 { 5848 PetscFunctionBegin; 5849 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5850 PetscAssertPointer(has_npc, 2); 5851 *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE; 5852 PetscFunctionReturn(PETSC_SUCCESS); 5853 } 5854 5855 /*@ 5856 SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`. 5857 5858 Logically Collective 5859 5860 Input Parameter: 5861 . snes - iterative context obtained from `SNESCreate()` 5862 5863 Output Parameter: 5864 . side - the preconditioning side, where side is one of 5865 .vb 5866 PC_LEFT - left preconditioning 5867 PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5868 .ve 5869 5870 Options Database Key: 5871 . -snes_npc_side <right,left> - nonlinear preconditioner side 5872 5873 Level: intermediate 5874 5875 Note: 5876 `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 5877 5878 .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5879 @*/ 5880 PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5881 { 5882 PetscFunctionBegin; 5883 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5884 PetscValidLogicalCollectiveEnum(snes, side, 2); 5885 if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 5886 PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5887 snes->npcside = side; 5888 PetscFunctionReturn(PETSC_SUCCESS); 5889 } 5890 5891 /*@ 5892 SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`. 5893 5894 Not Collective 5895 5896 Input Parameter: 5897 . snes - iterative context obtained from `SNESCreate()` 5898 5899 Output Parameter: 5900 . side - the preconditioning side, where side is one of 5901 .vb 5902 `PC_LEFT` - left preconditioning 5903 `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5904 .ve 5905 5906 Level: intermediate 5907 5908 .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5909 @*/ 5910 PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5911 { 5912 PetscFunctionBegin; 5913 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5914 PetscAssertPointer(side, 2); 5915 *side = snes->npcside; 5916 PetscFunctionReturn(PETSC_SUCCESS); 5917 } 5918 5919 /*@ 5920 SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES` 5921 5922 Collective 5923 5924 Input Parameters: 5925 + snes - iterative context obtained from `SNESCreate()` 5926 - linesearch - the linesearch object 5927 5928 Level: developer 5929 5930 Note: 5931 This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 5932 to configure it using the API). 5933 5934 .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 5935 @*/ 5936 PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5937 { 5938 PetscFunctionBegin; 5939 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5940 PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 5941 PetscCheckSameComm(snes, 1, linesearch, 2); 5942 PetscCall(PetscObjectReference((PetscObject)linesearch)); 5943 PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5944 5945 snes->linesearch = linesearch; 5946 PetscFunctionReturn(PETSC_SUCCESS); 5947 } 5948 5949 /*@ 5950 SNESGetLineSearch - Returns the line search associated with the `SNES`. 5951 5952 Not Collective 5953 5954 Input Parameter: 5955 . snes - iterative context obtained from `SNESCreate()` 5956 5957 Output Parameter: 5958 . linesearch - linesearch context 5959 5960 Level: beginner 5961 5962 Notes: 5963 It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`. 5964 5965 You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options. 5966 5967 .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()` 5968 @*/ 5969 PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5970 { 5971 const char *optionsprefix; 5972 5973 PetscFunctionBegin; 5974 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5975 PetscAssertPointer(linesearch, 2); 5976 if (!snes->linesearch) { 5977 PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 5978 PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 5979 PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 5980 PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 5981 PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 5982 } 5983 *linesearch = snes->linesearch; 5984 PetscFunctionReturn(PETSC_SUCCESS); 5985 } 5986