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