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 isascii, 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, &isascii)); 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 (isascii) { 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 Parameter: 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 Parameter: 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 DM dm; 3531 3532 PetscFunctionBegin; 3533 if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3534 PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3535 if (--((PetscObject)*snes)->refct > 0) { 3536 *snes = NULL; 3537 PetscFunctionReturn(PETSC_SUCCESS); 3538 } 3539 3540 PetscCall(SNESReset(*snes)); 3541 PetscCall(SNESDestroy(&(*snes)->npc)); 3542 3543 /* if memory was published with SAWs then destroy it */ 3544 PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3545 PetscTryTypeMethod(*snes, destroy); 3546 3547 dm = (*snes)->dm; 3548 while (dm) { 3549 PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 3550 PetscCall(DMGetCoarseDM(dm, &dm)); 3551 } 3552 3553 PetscCall(DMDestroy(&(*snes)->dm)); 3554 PetscCall(KSPDestroy(&(*snes)->ksp)); 3555 PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 3556 3557 PetscCall(PetscFree((*snes)->kspconvctx)); 3558 if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP)); 3559 if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3560 PetscCall(SNESMonitorCancel(*snes)); 3561 PetscCall(SNESConvergedReasonViewCancel(*snes)); 3562 PetscCall(PetscHeaderDestroy(snes)); 3563 PetscFunctionReturn(PETSC_SUCCESS); 3564 } 3565 3566 /* ----------- Routines to set solver parameters ---------- */ 3567 3568 /*@ 3569 SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`. 3570 3571 Logically Collective 3572 3573 Input Parameters: 3574 + snes - the `SNES` context 3575 - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3576 the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3577 3578 Options Database Keys: 3579 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 3580 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3581 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 3582 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3583 3584 Level: intermediate 3585 3586 Notes: 3587 The default is 1 3588 3589 The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3590 3591 `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3592 3593 .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3594 `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3595 @*/ 3596 PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3597 { 3598 PetscFunctionBegin; 3599 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3600 PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 3601 PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3602 PetscValidLogicalCollectiveInt(snes, lag, 2); 3603 snes->lagpreconditioner = lag; 3604 PetscFunctionReturn(PETSC_SUCCESS); 3605 } 3606 3607 /*@ 3608 SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3609 3610 Logically Collective 3611 3612 Input Parameters: 3613 + snes - the `SNES` context 3614 - steps - the number of refinements to do, defaults to 0 3615 3616 Options Database Key: 3617 . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3618 3619 Level: intermediate 3620 3621 Notes: 3622 Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement. 3623 3624 Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3625 3626 .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 3627 `SNESSetDM()`, `SNESSolve()` 3628 @*/ 3629 PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3630 { 3631 PetscFunctionBegin; 3632 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3633 PetscValidLogicalCollectiveInt(snes, steps, 2); 3634 snes->gridsequence = steps; 3635 PetscFunctionReturn(PETSC_SUCCESS); 3636 } 3637 3638 /*@ 3639 SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3640 3641 Logically Collective 3642 3643 Input Parameter: 3644 . snes - the `SNES` context 3645 3646 Output Parameter: 3647 . steps - the number of refinements to do, defaults to 0 3648 3649 Level: intermediate 3650 3651 .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3652 @*/ 3653 PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3654 { 3655 PetscFunctionBegin; 3656 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3657 *steps = snes->gridsequence; 3658 PetscFunctionReturn(PETSC_SUCCESS); 3659 } 3660 3661 /*@ 3662 SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3663 3664 Not Collective 3665 3666 Input Parameter: 3667 . snes - the `SNES` context 3668 3669 Output Parameter: 3670 . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3671 the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3672 3673 Level: intermediate 3674 3675 Notes: 3676 The default is 1 3677 3678 The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3679 3680 .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3681 @*/ 3682 PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3683 { 3684 PetscFunctionBegin; 3685 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3686 *lag = snes->lagpreconditioner; 3687 PetscFunctionReturn(PETSC_SUCCESS); 3688 } 3689 3690 /*@ 3691 SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3692 often the preconditioner is rebuilt. 3693 3694 Logically Collective 3695 3696 Input Parameters: 3697 + snes - the `SNES` context 3698 - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3699 the Jacobian is built etc. -2 means rebuild at next chance but then never again 3700 3701 Options Database Keys: 3702 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 3703 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3704 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 3705 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3706 3707 Level: intermediate 3708 3709 Notes: 3710 The default is 1 3711 3712 The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3713 3714 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 3715 at the next Newton step but never again (unless it is reset to another value) 3716 3717 .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3718 @*/ 3719 PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3720 { 3721 PetscFunctionBegin; 3722 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3723 PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 3724 PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3725 PetscValidLogicalCollectiveInt(snes, lag, 2); 3726 snes->lagjacobian = lag; 3727 PetscFunctionReturn(PETSC_SUCCESS); 3728 } 3729 3730 /*@ 3731 SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3732 3733 Not Collective 3734 3735 Input Parameter: 3736 . snes - the `SNES` context 3737 3738 Output Parameter: 3739 . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3740 the Jacobian is built etc. 3741 3742 Level: intermediate 3743 3744 Notes: 3745 The default is 1 3746 3747 The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3748 3749 .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3750 3751 @*/ 3752 PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3753 { 3754 PetscFunctionBegin; 3755 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3756 *lag = snes->lagjacobian; 3757 PetscFunctionReturn(PETSC_SUCCESS); 3758 } 3759 3760 /*@ 3761 SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 3762 3763 Logically collective 3764 3765 Input Parameters: 3766 + snes - the `SNES` context 3767 - flg - jacobian lagging persists if true 3768 3769 Options Database Keys: 3770 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 3771 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3772 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 3773 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3774 3775 Level: advanced 3776 3777 Notes: 3778 Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3779 3780 This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 3781 several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 3782 timesteps may present huge efficiency gains. 3783 3784 .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 3785 @*/ 3786 PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3787 { 3788 PetscFunctionBegin; 3789 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3790 PetscValidLogicalCollectiveBool(snes, flg, 2); 3791 snes->lagjac_persist = flg; 3792 PetscFunctionReturn(PETSC_SUCCESS); 3793 } 3794 3795 /*@ 3796 SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 3797 3798 Logically Collective 3799 3800 Input Parameters: 3801 + snes - the `SNES` context 3802 - flg - preconditioner lagging persists if true 3803 3804 Options Database Keys: 3805 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 3806 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3807 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 3808 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3809 3810 Level: developer 3811 3812 Notes: 3813 Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3814 3815 This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 3816 by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 3817 several timesteps may present huge efficiency gains. 3818 3819 .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 3820 @*/ 3821 PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3822 { 3823 PetscFunctionBegin; 3824 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3825 PetscValidLogicalCollectiveBool(snes, flg, 2); 3826 snes->lagpre_persist = flg; 3827 PetscFunctionReturn(PETSC_SUCCESS); 3828 } 3829 3830 /*@ 3831 SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3832 3833 Logically Collective 3834 3835 Input Parameters: 3836 + snes - the `SNES` context 3837 - force - `PETSC_TRUE` require at least one iteration 3838 3839 Options Database Key: 3840 . -snes_force_iteration <force> - Sets forcing an iteration 3841 3842 Level: intermediate 3843 3844 Note: 3845 This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3846 3847 .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()` 3848 @*/ 3849 PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3850 { 3851 PetscFunctionBegin; 3852 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3853 snes->forceiteration = force; 3854 PetscFunctionReturn(PETSC_SUCCESS); 3855 } 3856 3857 /*@ 3858 SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 3859 3860 Logically Collective 3861 3862 Input Parameter: 3863 . snes - the `SNES` context 3864 3865 Output Parameter: 3866 . force - `PETSC_TRUE` requires at least one iteration. 3867 3868 Level: intermediate 3869 3870 .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()` 3871 @*/ 3872 PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3873 { 3874 PetscFunctionBegin; 3875 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3876 *force = snes->forceiteration; 3877 PetscFunctionReturn(PETSC_SUCCESS); 3878 } 3879 3880 /*@ 3881 SNESSetTolerances - Sets various parameters used in `SNES` convergence tests. 3882 3883 Logically Collective 3884 3885 Input Parameters: 3886 + snes - the `SNES` context 3887 . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $ 3888 . rtol - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $ 3889 . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 3890 . maxit - the maximum number of iterations allowed in the solver, default 50. 3891 - maxf - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000 3892 3893 Options Database Keys: 3894 + -snes_atol <abstol> - Sets `abstol` 3895 . -snes_rtol <rtol> - Sets `rtol` 3896 . -snes_stol <stol> - Sets `stol` 3897 . -snes_max_it <maxit> - Sets `maxit` 3898 - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum) 3899 3900 Level: intermediate 3901 3902 Note: 3903 All parameters must be non-negative 3904 3905 Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`. 3906 The default value is the value in the object when its type is set. 3907 3908 Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations. 3909 3910 Fortran Note: 3911 Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL` 3912 3913 .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 3914 @*/ 3915 PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3916 { 3917 PetscFunctionBegin; 3918 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3919 PetscValidLogicalCollectiveReal(snes, abstol, 2); 3920 PetscValidLogicalCollectiveReal(snes, rtol, 3); 3921 PetscValidLogicalCollectiveReal(snes, stol, 4); 3922 PetscValidLogicalCollectiveInt(snes, maxit, 5); 3923 PetscValidLogicalCollectiveInt(snes, maxf, 6); 3924 3925 if (abstol == (PetscReal)PETSC_DETERMINE) { 3926 snes->abstol = snes->default_abstol; 3927 } else if (abstol != (PetscReal)PETSC_CURRENT) { 3928 PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3929 snes->abstol = abstol; 3930 } 3931 3932 if (rtol == (PetscReal)PETSC_DETERMINE) { 3933 snes->rtol = snes->default_rtol; 3934 } else if (rtol != (PetscReal)PETSC_CURRENT) { 3935 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); 3936 snes->rtol = rtol; 3937 } 3938 3939 if (stol == (PetscReal)PETSC_DETERMINE) { 3940 snes->stol = snes->default_stol; 3941 } else if (stol != (PetscReal)PETSC_CURRENT) { 3942 PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3943 snes->stol = stol; 3944 } 3945 3946 if (maxit == PETSC_DETERMINE) { 3947 snes->max_its = snes->default_max_its; 3948 } else if (maxit == PETSC_UNLIMITED) { 3949 snes->max_its = PETSC_INT_MAX; 3950 } else if (maxit != PETSC_CURRENT) { 3951 PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3952 snes->max_its = maxit; 3953 } 3954 3955 if (maxf == PETSC_DETERMINE) { 3956 snes->max_funcs = snes->default_max_funcs; 3957 } else if (maxf == PETSC_UNLIMITED || maxf == -1) { 3958 snes->max_funcs = PETSC_UNLIMITED; 3959 } else if (maxf != PETSC_CURRENT) { 3960 PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf); 3961 snes->max_funcs = maxf; 3962 } 3963 PetscFunctionReturn(PETSC_SUCCESS); 3964 } 3965 3966 /*@ 3967 SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3968 3969 Logically Collective 3970 3971 Input Parameters: 3972 + snes - the `SNES` context 3973 - 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 3974 is stopped due to divergence. 3975 3976 Options Database Key: 3977 . -snes_divergence_tolerance <divtol> - Sets `divtol` 3978 3979 Level: intermediate 3980 3981 Notes: 3982 Use `PETSC_DETERMINE` to use the default value from when the object's type was set. 3983 3984 Fortran Note: 3985 Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL` 3986 3987 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()` 3988 @*/ 3989 PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 3990 { 3991 PetscFunctionBegin; 3992 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3993 PetscValidLogicalCollectiveReal(snes, divtol, 2); 3994 3995 if (divtol == (PetscReal)PETSC_DETERMINE) { 3996 snes->divtol = snes->default_divtol; 3997 } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) { 3998 snes->divtol = PETSC_UNLIMITED; 3999 } else if (divtol != (PetscReal)PETSC_CURRENT) { 4000 PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol); 4001 snes->divtol = divtol; 4002 } 4003 PetscFunctionReturn(PETSC_SUCCESS); 4004 } 4005 4006 /*@ 4007 SNESGetTolerances - Gets various parameters used in `SNES` convergence tests. 4008 4009 Not Collective 4010 4011 Input Parameter: 4012 . snes - the `SNES` context 4013 4014 Output Parameters: 4015 + atol - the absolute convergence tolerance 4016 . rtol - the relative convergence tolerance 4017 . stol - convergence tolerance in terms of the norm of the change in the solution between steps 4018 . maxit - the maximum number of iterations allowed 4019 - maxf - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound 4020 4021 Level: intermediate 4022 4023 Notes: 4024 See `SNESSetTolerances()` for details on the parameters. 4025 4026 The user can specify `NULL` for any parameter that is not needed. 4027 4028 .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 4029 @*/ 4030 PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 4031 { 4032 PetscFunctionBegin; 4033 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4034 if (atol) *atol = snes->abstol; 4035 if (rtol) *rtol = snes->rtol; 4036 if (stol) *stol = snes->stol; 4037 if (maxit) *maxit = snes->max_its; 4038 if (maxf) *maxf = snes->max_funcs; 4039 PetscFunctionReturn(PETSC_SUCCESS); 4040 } 4041 4042 /*@ 4043 SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 4044 4045 Not Collective 4046 4047 Input Parameters: 4048 + snes - the `SNES` context 4049 - divtol - divergence tolerance 4050 4051 Level: intermediate 4052 4053 .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 4054 @*/ 4055 PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 4056 { 4057 PetscFunctionBegin; 4058 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4059 if (divtol) *divtol = snes->divtol; 4060 PetscFunctionReturn(PETSC_SUCCESS); 4061 } 4062 4063 PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 4064 4065 PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 4066 { 4067 PetscDrawLG lg; 4068 PetscReal x, y, per; 4069 PetscViewer v = (PetscViewer)monctx; 4070 static PetscReal prev; /* should be in the context */ 4071 PetscDraw draw; 4072 4073 PetscFunctionBegin; 4074 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 4075 PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 4076 if (!n) PetscCall(PetscDrawLGReset(lg)); 4077 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4078 PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 4079 x = (PetscReal)n; 4080 if (rnorm > 0.0) y = PetscLog10Real(rnorm); 4081 else y = -15.0; 4082 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4083 if (n < 20 || !(n % 5) || snes->reason) { 4084 PetscCall(PetscDrawLGDraw(lg)); 4085 PetscCall(PetscDrawLGSave(lg)); 4086 } 4087 4088 PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 4089 if (!n) PetscCall(PetscDrawLGReset(lg)); 4090 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4091 PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 4092 PetscCall(SNESMonitorRange_Private(snes, n, &per)); 4093 x = (PetscReal)n; 4094 y = 100.0 * per; 4095 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4096 if (n < 20 || !(n % 5) || snes->reason) { 4097 PetscCall(PetscDrawLGDraw(lg)); 4098 PetscCall(PetscDrawLGSave(lg)); 4099 } 4100 4101 PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 4102 if (!n) { 4103 prev = rnorm; 4104 PetscCall(PetscDrawLGReset(lg)); 4105 } 4106 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4107 PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 4108 x = (PetscReal)n; 4109 y = (prev - rnorm) / prev; 4110 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4111 if (n < 20 || !(n % 5) || snes->reason) { 4112 PetscCall(PetscDrawLGDraw(lg)); 4113 PetscCall(PetscDrawLGSave(lg)); 4114 } 4115 4116 PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 4117 if (!n) PetscCall(PetscDrawLGReset(lg)); 4118 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4119 PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 4120 x = (PetscReal)n; 4121 y = (prev - rnorm) / (prev * per); 4122 if (n > 2) { /*skip initial crazy value */ 4123 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4124 } 4125 if (n < 20 || !(n % 5) || snes->reason) { 4126 PetscCall(PetscDrawLGDraw(lg)); 4127 PetscCall(PetscDrawLGSave(lg)); 4128 } 4129 prev = rnorm; 4130 PetscFunctionReturn(PETSC_SUCCESS); 4131 } 4132 4133 /*@ 4134 SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 4135 4136 Collective 4137 4138 Input Parameters: 4139 + snes - the `SNES` context 4140 . it - current iteration 4141 . xnorm - 2-norm of current iterate 4142 . snorm - 2-norm of current step 4143 - fnorm - 2-norm of function 4144 4145 Level: developer 4146 4147 Note: 4148 This routine is called by the `SNESSolve()` implementations. 4149 It does not typically need to be called by the user. 4150 4151 .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 4152 @*/ 4153 PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 4154 { 4155 PetscFunctionBegin; 4156 if (!snes->reason) { 4157 if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 4158 if (it == snes->max_its && !snes->reason) { 4159 if (snes->normschedule == SNES_NORM_ALWAYS) { 4160 PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 4161 snes->reason = SNES_DIVERGED_MAX_IT; 4162 } else snes->reason = SNES_CONVERGED_ITS; 4163 } 4164 } 4165 PetscFunctionReturn(PETSC_SUCCESS); 4166 } 4167 4168 /*@ 4169 SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database 4170 4171 Collective 4172 4173 Input Parameters: 4174 + snes - nonlinear solver context obtained from `SNESCreate()` 4175 . iter - current iteration number 4176 - rnorm - current relative norm of the residual 4177 4178 Level: developer 4179 4180 Note: 4181 This routine is called by the `SNESSolve()` implementations. 4182 It does not typically need to be called by the user. 4183 4184 .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4185 @*/ 4186 PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4187 { 4188 PetscInt i, n = snes->numbermonitors; 4189 4190 PetscFunctionBegin; 4191 if (n > 0) SNESCheckFunctionNorm(snes, rnorm); 4192 PetscCall(VecLockReadPush(snes->vec_sol)); 4193 for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 4194 PetscCall(VecLockReadPop(snes->vec_sol)); 4195 PetscFunctionReturn(PETSC_SUCCESS); 4196 } 4197 4198 /* ------------ Routines to set performance monitoring options ----------- */ 4199 4200 /*MC 4201 SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4202 4203 Synopsis: 4204 #include <petscsnes.h> 4205 PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4206 4207 Collective 4208 4209 Input Parameters: 4210 + snes - the `SNES` context 4211 . its - iteration number 4212 . norm - 2-norm function value (may be estimated) 4213 - mctx - [optional] monitoring context 4214 4215 Level: advanced 4216 4217 .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()` 4218 M*/ 4219 4220 /*@C 4221 SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 4222 iteration of the `SNES` nonlinear solver to display the iteration's 4223 progress. 4224 4225 Logically Collective 4226 4227 Input Parameters: 4228 + snes - the `SNES` context 4229 . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4230 . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 4231 - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4232 4233 Options Database Keys: 4234 + -snes_monitor - sets `SNESMonitorDefault()` 4235 . -snes_monitor draw::draw_lg - sets line graph monitor, 4236 - -snes_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to `SNESMonitorSet()`, but does not cancel those set via 4237 the options database. 4238 4239 Level: intermediate 4240 4241 Note: 4242 Several different monitoring routines may be set by calling 4243 `SNESMonitorSet()` multiple times; all will be called in the 4244 order in which they were set. 4245 4246 Fortran Note: 4247 Only a single monitor function can be set for each `SNES` object 4248 4249 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn` 4250 @*/ 4251 PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy) 4252 { 4253 PetscInt i; 4254 PetscBool identical; 4255 4256 PetscFunctionBegin; 4257 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4258 for (i = 0; i < snes->numbermonitors; i++) { 4259 PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 4260 if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4261 } 4262 PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 4263 snes->monitor[snes->numbermonitors] = f; 4264 snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4265 snes->monitorcontext[snes->numbermonitors++] = mctx; 4266 PetscFunctionReturn(PETSC_SUCCESS); 4267 } 4268 4269 /*@ 4270 SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 4271 4272 Logically Collective 4273 4274 Input Parameter: 4275 . snes - the `SNES` context 4276 4277 Options Database Key: 4278 . -snes_monitor_cancel - cancels all monitors that have been hardwired 4279 into a code by calls to `SNESMonitorSet()`, but does not cancel those 4280 set via the options database 4281 4282 Level: intermediate 4283 4284 Note: 4285 There is no way to clear one specific monitor from a `SNES` object. 4286 4287 .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()` 4288 @*/ 4289 PetscErrorCode SNESMonitorCancel(SNES snes) 4290 { 4291 PetscInt i; 4292 4293 PetscFunctionBegin; 4294 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4295 for (i = 0; i < snes->numbermonitors; i++) { 4296 if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4297 } 4298 snes->numbermonitors = 0; 4299 PetscFunctionReturn(PETSC_SUCCESS); 4300 } 4301 4302 /*MC 4303 SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4304 4305 Synopsis: 4306 #include <petscsnes.h> 4307 PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4308 4309 Collective 4310 4311 Input Parameters: 4312 + snes - the `SNES` context 4313 . it - current iteration (0 is the first and is before any Newton step) 4314 . xnorm - 2-norm of current iterate 4315 . gnorm - 2-norm of current step 4316 . f - 2-norm of function 4317 - cctx - [optional] convergence context 4318 4319 Output Parameter: 4320 . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4321 4322 Level: intermediate 4323 4324 .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 4325 M*/ 4326 4327 /*@C 4328 SNESSetConvergenceTest - Sets the function that is to be used 4329 to test for convergence of the nonlinear iterative solution. 4330 4331 Logically Collective 4332 4333 Input Parameters: 4334 + snes - the `SNES` context 4335 . SNESConvergenceTestFunction - routine to test for convergence 4336 . cctx - [optional] context for private data for the convergence routine (may be `NULL`) 4337 - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 4338 4339 Level: advanced 4340 4341 .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 4342 @*/ 4343 PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *)) 4344 { 4345 PetscFunctionBegin; 4346 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4347 if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 4348 if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP)); 4349 snes->ops->converged = SNESConvergenceTestFunction; 4350 snes->ops->convergeddestroy = destroy; 4351 snes->cnvP = cctx; 4352 PetscFunctionReturn(PETSC_SUCCESS); 4353 } 4354 4355 /*@ 4356 SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation 4357 4358 Not Collective 4359 4360 Input Parameter: 4361 . snes - the `SNES` context 4362 4363 Output Parameter: 4364 . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4365 4366 Options Database Key: 4367 . -snes_converged_reason - prints the reason to standard out 4368 4369 Level: intermediate 4370 4371 Note: 4372 Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4373 4374 .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4375 @*/ 4376 PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4377 { 4378 PetscFunctionBegin; 4379 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4380 PetscAssertPointer(reason, 2); 4381 *reason = snes->reason; 4382 PetscFunctionReturn(PETSC_SUCCESS); 4383 } 4384 4385 /*@C 4386 SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4387 4388 Not Collective 4389 4390 Input Parameter: 4391 . snes - the `SNES` context 4392 4393 Output Parameter: 4394 . strreason - a human readable string that describes `SNES` converged reason 4395 4396 Level: beginner 4397 4398 .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4399 @*/ 4400 PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4401 { 4402 PetscFunctionBegin; 4403 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4404 PetscAssertPointer(strreason, 2); 4405 *strreason = SNESConvergedReasons[snes->reason]; 4406 PetscFunctionReturn(PETSC_SUCCESS); 4407 } 4408 4409 /*@ 4410 SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 4411 4412 Not Collective 4413 4414 Input Parameters: 4415 + snes - the `SNES` context 4416 - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 4417 manual pages for the individual convergence tests for complete lists 4418 4419 Level: developer 4420 4421 Developer Note: 4422 Called inside the various `SNESSolve()` implementations 4423 4424 .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 4425 @*/ 4426 PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4427 { 4428 PetscFunctionBegin; 4429 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4430 PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 4431 snes->reason = reason; 4432 PetscFunctionReturn(PETSC_SUCCESS); 4433 } 4434 4435 /*@ 4436 SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4437 4438 Logically Collective 4439 4440 Input Parameters: 4441 + snes - iterative context obtained from `SNESCreate()` 4442 . a - array to hold history, this array will contain the function norms computed at each step 4443 . its - integer array holds the number of linear iterations for each solve. 4444 . na - size of `a` and `its` 4445 - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4446 else it continues storing new values for new nonlinear solves after the old ones 4447 4448 Level: intermediate 4449 4450 Notes: 4451 If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` (or, deprecated, `PETSC_DEFAULT`) then a 4452 default array of length 1,000 is allocated. 4453 4454 This routine is useful, e.g., when running a code for purposes 4455 of accurate performance monitoring, when no I/O should be done 4456 during the section of code that is being timed. 4457 4458 If the arrays run out of space after a number of iterations then the later values are not saved in the history 4459 4460 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4461 @*/ 4462 PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4463 { 4464 PetscFunctionBegin; 4465 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4466 if (a) PetscAssertPointer(a, 2); 4467 if (its) PetscAssertPointer(its, 3); 4468 if (!a) { 4469 if (na == PETSC_DECIDE) na = 1000; 4470 PetscCall(PetscCalloc2(na, &a, na, &its)); 4471 snes->conv_hist_alloc = PETSC_TRUE; 4472 } 4473 snes->conv_hist = a; 4474 snes->conv_hist_its = its; 4475 snes->conv_hist_max = (size_t)na; 4476 snes->conv_hist_len = 0; 4477 snes->conv_hist_reset = reset; 4478 PetscFunctionReturn(PETSC_SUCCESS); 4479 } 4480 4481 #if defined(PETSC_HAVE_MATLAB) 4482 #include <engine.h> /* MATLAB include file */ 4483 #include <mex.h> /* MATLAB include file */ 4484 4485 PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4486 { 4487 mxArray *mat; 4488 PetscInt i; 4489 PetscReal *ar; 4490 4491 mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4492 ar = (PetscReal *)mxGetData(mat); 4493 for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 4494 return mat; 4495 } 4496 #endif 4497 4498 /*@C 4499 SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4500 4501 Not Collective 4502 4503 Input Parameter: 4504 . snes - iterative context obtained from `SNESCreate()` 4505 4506 Output Parameters: 4507 + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4508 . its - integer array holds the number of linear iterations (or 4509 negative if not converged) for each solve. 4510 - na - size of `a` and `its` 4511 4512 Level: intermediate 4513 4514 Note: 4515 This routine is useful, e.g., when running a code for purposes 4516 of accurate performance monitoring, when no I/O should be done 4517 during the section of code that is being timed. 4518 4519 Fortran Notes: 4520 Return the arrays with ``SNESRestoreConvergenceHistory()` 4521 4522 Use the arguments 4523 .vb 4524 PetscReal, pointer :: a(:) 4525 PetscInt, pointer :: its(:) 4526 .ve 4527 4528 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4529 @*/ 4530 PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4531 { 4532 PetscFunctionBegin; 4533 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4534 if (a) *a = snes->conv_hist; 4535 if (its) *its = snes->conv_hist_its; 4536 if (na) *na = (PetscInt)snes->conv_hist_len; 4537 PetscFunctionReturn(PETSC_SUCCESS); 4538 } 4539 4540 /*@C 4541 SNESSetUpdate - Sets the general-purpose update function called 4542 at the beginning of every iteration of the nonlinear solve. Specifically 4543 it is called just before the Jacobian is "evaluated" and after the function 4544 evaluation. 4545 4546 Logically Collective 4547 4548 Input Parameters: 4549 + snes - The nonlinear solver context 4550 - func - The update function; for calling sequence see `SNESUpdateFn` 4551 4552 Level: advanced 4553 4554 Notes: 4555 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 4556 to `SNESSetFunction()`, or `SNESSetPicard()` 4557 This is not used by most users, and it is intended to provide a general hook that is run 4558 right before the direction step is computed. 4559 4560 Users are free to modify the current residual vector, 4561 the current linearization point, or any other vector associated to the specific solver used. 4562 If such modifications take place, it is the user responsibility to update all the relevant 4563 vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like 4564 .vb 4565 PetscErrorCode update(SNES snes, PetscInt iteration) 4566 { 4567 PetscFunctionBeginUser; 4568 if (iteration > 0) { 4569 // update the model parameters here 4570 Vec x,f; 4571 PetscCall(SNESGetSolution(snes,&x)); 4572 PetcCall(SNESGetFunction(snes,&f,NULL,NULL)); 4573 PetscCall(SNESComputeFunction(snes,x,f)); 4574 } 4575 PetscFunctionReturn(PETSC_SUCCESS); 4576 } 4577 .ve 4578 4579 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. 4580 4581 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 4582 `SNESMonitorSet()` 4583 @*/ 4584 PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func) 4585 { 4586 PetscFunctionBegin; 4587 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4588 snes->ops->update = func; 4589 PetscFunctionReturn(PETSC_SUCCESS); 4590 } 4591 4592 /*@ 4593 SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 4594 4595 Collective 4596 4597 Input Parameters: 4598 + snes - iterative context obtained from `SNESCreate()` 4599 - viewer - the viewer to display the reason 4600 4601 Options Database Keys: 4602 + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4603 - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4604 4605 Level: beginner 4606 4607 Note: 4608 To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4609 use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 4610 4611 .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4612 `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4613 `SNESConvergedReasonViewFromOptions()`, 4614 `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 4615 @*/ 4616 PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4617 { 4618 PetscViewerFormat format; 4619 PetscBool isAscii; 4620 4621 PetscFunctionBegin; 4622 if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 4623 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 4624 if (isAscii) { 4625 PetscCall(PetscViewerGetFormat(viewer, &format)); 4626 PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1)); 4627 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 4628 DM dm; 4629 Vec u; 4630 PetscDS prob; 4631 PetscInt Nf, f; 4632 PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 4633 void **exactCtx; 4634 PetscReal error; 4635 4636 PetscCall(SNESGetDM(snes, &dm)); 4637 PetscCall(SNESGetSolution(snes, &u)); 4638 PetscCall(DMGetDS(dm, &prob)); 4639 PetscCall(PetscDSGetNumFields(prob, &Nf)); 4640 PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 4641 for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 4642 PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 4643 PetscCall(PetscFree2(exactSol, exactCtx)); 4644 if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 4645 else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 4646 } 4647 if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 4648 if (((PetscObject)snes)->prefix) { 4649 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 4650 } else { 4651 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 4652 } 4653 } else if (snes->reason <= 0) { 4654 if (((PetscObject)snes)->prefix) { 4655 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve did not converge due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 4656 } else { 4657 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 4658 } 4659 } 4660 PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1)); 4661 } 4662 PetscFunctionReturn(PETSC_SUCCESS); 4663 } 4664 4665 /*@C 4666 SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4667 end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4668 4669 Logically Collective 4670 4671 Input Parameters: 4672 + snes - the `SNES` context 4673 . f - the `SNESConvergedReason` view function 4674 . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 4675 - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4676 4677 Calling sequence of `f`: 4678 + snes - the `SNES` context 4679 - vctx - [optional] context for private data for the function 4680 4681 Options Database Keys: 4682 + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4683 - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4684 calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4685 4686 Level: intermediate 4687 4688 Note: 4689 Several different converged reason view routines may be set by calling 4690 `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4691 order in which they were set. 4692 4693 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`, 4694 `PetscCtxDestroyFn` 4695 @*/ 4696 PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy) 4697 { 4698 PetscInt i; 4699 PetscBool identical; 4700 4701 PetscFunctionBegin; 4702 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4703 for (i = 0; i < snes->numberreasonviews; i++) { 4704 PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 4705 if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4706 } 4707 PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4708 snes->reasonview[snes->numberreasonviews] = f; 4709 snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4710 snes->reasonviewcontext[snes->numberreasonviews++] = vctx; 4711 PetscFunctionReturn(PETSC_SUCCESS); 4712 } 4713 4714 /*@ 4715 SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 4716 All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist. 4717 4718 Collective 4719 4720 Input Parameter: 4721 . snes - the `SNES` object 4722 4723 Level: advanced 4724 4725 .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4726 `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 4727 @*/ 4728 PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4729 { 4730 static PetscBool incall = PETSC_FALSE; 4731 4732 PetscFunctionBegin; 4733 if (incall) PetscFunctionReturn(PETSC_SUCCESS); 4734 incall = PETSC_TRUE; 4735 4736 /* All user-provided viewers are called first, if they exist. */ 4737 for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4738 4739 /* Call PETSc default routine if users ask for it */ 4740 if (snes->convergedreasonviewer) { 4741 PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat)); 4742 PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer)); 4743 PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer)); 4744 } 4745 incall = PETSC_FALSE; 4746 PetscFunctionReturn(PETSC_SUCCESS); 4747 } 4748 4749 /*@ 4750 SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object 4751 4752 Collective 4753 4754 Input Parameters: 4755 + snes - the `SNES` context 4756 . b - the constant part of the equation $F(x) = b$, or `NULL` to use zero. 4757 - x - the solution vector. 4758 4759 Level: beginner 4760 4761 Note: 4762 The user should initialize the vector, `x`, with the initial guess 4763 for the nonlinear solve prior to calling `SNESSolve()` . 4764 4765 .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4766 `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4767 `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()` 4768 @*/ 4769 PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4770 { 4771 PetscBool flg; 4772 PetscInt grid; 4773 Vec xcreated = NULL; 4774 DM dm; 4775 4776 PetscFunctionBegin; 4777 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4778 if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4779 if (x) PetscCheckSameComm(snes, 1, x, 3); 4780 if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4781 if (b) PetscCheckSameComm(snes, 1, b, 2); 4782 4783 /* High level operations using the nonlinear solver */ 4784 { 4785 PetscViewer viewer; 4786 PetscViewerFormat format; 4787 PetscInt num; 4788 PetscBool flg; 4789 static PetscBool incall = PETSC_FALSE; 4790 4791 if (!incall) { 4792 /* Estimate the convergence rate of the discretization */ 4793 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 4794 if (flg) { 4795 PetscConvEst conv; 4796 DM dm; 4797 PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 4798 PetscInt Nf; 4799 4800 incall = PETSC_TRUE; 4801 PetscCall(SNESGetDM(snes, &dm)); 4802 PetscCall(DMGetNumFields(dm, &Nf)); 4803 PetscCall(PetscCalloc1(Nf, &alpha)); 4804 PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 4805 PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 4806 PetscCall(PetscConvEstSetFromOptions(conv)); 4807 PetscCall(PetscConvEstSetUp(conv)); 4808 PetscCall(PetscConvEstGetConvRate(conv, alpha)); 4809 PetscCall(PetscViewerPushFormat(viewer, format)); 4810 PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 4811 PetscCall(PetscViewerPopFormat(viewer)); 4812 PetscCall(PetscViewerDestroy(&viewer)); 4813 PetscCall(PetscConvEstDestroy(&conv)); 4814 PetscCall(PetscFree(alpha)); 4815 incall = PETSC_FALSE; 4816 } 4817 /* Adaptively refine the initial grid */ 4818 num = 1; 4819 PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 4820 if (flg) { 4821 DMAdaptor adaptor; 4822 4823 incall = PETSC_TRUE; 4824 PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4825 PetscCall(DMAdaptorSetSolver(adaptor, snes)); 4826 PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 4827 PetscCall(DMAdaptorSetFromOptions(adaptor)); 4828 PetscCall(DMAdaptorSetUp(adaptor)); 4829 PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 4830 PetscCall(DMAdaptorDestroy(&adaptor)); 4831 incall = PETSC_FALSE; 4832 } 4833 /* Use grid sequencing to adapt */ 4834 num = 0; 4835 PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 4836 if (num) { 4837 DMAdaptor adaptor; 4838 const char *prefix; 4839 4840 incall = PETSC_TRUE; 4841 PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4842 PetscCall(SNESGetOptionsPrefix(snes, &prefix)); 4843 PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix)); 4844 PetscCall(DMAdaptorSetSolver(adaptor, snes)); 4845 PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 4846 PetscCall(DMAdaptorSetFromOptions(adaptor)); 4847 PetscCall(DMAdaptorSetUp(adaptor)); 4848 PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view")); 4849 PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 4850 PetscCall(DMAdaptorDestroy(&adaptor)); 4851 incall = PETSC_FALSE; 4852 } 4853 } 4854 } 4855 if (!x) x = snes->vec_sol; 4856 if (!x) { 4857 PetscCall(SNESGetDM(snes, &dm)); 4858 PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4859 x = xcreated; 4860 } 4861 PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4862 4863 for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4864 for (grid = 0; grid < snes->gridsequence + 1; grid++) { 4865 /* set solution vector */ 4866 if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 4867 PetscCall(VecDestroy(&snes->vec_sol)); 4868 snes->vec_sol = x; 4869 PetscCall(SNESGetDM(snes, &dm)); 4870 4871 /* set affine vector if provided */ 4872 if (b) PetscCall(PetscObjectReference((PetscObject)b)); 4873 PetscCall(VecDestroy(&snes->vec_rhs)); 4874 snes->vec_rhs = b; 4875 4876 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"); 4877 PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4878 PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector"); 4879 if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 4880 PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 4881 PetscCall(SNESSetUp(snes)); 4882 4883 if (!grid) { 4884 if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4885 } 4886 4887 if (snes->conv_hist_reset) snes->conv_hist_len = 0; 4888 PetscCall(SNESResetCounters(snes)); 4889 snes->reason = SNES_CONVERGED_ITERATING; 4890 PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4891 PetscUseTypeMethod(snes, solve); 4892 PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 4893 PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4894 snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 4895 4896 if (snes->lagjac_persist) snes->jac_iter += snes->iter; 4897 if (snes->lagpre_persist) snes->pre_iter += snes->iter; 4898 4899 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 4900 if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4901 /* Call converged reason views. This may involve user-provided viewers as well */ 4902 PetscCall(SNESConvergedReasonViewFromOptions(snes)); 4903 4904 if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 4905 if (snes->reason < 0) break; 4906 if (grid < snes->gridsequence) { 4907 DM fine; 4908 Vec xnew; 4909 Mat interp; 4910 4911 PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 4912 PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 4913 PetscCall(DMGetCoordinatesLocalSetUp(fine)); 4914 PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 4915 PetscCall(DMCreateGlobalVector(fine, &xnew)); 4916 PetscCall(MatInterpolate(interp, x, xnew)); 4917 PetscCall(DMInterpolate(snes->dm, interp, fine)); 4918 PetscCall(MatDestroy(&interp)); 4919 x = xnew; 4920 4921 PetscCall(SNESReset(snes)); 4922 PetscCall(SNESSetDM(snes, fine)); 4923 PetscCall(SNESResetFromOptions(snes)); 4924 PetscCall(DMDestroy(&fine)); 4925 PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4926 } 4927 } 4928 PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 4929 PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 4930 PetscCall(DMMonitor(snes->dm)); 4931 PetscCall(SNESMonitorPauseFinal_Internal(snes)); 4932 4933 PetscCall(VecDestroy(&xcreated)); 4934 PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 4935 PetscFunctionReturn(PETSC_SUCCESS); 4936 } 4937 4938 /* --------- Internal routines for SNES Package --------- */ 4939 4940 /*@ 4941 SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES` 4942 4943 Collective 4944 4945 Input Parameters: 4946 + snes - the `SNES` context 4947 - type - a known method 4948 4949 Options Database Key: 4950 . -snes_type <type> - Sets the method; use -help for a list 4951 of available methods (for instance, newtonls or newtontr) 4952 4953 Level: intermediate 4954 4955 Notes: 4956 See `SNESType` for available methods (for instance) 4957 + `SNESNEWTONLS` - Newton's method with line search 4958 (systems of nonlinear equations) 4959 - `SNESNEWTONTR` - Newton's method with trust region 4960 (systems of nonlinear equations) 4961 4962 Normally, it is best to use the `SNESSetFromOptions()` command and then 4963 set the `SNES` solver type from the options database rather than by using 4964 this routine. Using the options database provides the user with 4965 maximum flexibility in evaluating the many nonlinear solvers. 4966 The `SNESSetType()` routine is provided for those situations where it 4967 is necessary to set the nonlinear solver independently of the command 4968 line or options database. This might be the case, for example, when 4969 the choice of solver changes during the execution of the program, 4970 and the user's application is taking responsibility for choosing the 4971 appropriate method. 4972 4973 Developer Note: 4974 `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4975 the constructor in that list and calls it to create the specific object. 4976 4977 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 4978 @*/ 4979 PetscErrorCode SNESSetType(SNES snes, SNESType type) 4980 { 4981 PetscBool match; 4982 PetscErrorCode (*r)(SNES); 4983 4984 PetscFunctionBegin; 4985 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4986 PetscAssertPointer(type, 2); 4987 4988 PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 4989 if (match) PetscFunctionReturn(PETSC_SUCCESS); 4990 4991 PetscCall(PetscFunctionListFind(SNESList, type, &r)); 4992 PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 4993 /* Destroy the previous private SNES context */ 4994 PetscTryTypeMethod(snes, destroy); 4995 /* Reinitialize type-specific function pointers in SNESOps structure */ 4996 snes->ops->reset = NULL; 4997 snes->ops->setup = NULL; 4998 snes->ops->solve = NULL; 4999 snes->ops->view = NULL; 5000 snes->ops->setfromoptions = NULL; 5001 snes->ops->destroy = NULL; 5002 5003 /* It may happen the user has customized the line search before calling SNESSetType */ 5004 if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5005 5006 /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 5007 snes->setupcalled = PETSC_FALSE; 5008 5009 PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 5010 PetscCall((*r)(snes)); 5011 PetscFunctionReturn(PETSC_SUCCESS); 5012 } 5013 5014 /*@ 5015 SNESGetType - Gets the `SNES` method type and name (as a string). 5016 5017 Not Collective 5018 5019 Input Parameter: 5020 . snes - nonlinear solver context 5021 5022 Output Parameter: 5023 . type - `SNES` method (a character string) 5024 5025 Level: intermediate 5026 5027 .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 5028 @*/ 5029 PetscErrorCode SNESGetType(SNES snes, SNESType *type) 5030 { 5031 PetscFunctionBegin; 5032 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5033 PetscAssertPointer(type, 2); 5034 *type = ((PetscObject)snes)->type_name; 5035 PetscFunctionReturn(PETSC_SUCCESS); 5036 } 5037 5038 /*@ 5039 SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 5040 5041 Logically Collective 5042 5043 Input Parameters: 5044 + snes - the `SNES` context obtained from `SNESCreate()` 5045 - u - the solution vector 5046 5047 Level: beginner 5048 5049 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 5050 @*/ 5051 PetscErrorCode SNESSetSolution(SNES snes, Vec u) 5052 { 5053 DM dm; 5054 5055 PetscFunctionBegin; 5056 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5057 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 5058 PetscCall(PetscObjectReference((PetscObject)u)); 5059 PetscCall(VecDestroy(&snes->vec_sol)); 5060 5061 snes->vec_sol = u; 5062 5063 PetscCall(SNESGetDM(snes, &dm)); 5064 PetscCall(DMShellSetGlobalVector(dm, u)); 5065 PetscFunctionReturn(PETSC_SUCCESS); 5066 } 5067 5068 /*@ 5069 SNESGetSolution - Returns the vector where the approximate solution is 5070 stored. This is the fine grid solution when using `SNESSetGridSequence()`. 5071 5072 Not Collective, but `x` is parallel if `snes` is parallel 5073 5074 Input Parameter: 5075 . snes - the `SNES` context 5076 5077 Output Parameter: 5078 . x - the solution 5079 5080 Level: intermediate 5081 5082 .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 5083 @*/ 5084 PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 5085 { 5086 PetscFunctionBegin; 5087 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5088 PetscAssertPointer(x, 2); 5089 *x = snes->vec_sol; 5090 PetscFunctionReturn(PETSC_SUCCESS); 5091 } 5092 5093 /*@ 5094 SNESGetSolutionUpdate - Returns the vector where the solution update is 5095 stored. 5096 5097 Not Collective, but `x` is parallel if `snes` is parallel 5098 5099 Input Parameter: 5100 . snes - the `SNES` context 5101 5102 Output Parameter: 5103 . x - the solution update 5104 5105 Level: advanced 5106 5107 .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 5108 @*/ 5109 PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 5110 { 5111 PetscFunctionBegin; 5112 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5113 PetscAssertPointer(x, 2); 5114 *x = snes->vec_sol_update; 5115 PetscFunctionReturn(PETSC_SUCCESS); 5116 } 5117 5118 /*@C 5119 SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 5120 5121 Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 5122 5123 Input Parameter: 5124 . snes - the `SNES` context 5125 5126 Output Parameters: 5127 + r - the vector that is used to store residuals (or `NULL` if you don't want it) 5128 . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn` 5129 - ctx - the function context (or `NULL` if you don't want it) 5130 5131 Level: advanced 5132 5133 Note: 5134 The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 5135 5136 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn` 5137 @*/ 5138 PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx) 5139 { 5140 DM dm; 5141 5142 PetscFunctionBegin; 5143 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5144 if (r) { 5145 if (!snes->vec_func) { 5146 if (snes->vec_rhs) { 5147 PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 5148 } else if (snes->vec_sol) { 5149 PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 5150 } else if (snes->dm) { 5151 PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 5152 } 5153 } 5154 *r = snes->vec_func; 5155 } 5156 PetscCall(SNESGetDM(snes, &dm)); 5157 PetscCall(DMSNESGetFunction(dm, f, ctx)); 5158 PetscFunctionReturn(PETSC_SUCCESS); 5159 } 5160 5161 /*@C 5162 SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5163 5164 Input Parameter: 5165 . snes - the `SNES` context 5166 5167 Output Parameters: 5168 + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence 5169 - ctx - the function context (or `NULL`) 5170 5171 Level: advanced 5172 5173 .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn` 5174 @*/ 5175 PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx) 5176 { 5177 DM dm; 5178 5179 PetscFunctionBegin; 5180 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5181 PetscCall(SNESGetDM(snes, &dm)); 5182 PetscCall(DMSNESGetNGS(dm, f, ctx)); 5183 PetscFunctionReturn(PETSC_SUCCESS); 5184 } 5185 5186 /*@ 5187 SNESSetOptionsPrefix - Sets the prefix used for searching for all 5188 `SNES` options in the database. 5189 5190 Logically Collective 5191 5192 Input Parameters: 5193 + snes - the `SNES` context 5194 - prefix - the prefix to prepend to all option names 5195 5196 Level: advanced 5197 5198 Note: 5199 A hyphen (-) must NOT be given at the beginning of the prefix name. 5200 The first character of all runtime options is AUTOMATICALLY the hyphen. 5201 5202 .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 5203 @*/ 5204 PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5205 { 5206 PetscFunctionBegin; 5207 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5208 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 5209 if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 5210 if (snes->linesearch) { 5211 PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 5212 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 5213 } 5214 PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 5215 PetscFunctionReturn(PETSC_SUCCESS); 5216 } 5217 5218 /*@ 5219 SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5220 `SNES` options in the database. 5221 5222 Logically Collective 5223 5224 Input Parameters: 5225 + snes - the `SNES` context 5226 - prefix - the prefix to prepend to all option names 5227 5228 Level: advanced 5229 5230 Note: 5231 A hyphen (-) must NOT be given at the beginning of the prefix name. 5232 The first character of all runtime options is AUTOMATICALLY the hyphen. 5233 5234 .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 5235 @*/ 5236 PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5237 { 5238 PetscFunctionBegin; 5239 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5240 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 5241 if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 5242 if (snes->linesearch) { 5243 PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 5244 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 5245 } 5246 PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 5247 PetscFunctionReturn(PETSC_SUCCESS); 5248 } 5249 5250 /*@ 5251 SNESGetOptionsPrefix - Gets the prefix used for searching for all 5252 `SNES` options in the database. 5253 5254 Not Collective 5255 5256 Input Parameter: 5257 . snes - the `SNES` context 5258 5259 Output Parameter: 5260 . prefix - pointer to the prefix string used 5261 5262 Level: advanced 5263 5264 .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 5265 @*/ 5266 PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5267 { 5268 PetscFunctionBegin; 5269 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5270 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 5271 PetscFunctionReturn(PETSC_SUCCESS); 5272 } 5273 5274 /*@C 5275 SNESRegister - Adds a method to the nonlinear solver package. 5276 5277 Not Collective 5278 5279 Input Parameters: 5280 + sname - name of a new user-defined solver 5281 - function - routine to create method context 5282 5283 Level: advanced 5284 5285 Note: 5286 `SNESRegister()` may be called multiple times to add several user-defined solvers. 5287 5288 Example Usage: 5289 .vb 5290 SNESRegister("my_solver", MySolverCreate); 5291 .ve 5292 5293 Then, your solver can be chosen with the procedural interface via 5294 .vb 5295 SNESSetType(snes, "my_solver") 5296 .ve 5297 or at runtime via the option 5298 .vb 5299 -snes_type my_solver 5300 .ve 5301 5302 .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 5303 @*/ 5304 PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5305 { 5306 PetscFunctionBegin; 5307 PetscCall(SNESInitializePackage()); 5308 PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 5309 PetscFunctionReturn(PETSC_SUCCESS); 5310 } 5311 5312 PetscErrorCode SNESTestLocalMin(SNES snes) 5313 { 5314 PetscInt N, i, j; 5315 Vec u, uh, fh; 5316 PetscScalar value; 5317 PetscReal norm; 5318 5319 PetscFunctionBegin; 5320 PetscCall(SNESGetSolution(snes, &u)); 5321 PetscCall(VecDuplicate(u, &uh)); 5322 PetscCall(VecDuplicate(u, &fh)); 5323 5324 /* currently only works for sequential */ 5325 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 5326 PetscCall(VecGetSize(u, &N)); 5327 for (i = 0; i < N; i++) { 5328 PetscCall(VecCopy(u, uh)); 5329 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5330 for (j = -10; j < 11; j++) { 5331 value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 5332 PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5333 PetscCall(SNESComputeFunction(snes, uh, fh)); 5334 PetscCall(VecNorm(fh, NORM_2, &norm)); 5335 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5336 value = -value; 5337 PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5338 } 5339 } 5340 PetscCall(VecDestroy(&uh)); 5341 PetscCall(VecDestroy(&fh)); 5342 PetscFunctionReturn(PETSC_SUCCESS); 5343 } 5344 5345 /*@ 5346 SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 5347 computing relative tolerance for linear solvers within an inexact 5348 Newton method. 5349 5350 Logically Collective 5351 5352 Input Parameters: 5353 + snes - `SNES` context 5354 - flag - `PETSC_TRUE` or `PETSC_FALSE` 5355 5356 Options Database Keys: 5357 + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 5358 . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 5359 . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 5360 . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 5361 . -snes_ksp_ew_gamma <gamma> - Sets gamma 5362 . -snes_ksp_ew_alpha <alpha> - Sets alpha 5363 . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 5364 - -snes_ksp_ew_threshold <threshold> - Sets threshold 5365 5366 Level: advanced 5367 5368 Note: 5369 The default is to use a constant relative tolerance for 5370 the inner linear solvers. Alternatively, one can use the 5371 Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance 5372 is reset at each Newton iteration according progress of the nonlinear 5373 solver. 5374 5375 .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 5376 @*/ 5377 PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5378 { 5379 PetscFunctionBegin; 5380 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5381 PetscValidLogicalCollectiveBool(snes, flag, 2); 5382 snes->ksp_ewconv = flag; 5383 PetscFunctionReturn(PETSC_SUCCESS); 5384 } 5385 5386 /*@ 5387 SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 5388 for computing relative tolerance for linear solvers within an 5389 inexact Newton method. 5390 5391 Not Collective 5392 5393 Input Parameter: 5394 . snes - `SNES` context 5395 5396 Output Parameter: 5397 . flag - `PETSC_TRUE` or `PETSC_FALSE` 5398 5399 Level: advanced 5400 5401 .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 5402 @*/ 5403 PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5404 { 5405 PetscFunctionBegin; 5406 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5407 PetscAssertPointer(flag, 2); 5408 *flag = snes->ksp_ewconv; 5409 PetscFunctionReturn(PETSC_SUCCESS); 5410 } 5411 5412 /*@ 5413 SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 5414 convergence criteria for the linear solvers within an inexact 5415 Newton method. 5416 5417 Logically Collective 5418 5419 Input Parameters: 5420 + snes - `SNES` context 5421 . version - version 1, 2 (default is 2), 3 or 4 5422 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 5423 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5424 . gamma - multiplicative factor for version 2 rtol computation 5425 (0 <= gamma2 <= 1) 5426 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 5427 . alpha2 - power for safeguard 5428 - threshold - threshold for imposing safeguard (0 < threshold < 1) 5429 5430 Level: advanced 5431 5432 Notes: 5433 Version 3 was contributed by Luis Chacon, June 2006. 5434 5435 Use `PETSC_CURRENT` to retain the default for any of the parameters. 5436 5437 .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 5438 @*/ 5439 PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5440 { 5441 SNESKSPEW *kctx; 5442 5443 PetscFunctionBegin; 5444 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5445 kctx = (SNESKSPEW *)snes->kspconvctx; 5446 PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5447 PetscValidLogicalCollectiveInt(snes, version, 2); 5448 PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5449 PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5450 PetscValidLogicalCollectiveReal(snes, gamma, 5); 5451 PetscValidLogicalCollectiveReal(snes, alpha, 6); 5452 PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5453 PetscValidLogicalCollectiveReal(snes, threshold, 8); 5454 5455 if (version != PETSC_CURRENT) kctx->version = version; 5456 if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0; 5457 if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max; 5458 if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma; 5459 if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha; 5460 if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2; 5461 if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold; 5462 5463 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); 5464 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); 5465 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); 5466 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); 5467 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); 5468 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); 5469 PetscFunctionReturn(PETSC_SUCCESS); 5470 } 5471 5472 /*@ 5473 SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 5474 convergence criteria for the linear solvers within an inexact 5475 Newton method. 5476 5477 Not Collective 5478 5479 Input Parameter: 5480 . snes - `SNES` context 5481 5482 Output Parameters: 5483 + version - version 1, 2 (default is 2), 3 or 4 5484 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 5485 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5486 . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 5487 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 5488 . alpha2 - power for safeguard 5489 - threshold - threshold for imposing safeguard (0 < threshold < 1) 5490 5491 Level: advanced 5492 5493 .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 5494 @*/ 5495 PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5496 { 5497 SNESKSPEW *kctx; 5498 5499 PetscFunctionBegin; 5500 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5501 kctx = (SNESKSPEW *)snes->kspconvctx; 5502 PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5503 if (version) *version = kctx->version; 5504 if (rtol_0) *rtol_0 = kctx->rtol_0; 5505 if (rtol_max) *rtol_max = kctx->rtol_max; 5506 if (gamma) *gamma = kctx->gamma; 5507 if (alpha) *alpha = kctx->alpha; 5508 if (alpha2) *alpha2 = kctx->alpha2; 5509 if (threshold) *threshold = kctx->threshold; 5510 PetscFunctionReturn(PETSC_SUCCESS); 5511 } 5512 5513 PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5514 { 5515 SNES snes = (SNES)ctx; 5516 SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 5517 PetscReal rtol = PETSC_CURRENT, stol; 5518 5519 PetscFunctionBegin; 5520 if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 5521 if (!snes->iter) { 5522 rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 5523 PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 5524 } else { 5525 PetscCheck(kctx->version >= 1 && kctx->version <= 4, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only versions 1-4 are supported: %" PetscInt_FMT, kctx->version); 5526 if (kctx->version == 1) { 5527 rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 5528 stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 5529 if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 5530 } else if (kctx->version == 2) { 5531 rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 5532 stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 5533 if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 5534 } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 5535 rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 5536 /* safeguard: avoid sharp decrease of rtol */ 5537 stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 5538 stol = PetscMax(rtol, stol); 5539 rtol = PetscMin(kctx->rtol_0, stol); 5540 /* safeguard: avoid oversolving */ 5541 stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 5542 stol = PetscMax(rtol, stol); 5543 rtol = PetscMin(kctx->rtol_0, stol); 5544 } else /* if (kctx->version == 4) */ { 5545 /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 5546 PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 5547 PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 5548 PetscReal rk = ared / pred; 5549 if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 5550 else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 5551 else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 5552 else rtol = kctx->v4_m2 * kctx->rtol_last; 5553 5554 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; 5555 kctx->rtol_last_2 = kctx->rtol_last; 5556 kctx->rk_last_2 = kctx->rk_last; 5557 kctx->rk_last = rk; 5558 } 5559 } 5560 /* safeguard: avoid rtol greater than rtol_max */ 5561 rtol = PetscMin(rtol, kctx->rtol_max); 5562 PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT)); 5563 PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 5564 PetscFunctionReturn(PETSC_SUCCESS); 5565 } 5566 5567 PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5568 { 5569 SNES snes = (SNES)ctx; 5570 SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 5571 PCSide pcside; 5572 Vec lres; 5573 5574 PetscFunctionBegin; 5575 if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 5576 PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 5577 kctx->norm_last = snes->norm; 5578 if (kctx->version == 1 || kctx->version == 4) { 5579 PC pc; 5580 PetscBool getRes; 5581 5582 PetscCall(KSPGetPC(ksp, &pc)); 5583 PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 5584 if (!getRes) { 5585 KSPNormType normtype; 5586 5587 PetscCall(KSPGetNormType(ksp, &normtype)); 5588 getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 5589 } 5590 PetscCall(KSPGetPCSide(ksp, &pcside)); 5591 if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 5592 PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 5593 } else { 5594 /* KSP residual is preconditioned residual */ 5595 /* compute true linear residual norm */ 5596 Mat J; 5597 PetscCall(KSPGetOperators(ksp, &J, NULL)); 5598 PetscCall(VecDuplicate(b, &lres)); 5599 PetscCall(MatMult(J, x, lres)); 5600 PetscCall(VecAYPX(lres, -1.0, b)); 5601 PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 5602 PetscCall(VecDestroy(&lres)); 5603 } 5604 } 5605 PetscFunctionReturn(PETSC_SUCCESS); 5606 } 5607 5608 /*@ 5609 SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5610 5611 Not Collective, but if `snes` is parallel, then `ksp` is parallel 5612 5613 Input Parameter: 5614 . snes - the `SNES` context 5615 5616 Output Parameter: 5617 . ksp - the `KSP` context 5618 5619 Level: beginner 5620 5621 Notes: 5622 The user can then directly manipulate the `KSP` context to set various 5623 options, etc. Likewise, the user can then extract and manipulate the 5624 `PC` contexts as well. 5625 5626 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. 5627 5628 .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5629 @*/ 5630 PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5631 { 5632 PetscFunctionBegin; 5633 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5634 PetscAssertPointer(ksp, 2); 5635 5636 if (!snes->ksp) { 5637 PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 5638 PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5639 5640 PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 5641 PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5642 5643 PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 5644 PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5645 } 5646 *ksp = snes->ksp; 5647 PetscFunctionReturn(PETSC_SUCCESS); 5648 } 5649 5650 #include <petsc/private/dmimpl.h> 5651 /*@ 5652 SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners 5653 5654 Logically Collective 5655 5656 Input Parameters: 5657 + snes - the nonlinear solver context 5658 - dm - the `DM`, cannot be `NULL` 5659 5660 Level: intermediate 5661 5662 Note: 5663 A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5664 even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5665 problems using the same function space. 5666 5667 .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 5668 @*/ 5669 PetscErrorCode SNESSetDM(SNES snes, DM dm) 5670 { 5671 KSP ksp; 5672 DMSNES sdm; 5673 5674 PetscFunctionBegin; 5675 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5676 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 5677 PetscCall(PetscObjectReference((PetscObject)dm)); 5678 if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 5679 if (snes->dm->dmsnes && !dm->dmsnes) { 5680 PetscCall(DMCopyDMSNES(snes->dm, dm)); 5681 PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5682 if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 5683 } 5684 PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 5685 PetscCall(DMDestroy(&snes->dm)); 5686 } 5687 snes->dm = dm; 5688 snes->dmAuto = PETSC_FALSE; 5689 5690 PetscCall(SNESGetKSP(snes, &ksp)); 5691 PetscCall(KSPSetDM(ksp, dm)); 5692 PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5693 if (snes->npc) { 5694 PetscCall(SNESSetDM(snes->npc, snes->dm)); 5695 PetscCall(SNESSetNPCSide(snes, snes->npcside)); 5696 } 5697 PetscFunctionReturn(PETSC_SUCCESS); 5698 } 5699 5700 /*@ 5701 SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners 5702 5703 Not Collective but `dm` obtained is parallel on `snes` 5704 5705 Input Parameter: 5706 . snes - the `SNES` context 5707 5708 Output Parameter: 5709 . dm - the `DM` 5710 5711 Level: intermediate 5712 5713 .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 5714 @*/ 5715 PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5716 { 5717 PetscFunctionBegin; 5718 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5719 if (!snes->dm) { 5720 PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5721 snes->dmAuto = PETSC_TRUE; 5722 } 5723 *dm = snes->dm; 5724 PetscFunctionReturn(PETSC_SUCCESS); 5725 } 5726 5727 /*@ 5728 SNESSetNPC - Sets the nonlinear preconditioner to be used. 5729 5730 Collective 5731 5732 Input Parameters: 5733 + snes - iterative context obtained from `SNESCreate()` 5734 - npc - the `SNES` nonlinear preconditioner object 5735 5736 Options Database Key: 5737 . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5738 5739 Level: developer 5740 5741 Notes: 5742 This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API. 5743 5744 Only some `SNESType` can use a nonlinear preconditioner 5745 5746 .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 5747 @*/ 5748 PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5749 { 5750 PetscFunctionBegin; 5751 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5752 PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5753 PetscCheckSameComm(snes, 1, npc, 2); 5754 PetscCall(PetscObjectReference((PetscObject)npc)); 5755 PetscCall(SNESDestroy(&snes->npc)); 5756 snes->npc = npc; 5757 PetscFunctionReturn(PETSC_SUCCESS); 5758 } 5759 5760 /*@ 5761 SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 5762 5763 Not Collective; but any changes to the obtained the `pc` object must be applied collectively 5764 5765 Input Parameter: 5766 . snes - iterative context obtained from `SNESCreate()` 5767 5768 Output Parameter: 5769 . pc - the `SNES` preconditioner context 5770 5771 Options Database Key: 5772 . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5773 5774 Level: advanced 5775 5776 Notes: 5777 If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will 5778 be used as the nonlinear preconditioner for the current `SNES`. 5779 5780 The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 5781 `SNES`. These may be overwritten if needed. 5782 5783 Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner 5784 5785 .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 5786 @*/ 5787 PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5788 { 5789 const char *optionsprefix; 5790 5791 PetscFunctionBegin; 5792 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5793 PetscAssertPointer(pc, 2); 5794 if (!snes->npc) { 5795 void *ctx; 5796 5797 PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 5798 PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 5799 PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 5800 PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 5801 PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5802 if (snes->ops->usercompute) { 5803 PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy)); 5804 } else { 5805 PetscCall(SNESGetApplicationContext(snes, &ctx)); 5806 PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5807 } 5808 PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 5809 } 5810 *pc = snes->npc; 5811 PetscFunctionReturn(PETSC_SUCCESS); 5812 } 5813 5814 /*@ 5815 SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES` 5816 5817 Not Collective 5818 5819 Input Parameter: 5820 . snes - iterative context obtained from `SNESCreate()` 5821 5822 Output Parameter: 5823 . has_npc - whether the `SNES` has a nonlinear preconditioner or not 5824 5825 Level: developer 5826 5827 .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 5828 @*/ 5829 PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5830 { 5831 PetscFunctionBegin; 5832 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5833 PetscAssertPointer(has_npc, 2); 5834 *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE; 5835 PetscFunctionReturn(PETSC_SUCCESS); 5836 } 5837 5838 /*@ 5839 SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`. 5840 5841 Logically Collective 5842 5843 Input Parameter: 5844 . snes - iterative context obtained from `SNESCreate()` 5845 5846 Output Parameter: 5847 . side - the preconditioning side, where side is one of 5848 .vb 5849 PC_LEFT - left preconditioning 5850 PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5851 .ve 5852 5853 Options Database Key: 5854 . -snes_npc_side <right,left> - nonlinear preconditioner side 5855 5856 Level: intermediate 5857 5858 Note: 5859 `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 5860 5861 .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5862 @*/ 5863 PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5864 { 5865 PetscFunctionBegin; 5866 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5867 PetscValidLogicalCollectiveEnum(snes, side, 2); 5868 if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 5869 PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5870 snes->npcside = side; 5871 PetscFunctionReturn(PETSC_SUCCESS); 5872 } 5873 5874 /*@ 5875 SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`. 5876 5877 Not Collective 5878 5879 Input Parameter: 5880 . snes - iterative context obtained from `SNESCreate()` 5881 5882 Output Parameter: 5883 . side - the preconditioning side, where side is one of 5884 .vb 5885 `PC_LEFT` - left preconditioning 5886 `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5887 .ve 5888 5889 Level: intermediate 5890 5891 .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5892 @*/ 5893 PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5894 { 5895 PetscFunctionBegin; 5896 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5897 PetscAssertPointer(side, 2); 5898 *side = snes->npcside; 5899 PetscFunctionReturn(PETSC_SUCCESS); 5900 } 5901 5902 /*@ 5903 SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES` 5904 5905 Collective 5906 5907 Input Parameters: 5908 + snes - iterative context obtained from `SNESCreate()` 5909 - linesearch - the linesearch object 5910 5911 Level: developer 5912 5913 Note: 5914 This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 5915 to configure it using the API). 5916 5917 .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 5918 @*/ 5919 PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5920 { 5921 PetscFunctionBegin; 5922 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5923 PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 5924 PetscCheckSameComm(snes, 1, linesearch, 2); 5925 PetscCall(PetscObjectReference((PetscObject)linesearch)); 5926 PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5927 5928 snes->linesearch = linesearch; 5929 PetscFunctionReturn(PETSC_SUCCESS); 5930 } 5931 5932 /*@ 5933 SNESGetLineSearch - Returns the line search associated with the `SNES`. 5934 5935 Not Collective 5936 5937 Input Parameter: 5938 . snes - iterative context obtained from `SNESCreate()` 5939 5940 Output Parameter: 5941 . linesearch - linesearch context 5942 5943 Level: beginner 5944 5945 Notes: 5946 It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`. 5947 5948 You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options. 5949 5950 .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()` 5951 @*/ 5952 PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5953 { 5954 const char *optionsprefix; 5955 5956 PetscFunctionBegin; 5957 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5958 PetscAssertPointer(linesearch, 2); 5959 if (!snes->linesearch) { 5960 PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 5961 PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 5962 PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 5963 PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 5964 PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 5965 } 5966 *linesearch = snes->linesearch; 5967 PetscFunctionReturn(PETSC_SUCCESS); 5968 } 5969