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