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_EXTERN 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 PetscErrorCode SNESTestJacobian(SNES snes) 2712 { 2713 Mat A, B, C, D, jacobian; 2714 Vec x = snes->vec_sol, f; 2715 PetscReal nrm, gnorm; 2716 PetscReal threshold = 1.e-5; 2717 MatType mattype; 2718 PetscInt m, n, M, N; 2719 void *functx; 2720 PetscBool complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose; 2721 PetscViewer viewer, mviewer; 2722 MPI_Comm comm; 2723 PetscInt tabs; 2724 static PetscBool directionsprinted = PETSC_FALSE; 2725 PetscViewerFormat format; 2726 2727 PetscFunctionBegin; 2728 PetscObjectOptionsBegin((PetscObject)snes); 2729 PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test)); 2730 PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL)); 2731 PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL)); 2732 PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print)); 2733 PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)")); 2734 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)); 2735 PetscOptionsEnd(); 2736 if (!test) PetscFunctionReturn(PETSC_SUCCESS); 2737 2738 PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 2739 PetscCall(PetscViewerASCIIGetStdout(comm, &viewer)); 2740 PetscCall(PetscViewerASCIIGetTab(viewer, &tabs)); 2741 PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel)); 2742 PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian -------------\n")); 2743 if (!complete_print && !directionsprinted) { 2744 PetscCall(PetscViewerASCIIPrintf(viewer, " Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n")); 2745 PetscCall(PetscViewerASCIIPrintf(viewer, " of hand-coded and finite difference Jacobian entries greater than <threshold>.\n")); 2746 } 2747 if (!directionsprinted) { 2748 PetscCall(PetscViewerASCIIPrintf(viewer, " Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n")); 2749 PetscCall(PetscViewerASCIIPrintf(viewer, " O(1.e-8), the hand-coded Jacobian is probably correct.\n")); 2750 directionsprinted = PETSC_TRUE; 2751 } 2752 if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format)); 2753 2754 PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg)); 2755 if (!flg) jacobian = snes->jacobian; 2756 else jacobian = snes->jacobian_pre; 2757 2758 if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL)); 2759 else PetscCall(PetscObjectReference((PetscObject)x)); 2760 PetscCall(VecDuplicate(x, &f)); 2761 2762 /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 2763 PetscCall(SNESComputeFunction(snes, x, f)); 2764 PetscCall(VecDestroy(&f)); 2765 PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose)); 2766 while (jacobian) { 2767 Mat JT = NULL, Jsave = NULL; 2768 2769 if (istranspose) { 2770 PetscCall(MatCreateTranspose(jacobian, &JT)); 2771 Jsave = jacobian; 2772 jacobian = JT; 2773 } 2774 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, "")); 2775 if (flg) { 2776 A = jacobian; 2777 PetscCall(PetscObjectReference((PetscObject)A)); 2778 } else { 2779 PetscCall(MatComputeOperator(jacobian, MATAIJ, &A)); 2780 } 2781 2782 PetscCall(MatGetType(A, &mattype)); 2783 PetscCall(MatGetSize(A, &M, &N)); 2784 PetscCall(MatGetLocalSize(A, &m, &n)); 2785 PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 2786 PetscCall(MatSetType(B, mattype)); 2787 PetscCall(MatSetSizes(B, m, n, M, N)); 2788 PetscCall(MatSetBlockSizesFromMats(B, A, A)); 2789 PetscCall(MatSetUp(B)); 2790 PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2791 2792 PetscCall(SNESGetFunction(snes, NULL, NULL, &functx)); 2793 PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx)); 2794 2795 PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D)); 2796 PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 2797 PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm)); 2798 PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm)); 2799 PetscCall(MatDestroy(&D)); 2800 if (!gnorm) gnorm = 1; /* just in case */ 2801 PetscCall(PetscViewerASCIIPrintf(viewer, " ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm)); 2802 2803 if (complete_print) { 2804 PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded Jacobian ----------\n")); 2805 PetscCall(MatView(A, mviewer)); 2806 PetscCall(PetscViewerASCIIPrintf(viewer, " Finite difference Jacobian ----------\n")); 2807 PetscCall(MatView(B, mviewer)); 2808 } 2809 2810 if (threshold_print || complete_print) { 2811 PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2812 PetscScalar *cvals; 2813 const PetscInt *bcols; 2814 const PetscScalar *bvals; 2815 2816 PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 2817 PetscCall(MatSetType(C, mattype)); 2818 PetscCall(MatSetSizes(C, m, n, M, N)); 2819 PetscCall(MatSetBlockSizesFromMats(C, A, A)); 2820 PetscCall(MatSetUp(C)); 2821 PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 2822 2823 PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN)); 2824 PetscCall(MatGetOwnershipRange(B, &Istart, &Iend)); 2825 2826 for (row = Istart; row < Iend; row++) { 2827 PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals)); 2828 PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals)); 2829 for (j = 0, cncols = 0; j < bncols; j++) { 2830 if (PetscAbsScalar(bvals[j]) > threshold) { 2831 ccols[cncols] = bcols[j]; 2832 cvals[cncols] = bvals[j]; 2833 cncols += 1; 2834 } 2835 } 2836 if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES)); 2837 PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals)); 2838 PetscCall(PetscFree2(ccols, cvals)); 2839 } 2840 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 2841 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 2842 PetscCall(PetscViewerASCIIPrintf(viewer, " Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold)); 2843 PetscCall(MatView(C, complete_print ? mviewer : viewer)); 2844 PetscCall(MatDestroy(&C)); 2845 } 2846 PetscCall(MatDestroy(&A)); 2847 PetscCall(MatDestroy(&B)); 2848 PetscCall(MatDestroy(&JT)); 2849 if (Jsave) jacobian = Jsave; 2850 if (jacobian != snes->jacobian_pre) { 2851 jacobian = snes->jacobian_pre; 2852 PetscCall(PetscViewerASCIIPrintf(viewer, " ---------- Testing Jacobian for preconditioner -------------\n")); 2853 } else jacobian = NULL; 2854 } 2855 PetscCall(VecDestroy(&x)); 2856 if (complete_print) PetscCall(PetscViewerPopFormat(mviewer)); 2857 if (mviewer) PetscCall(PetscViewerDestroy(&mviewer)); 2858 PetscCall(PetscViewerASCIISetTab(viewer, tabs)); 2859 PetscFunctionReturn(PETSC_SUCCESS); 2860 } 2861 2862 /*@ 2863 SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 2864 2865 Collective 2866 2867 Input Parameters: 2868 + snes - the `SNES` context 2869 - X - input vector 2870 2871 Output Parameters: 2872 + A - Jacobian matrix 2873 - B - optional matrix for building the preconditioner, usually the same as `A` 2874 2875 Options Database Keys: 2876 + -snes_lag_preconditioner <lag> - how often to rebuild preconditioner 2877 . -snes_lag_jacobian <lag> - how often to rebuild Jacobian 2878 . -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. 2879 . -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 2880 . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2881 . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2882 . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 2883 . -snes_compare_operator - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner 2884 . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2885 . -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences 2886 . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2887 . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2888 . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold` 2889 . -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences 2890 - -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences 2891 2892 Level: developer 2893 2894 Note: 2895 Most users should not need to explicitly call this routine, as it 2896 is used internally within the nonlinear solvers. 2897 2898 Developer Note: 2899 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 2900 with the `SNESType` of test that has been removed. 2901 2902 .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()` 2903 @*/ 2904 PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B) 2905 { 2906 PetscBool flag; 2907 DM dm; 2908 DMSNES sdm; 2909 KSP ksp; 2910 2911 PetscFunctionBegin; 2912 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 2913 PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 2914 PetscCheckSameComm(snes, 1, X, 2); 2915 PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE)); 2916 PetscCall(SNESGetDM(snes, &dm)); 2917 PetscCall(DMGetDMSNES(dm, &sdm)); 2918 2919 /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */ 2920 if (snes->lagjacobian == -2) { 2921 snes->lagjacobian = -1; 2922 2923 PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n")); 2924 } else if (snes->lagjacobian == -1) { 2925 PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n")); 2926 PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2927 if (flag) { 2928 PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 2929 PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2930 } 2931 PetscFunctionReturn(PETSC_SUCCESS); 2932 } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 2933 PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter)); 2934 PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag)); 2935 if (flag) { 2936 PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 2937 PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2938 } 2939 PetscFunctionReturn(PETSC_SUCCESS); 2940 } 2941 if (snes->npc && snes->npcside == PC_LEFT) { 2942 PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 2943 PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 2944 PetscFunctionReturn(PETSC_SUCCESS); 2945 } 2946 2947 PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B)); 2948 PetscCall(VecLockReadPush(X)); 2949 { 2950 void *ctx; 2951 SNESJacobianFn *J; 2952 PetscCall(DMSNESGetJacobian(dm, &J, &ctx)); 2953 PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx)); 2954 } 2955 PetscCall(VecLockReadPop(X)); 2956 PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B)); 2957 2958 /* attach latest linearization point to the matrix used to construct the preconditioner */ 2959 PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X)); 2960 2961 /* the next line ensures that snes->ksp exists */ 2962 PetscCall(SNESGetKSP(snes, &ksp)); 2963 if (snes->lagpreconditioner == -2) { 2964 PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n")); 2965 PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 2966 snes->lagpreconditioner = -1; 2967 } else if (snes->lagpreconditioner == -1) { 2968 PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n")); 2969 PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 2970 } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 2971 PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter)); 2972 PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE)); 2973 } else { 2974 PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n")); 2975 PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE)); 2976 } 2977 2978 /* monkey business to allow testing Jacobians in multilevel solvers. 2979 This is needed because the SNESTestXXX interface does not accept vectors and matrices */ 2980 { 2981 Vec xsave = snes->vec_sol; 2982 Mat jacobiansave = snes->jacobian; 2983 Mat jacobian_presave = snes->jacobian_pre; 2984 2985 snes->vec_sol = X; 2986 snes->jacobian = A; 2987 snes->jacobian_pre = B; 2988 PetscCall(SNESTestFunction(snes)); 2989 PetscCall(SNESTestJacobian(snes)); 2990 2991 snes->vec_sol = xsave; 2992 snes->jacobian = jacobiansave; 2993 snes->jacobian_pre = jacobian_presave; 2994 } 2995 2996 { 2997 PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE; 2998 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag)); 2999 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw)); 3000 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour)); 3001 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator)); 3002 if (flag || flag_draw || flag_contour) { 3003 Mat Bexp_mine = NULL, Bexp, FDexp; 3004 PetscViewer vdraw, vstdout; 3005 PetscBool flg; 3006 if (flag_operator) { 3007 PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine)); 3008 Bexp = Bexp_mine; 3009 } else { 3010 /* See if the matrix used to construct the preconditioner can be viewed and added directly */ 3011 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, "")); 3012 if (flg) Bexp = B; 3013 else { 3014 /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 3015 PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine)); 3016 Bexp = Bexp_mine; 3017 } 3018 } 3019 PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp)); 3020 PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL)); 3021 PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 3022 if (flag_draw || flag_contour) { 3023 PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 3024 if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 3025 } else vdraw = NULL; 3026 PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian")); 3027 if (flag) PetscCall(MatView(Bexp, vstdout)); 3028 if (vdraw) PetscCall(MatView(Bexp, vdraw)); 3029 PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n")); 3030 if (flag) PetscCall(MatView(FDexp, vstdout)); 3031 if (vdraw) PetscCall(MatView(FDexp, vdraw)); 3032 PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN)); 3033 PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n")); 3034 if (flag) PetscCall(MatView(FDexp, vstdout)); 3035 if (vdraw) { /* Always use contour for the difference */ 3036 PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 3037 PetscCall(MatView(FDexp, vdraw)); 3038 PetscCall(PetscViewerPopFormat(vdraw)); 3039 } 3040 if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 3041 PetscCall(PetscViewerDestroy(&vdraw)); 3042 PetscCall(MatDestroy(&Bexp_mine)); 3043 PetscCall(MatDestroy(&FDexp)); 3044 } 3045 } 3046 { 3047 PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE; 3048 PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON; 3049 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag)); 3050 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display)); 3051 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw)); 3052 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour)); 3053 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold)); 3054 if (flag_threshold) { 3055 PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL)); 3056 PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL)); 3057 } 3058 if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 3059 Mat Bfd; 3060 PetscViewer vdraw, vstdout; 3061 MatColoring coloring; 3062 ISColoring iscoloring; 3063 MatFDColoring matfdcoloring; 3064 SNESFunctionFn *func; 3065 void *funcctx; 3066 PetscReal norm1, norm2, normmax; 3067 3068 PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd)); 3069 PetscCall(MatColoringCreate(Bfd, &coloring)); 3070 PetscCall(MatColoringSetType(coloring, MATCOLORINGSL)); 3071 PetscCall(MatColoringSetFromOptions(coloring)); 3072 PetscCall(MatColoringApply(coloring, &iscoloring)); 3073 PetscCall(MatColoringDestroy(&coloring)); 3074 PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring)); 3075 PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 3076 PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring)); 3077 PetscCall(ISColoringDestroy(&iscoloring)); 3078 3079 /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 3080 PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx)); 3081 PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))func, funcctx)); 3082 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix)); 3083 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_")); 3084 PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 3085 PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes)); 3086 PetscCall(MatFDColoringDestroy(&matfdcoloring)); 3087 3088 PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout)); 3089 if (flag_draw || flag_contour) { 3090 PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw)); 3091 if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 3092 } else vdraw = NULL; 3093 PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n")); 3094 if (flag_display) PetscCall(MatView(B, vstdout)); 3095 if (vdraw) PetscCall(MatView(B, vdraw)); 3096 PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n")); 3097 if (flag_display) PetscCall(MatView(Bfd, vstdout)); 3098 if (vdraw) PetscCall(MatView(Bfd, vdraw)); 3099 PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN)); 3100 PetscCall(MatNorm(Bfd, NORM_1, &norm1)); 3101 PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2)); 3102 PetscCall(MatNorm(Bfd, NORM_MAX, &normmax)); 3103 PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax)); 3104 if (flag_display) PetscCall(MatView(Bfd, vstdout)); 3105 if (vdraw) { /* Always use contour for the difference */ 3106 PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR)); 3107 PetscCall(MatView(Bfd, vdraw)); 3108 PetscCall(PetscViewerPopFormat(vdraw)); 3109 } 3110 if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw)); 3111 3112 if (flag_threshold) { 3113 PetscInt bs, rstart, rend, i; 3114 PetscCall(MatGetBlockSize(B, &bs)); 3115 PetscCall(MatGetOwnershipRange(B, &rstart, &rend)); 3116 for (i = rstart; i < rend; i++) { 3117 const PetscScalar *ba, *ca; 3118 const PetscInt *bj, *cj; 3119 PetscInt bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1; 3120 PetscReal maxentry = 0, maxdiff = 0, maxrdiff = 0; 3121 PetscCall(MatGetRow(B, i, &bn, &bj, &ba)); 3122 PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca)); 3123 PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 3124 for (j = 0; j < bn; j++) { 3125 PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 3126 if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 3127 maxentrycol = bj[j]; 3128 maxentry = PetscRealPart(ba[j]); 3129 } 3130 if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 3131 maxdiffcol = bj[j]; 3132 maxdiff = PetscRealPart(ca[j]); 3133 } 3134 if (rdiff > maxrdiff) { 3135 maxrdiffcol = bj[j]; 3136 maxrdiff = rdiff; 3137 } 3138 } 3139 if (maxrdiff > 1) { 3140 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)); 3141 for (j = 0; j < bn; j++) { 3142 PetscReal rdiff; 3143 rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j])); 3144 if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j]))); 3145 } 3146 PetscCall(PetscViewerASCIIPrintf(vstdout, "\n")); 3147 } 3148 PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba)); 3149 PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca)); 3150 } 3151 } 3152 PetscCall(PetscViewerDestroy(&vdraw)); 3153 PetscCall(MatDestroy(&Bfd)); 3154 } 3155 } 3156 PetscFunctionReturn(PETSC_SUCCESS); 3157 } 3158 3159 /*@C 3160 SNESSetJacobian - Sets the function to compute Jacobian as well as the 3161 location to store the matrix. 3162 3163 Logically Collective 3164 3165 Input Parameters: 3166 + snes - the `SNES` context 3167 . Amat - the matrix that defines the (approximate) Jacobian 3168 . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`. 3169 . J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details 3170 - ctx - [optional] user-defined context for private data for the 3171 Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value) 3172 3173 Level: beginner 3174 3175 Notes: 3176 If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on 3177 each matrix. 3178 3179 If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 3180 space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 3181 3182 If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument 3183 must be a `MatFDColoring`. 3184 3185 Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 3186 example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()` 3187 3188 .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, 3189 `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn` 3190 @*/ 3191 PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx) 3192 { 3193 DM dm; 3194 3195 PetscFunctionBegin; 3196 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3197 if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 3198 if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 3199 if (Amat) PetscCheckSameComm(snes, 1, Amat, 2); 3200 if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3); 3201 PetscCall(SNESGetDM(snes, &dm)); 3202 PetscCall(DMSNESSetJacobian(dm, J, ctx)); 3203 if (Amat) { 3204 PetscCall(PetscObjectReference((PetscObject)Amat)); 3205 PetscCall(MatDestroy(&snes->jacobian)); 3206 3207 snes->jacobian = Amat; 3208 } 3209 if (Pmat) { 3210 PetscCall(PetscObjectReference((PetscObject)Pmat)); 3211 PetscCall(MatDestroy(&snes->jacobian_pre)); 3212 3213 snes->jacobian_pre = Pmat; 3214 } 3215 PetscFunctionReturn(PETSC_SUCCESS); 3216 } 3217 3218 /*@C 3219 SNESGetJacobian - Returns the Jacobian matrix and optionally the user 3220 provided context for evaluating the Jacobian. 3221 3222 Not Collective, but `Mat` object will be parallel if `SNES` is 3223 3224 Input Parameter: 3225 . snes - the nonlinear solver context 3226 3227 Output Parameters: 3228 + Amat - location to stash (approximate) Jacobian matrix (or `NULL`) 3229 . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`) 3230 . J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn` 3231 - ctx - location to stash Jacobian ctx (or `NULL`) 3232 3233 Level: advanced 3234 3235 .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()` 3236 @*/ 3237 PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx) 3238 { 3239 DM dm; 3240 3241 PetscFunctionBegin; 3242 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3243 if (Amat) *Amat = snes->jacobian; 3244 if (Pmat) *Pmat = snes->jacobian_pre; 3245 PetscCall(SNESGetDM(snes, &dm)); 3246 PetscCall(DMSNESGetJacobian(dm, J, ctx)); 3247 PetscFunctionReturn(PETSC_SUCCESS); 3248 } 3249 3250 static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes) 3251 { 3252 DM dm; 3253 DMSNES sdm; 3254 3255 PetscFunctionBegin; 3256 PetscCall(SNESGetDM(snes, &dm)); 3257 PetscCall(DMGetDMSNES(dm, &sdm)); 3258 if (!sdm->ops->computejacobian && snes->jacobian_pre) { 3259 DM dm; 3260 PetscBool isdense, ismf; 3261 3262 PetscCall(SNESGetDM(snes, &dm)); 3263 PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL)); 3264 PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL)); 3265 if (isdense) { 3266 PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL)); 3267 } else if (!ismf) { 3268 PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL)); 3269 } 3270 } 3271 PetscFunctionReturn(PETSC_SUCCESS); 3272 } 3273 3274 /*@ 3275 SNESSetUp - Sets up the internal data structures for the later use 3276 of a nonlinear solver `SNESSolve()`. 3277 3278 Collective 3279 3280 Input Parameter: 3281 . snes - the `SNES` context 3282 3283 Level: advanced 3284 3285 Note: 3286 For basic use of the `SNES` solvers the user does not need to explicitly call 3287 `SNESSetUp()`, since these actions will automatically occur during 3288 the call to `SNESSolve()`. However, if one wishes to control this 3289 phase separately, `SNESSetUp()` should be called after `SNESCreate()` 3290 and optional routines of the form SNESSetXXX(), but before `SNESSolve()`. 3291 3292 .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()` 3293 @*/ 3294 PetscErrorCode SNESSetUp(SNES snes) 3295 { 3296 DM dm; 3297 DMSNES sdm; 3298 SNESLineSearch linesearch, pclinesearch; 3299 void *lsprectx, *lspostctx; 3300 PetscBool mf_operator, mf; 3301 Vec f, fpc; 3302 void *funcctx; 3303 void *jacctx, *appctx; 3304 Mat j, jpre; 3305 PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 3306 PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 3307 SNESFunctionFn *func; 3308 SNESJacobianFn *jac; 3309 3310 PetscFunctionBegin; 3311 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3312 if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 3313 PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0)); 3314 3315 if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 3316 3317 PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 3318 3319 PetscCall(SNESGetDM(snes, &dm)); 3320 PetscCall(DMGetDMSNES(dm, &sdm)); 3321 PetscCall(SNESSetDefaultComputeJacobian(snes)); 3322 3323 if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3324 3325 if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3326 3327 if (snes->linesearch) { 3328 PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 3329 PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3330 } 3331 3332 PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf)); 3333 if (snes->npc && snes->npcside == PC_LEFT) { 3334 snes->mf = PETSC_TRUE; 3335 snes->mf_operator = PETSC_FALSE; 3336 } 3337 3338 if (snes->npc) { 3339 /* copy the DM over */ 3340 PetscCall(SNESGetDM(snes, &dm)); 3341 PetscCall(SNESSetDM(snes->npc, dm)); 3342 3343 PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 3344 PetscCall(VecDuplicate(f, &fpc)); 3345 PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 3346 PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 3347 PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 3348 PetscCall(SNESGetApplicationContext(snes, &appctx)); 3349 PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 3350 PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf)); 3351 PetscCall(VecDestroy(&fpc)); 3352 3353 /* copy the function pointers over */ 3354 PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 3355 3356 /* default to 1 iteration */ 3357 PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3358 if (snes->npcside == PC_RIGHT) { 3359 PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3360 } else { 3361 PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3362 } 3363 PetscCall(SNESSetFromOptions(snes->npc)); 3364 3365 /* copy the line search context over */ 3366 if (snes->linesearch && snes->npc->linesearch) { 3367 PetscCall(SNESGetLineSearch(snes, &linesearch)); 3368 PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 3369 PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 3370 PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 3371 PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 3372 PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 3373 PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 3374 } 3375 } 3376 if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 3377 if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx)); 3378 3379 snes->jac_iter = 0; 3380 snes->pre_iter = 0; 3381 3382 PetscTryTypeMethod(snes, setup); 3383 3384 PetscCall(SNESSetDefaultComputeJacobian(snes)); 3385 3386 if (snes->npc && snes->npcside == PC_LEFT) { 3387 if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3388 if (snes->linesearch) { 3389 PetscCall(SNESGetLineSearch(snes, &linesearch)); 3390 PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 3391 } 3392 } 3393 } 3394 PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0)); 3395 snes->setupcalled = PETSC_TRUE; 3396 PetscFunctionReturn(PETSC_SUCCESS); 3397 } 3398 3399 /*@ 3400 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 3401 3402 Collective 3403 3404 Input Parameter: 3405 . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 3406 3407 Level: intermediate 3408 3409 Notes: 3410 Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain. 3411 3412 Call this if you wish to reuse a `SNES` but with different size vectors 3413 3414 Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3415 3416 .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 3417 @*/ 3418 PetscErrorCode SNESReset(SNES snes) 3419 { 3420 PetscFunctionBegin; 3421 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3422 if (snes->ops->ctxdestroy && snes->ctx) { 3423 PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx)); 3424 snes->ctx = NULL; 3425 } 3426 if (snes->npc) PetscCall(SNESReset(snes->npc)); 3427 3428 PetscTryTypeMethod(snes, reset); 3429 if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 3430 3431 if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 3432 3433 PetscCall(VecDestroy(&snes->vec_rhs)); 3434 PetscCall(VecDestroy(&snes->vec_sol)); 3435 PetscCall(VecDestroy(&snes->vec_sol_update)); 3436 PetscCall(VecDestroy(&snes->vec_func)); 3437 PetscCall(MatDestroy(&snes->jacobian)); 3438 PetscCall(MatDestroy(&snes->jacobian_pre)); 3439 PetscCall(MatDestroy(&snes->picard)); 3440 PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 3441 PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3442 3443 snes->alwayscomputesfinalresidual = PETSC_FALSE; 3444 3445 snes->nwork = snes->nvwork = 0; 3446 snes->setupcalled = PETSC_FALSE; 3447 PetscFunctionReturn(PETSC_SUCCESS); 3448 } 3449 3450 /*@ 3451 SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also 3452 removes the default viewer. 3453 3454 Collective 3455 3456 Input Parameter: 3457 . snes - the nonlinear iterative solver context obtained from `SNESCreate()` 3458 3459 Level: intermediate 3460 3461 .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()` 3462 @*/ 3463 PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3464 { 3465 PetscInt i; 3466 3467 PetscFunctionBegin; 3468 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3469 for (i = 0; i < snes->numberreasonviews; i++) { 3470 if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3471 } 3472 snes->numberreasonviews = 0; 3473 PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer)); 3474 PetscFunctionReturn(PETSC_SUCCESS); 3475 } 3476 3477 /*@ 3478 SNESDestroy - Destroys the nonlinear solver context that was created 3479 with `SNESCreate()`. 3480 3481 Collective 3482 3483 Input Parameter: 3484 . snes - the `SNES` context 3485 3486 Level: beginner 3487 3488 .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()` 3489 @*/ 3490 PetscErrorCode SNESDestroy(SNES *snes) 3491 { 3492 DM dm; 3493 3494 PetscFunctionBegin; 3495 if (!*snes) PetscFunctionReturn(PETSC_SUCCESS); 3496 PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1); 3497 if (--((PetscObject)*snes)->refct > 0) { 3498 *snes = NULL; 3499 PetscFunctionReturn(PETSC_SUCCESS); 3500 } 3501 3502 PetscCall(SNESReset(*snes)); 3503 PetscCall(SNESDestroy(&(*snes)->npc)); 3504 3505 /* if memory was published with SAWs then destroy it */ 3506 PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3507 PetscTryTypeMethod(*snes, destroy); 3508 3509 dm = (*snes)->dm; 3510 while (dm) { 3511 PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 3512 PetscCall(DMGetCoarseDM(dm, &dm)); 3513 } 3514 3515 PetscCall(DMDestroy(&(*snes)->dm)); 3516 PetscCall(KSPDestroy(&(*snes)->ksp)); 3517 PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 3518 3519 PetscCall(PetscFree((*snes)->kspconvctx)); 3520 if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP)); 3521 if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3522 PetscCall(SNESMonitorCancel(*snes)); 3523 PetscCall(SNESConvergedReasonViewCancel(*snes)); 3524 PetscCall(PetscHeaderDestroy(snes)); 3525 PetscFunctionReturn(PETSC_SUCCESS); 3526 } 3527 3528 /* ----------- Routines to set solver parameters ---------- */ 3529 3530 /*@ 3531 SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`. 3532 3533 Logically Collective 3534 3535 Input Parameters: 3536 + snes - the `SNES` context 3537 - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3538 the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3539 3540 Options Database Keys: 3541 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple `SNESSolve()` 3542 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3543 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()` 3544 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3545 3546 Level: intermediate 3547 3548 Notes: 3549 The default is 1 3550 3551 The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3552 3553 `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3554 3555 .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3556 `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3557 @*/ 3558 PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3559 { 3560 PetscFunctionBegin; 3561 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3562 PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 3563 PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3564 PetscValidLogicalCollectiveInt(snes, lag, 2); 3565 snes->lagpreconditioner = lag; 3566 PetscFunctionReturn(PETSC_SUCCESS); 3567 } 3568 3569 /*@ 3570 SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3571 3572 Logically Collective 3573 3574 Input Parameters: 3575 + snes - the `SNES` context 3576 - steps - the number of refinements to do, defaults to 0 3577 3578 Options Database Key: 3579 . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3580 3581 Level: intermediate 3582 3583 Notes: 3584 Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement. 3585 3586 Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3587 3588 .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`, 3589 `SNESSetDM()`, `SNESSolve()` 3590 @*/ 3591 PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3592 { 3593 PetscFunctionBegin; 3594 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3595 PetscValidLogicalCollectiveInt(snes, steps, 2); 3596 snes->gridsequence = steps; 3597 PetscFunctionReturn(PETSC_SUCCESS); 3598 } 3599 3600 /*@ 3601 SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3602 3603 Logically Collective 3604 3605 Input Parameter: 3606 . snes - the `SNES` context 3607 3608 Output Parameter: 3609 . steps - the number of refinements to do, defaults to 0 3610 3611 Level: intermediate 3612 3613 .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3614 @*/ 3615 PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3616 { 3617 PetscFunctionBegin; 3618 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3619 *steps = snes->gridsequence; 3620 PetscFunctionReturn(PETSC_SUCCESS); 3621 } 3622 3623 /*@ 3624 SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3625 3626 Not Collective 3627 3628 Input Parameter: 3629 . snes - the `SNES` context 3630 3631 Output Parameter: 3632 . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3633 the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3634 3635 Level: intermediate 3636 3637 Notes: 3638 The default is 1 3639 3640 The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3641 3642 .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3643 @*/ 3644 PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3645 { 3646 PetscFunctionBegin; 3647 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3648 *lag = snes->lagpreconditioner; 3649 PetscFunctionReturn(PETSC_SUCCESS); 3650 } 3651 3652 /*@ 3653 SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3654 often the preconditioner is rebuilt. 3655 3656 Logically Collective 3657 3658 Input Parameters: 3659 + snes - the `SNES` context 3660 - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3661 the Jacobian is built etc. -2 means rebuild at next chance but then never again 3662 3663 Options Database Keys: 3664 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 3665 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3666 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 3667 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3668 3669 Level: intermediate 3670 3671 Notes: 3672 The default is 1 3673 3674 The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3675 3676 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 3677 at the next Newton step but never again (unless it is reset to another value) 3678 3679 .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3680 @*/ 3681 PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3682 { 3683 PetscFunctionBegin; 3684 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3685 PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 3686 PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3687 PetscValidLogicalCollectiveInt(snes, lag, 2); 3688 snes->lagjacobian = lag; 3689 PetscFunctionReturn(PETSC_SUCCESS); 3690 } 3691 3692 /*@ 3693 SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3694 3695 Not Collective 3696 3697 Input Parameter: 3698 . snes - the `SNES` context 3699 3700 Output Parameter: 3701 . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3702 the Jacobian is built etc. 3703 3704 Level: intermediate 3705 3706 Notes: 3707 The default is 1 3708 3709 The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3710 3711 .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3712 3713 @*/ 3714 PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3715 { 3716 PetscFunctionBegin; 3717 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3718 *lag = snes->lagjacobian; 3719 PetscFunctionReturn(PETSC_SUCCESS); 3720 } 3721 3722 /*@ 3723 SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 3724 3725 Logically collective 3726 3727 Input Parameters: 3728 + snes - the `SNES` context 3729 - flg - jacobian lagging persists if true 3730 3731 Options Database Keys: 3732 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 3733 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3734 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 3735 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3736 3737 Level: advanced 3738 3739 Notes: 3740 Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3741 3742 This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 3743 several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 3744 timesteps may present huge efficiency gains. 3745 3746 .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()` 3747 @*/ 3748 PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3749 { 3750 PetscFunctionBegin; 3751 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3752 PetscValidLogicalCollectiveBool(snes, flg, 2); 3753 snes->lagjac_persist = flg; 3754 PetscFunctionReturn(PETSC_SUCCESS); 3755 } 3756 3757 /*@ 3758 SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 3759 3760 Logically Collective 3761 3762 Input Parameters: 3763 + snes - the `SNES` context 3764 - flg - preconditioner lagging persists if true 3765 3766 Options Database Keys: 3767 + -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves 3768 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3769 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves 3770 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3771 3772 Level: developer 3773 3774 Notes: 3775 Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior 3776 3777 This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 3778 by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 3779 several timesteps may present huge efficiency gains. 3780 3781 .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 3782 @*/ 3783 PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3784 { 3785 PetscFunctionBegin; 3786 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3787 PetscValidLogicalCollectiveBool(snes, flg, 2); 3788 snes->lagpre_persist = flg; 3789 PetscFunctionReturn(PETSC_SUCCESS); 3790 } 3791 3792 /*@ 3793 SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3794 3795 Logically Collective 3796 3797 Input Parameters: 3798 + snes - the `SNES` context 3799 - force - `PETSC_TRUE` require at least one iteration 3800 3801 Options Database Key: 3802 . -snes_force_iteration <force> - Sets forcing an iteration 3803 3804 Level: intermediate 3805 3806 Note: 3807 This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3808 3809 .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()` 3810 @*/ 3811 PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3812 { 3813 PetscFunctionBegin; 3814 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3815 snes->forceiteration = force; 3816 PetscFunctionReturn(PETSC_SUCCESS); 3817 } 3818 3819 /*@ 3820 SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 3821 3822 Logically Collective 3823 3824 Input Parameter: 3825 . snes - the `SNES` context 3826 3827 Output Parameter: 3828 . force - `PETSC_TRUE` requires at least one iteration. 3829 3830 Level: intermediate 3831 3832 .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()` 3833 @*/ 3834 PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3835 { 3836 PetscFunctionBegin; 3837 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3838 *force = snes->forceiteration; 3839 PetscFunctionReturn(PETSC_SUCCESS); 3840 } 3841 3842 /*@ 3843 SNESSetTolerances - Sets various parameters used in `SNES` convergence tests. 3844 3845 Logically Collective 3846 3847 Input Parameters: 3848 + snes - the `SNES` context 3849 . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $ 3850 . rtol - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $ 3851 . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 3852 . maxit - the maximum number of iterations allowed in the solver, default 50. 3853 - maxf - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000 3854 3855 Options Database Keys: 3856 + -snes_atol <abstol> - Sets `abstol` 3857 . -snes_rtol <rtol> - Sets `rtol` 3858 . -snes_stol <stol> - Sets `stol` 3859 . -snes_max_it <maxit> - Sets `maxit` 3860 - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum) 3861 3862 Level: intermediate 3863 3864 Note: 3865 All parameters must be non-negative 3866 3867 Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`. 3868 The default value is the value in the object when its type is set. 3869 3870 Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations. 3871 3872 Fortran Note: 3873 Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL` 3874 3875 .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 3876 @*/ 3877 PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3878 { 3879 PetscFunctionBegin; 3880 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3881 PetscValidLogicalCollectiveReal(snes, abstol, 2); 3882 PetscValidLogicalCollectiveReal(snes, rtol, 3); 3883 PetscValidLogicalCollectiveReal(snes, stol, 4); 3884 PetscValidLogicalCollectiveInt(snes, maxit, 5); 3885 PetscValidLogicalCollectiveInt(snes, maxf, 6); 3886 3887 if (abstol == (PetscReal)PETSC_DETERMINE) { 3888 snes->abstol = snes->default_abstol; 3889 } else if (abstol != (PetscReal)PETSC_CURRENT) { 3890 PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3891 snes->abstol = abstol; 3892 } 3893 3894 if (rtol == (PetscReal)PETSC_DETERMINE) { 3895 snes->rtol = snes->default_rtol; 3896 } else if (rtol != (PetscReal)PETSC_CURRENT) { 3897 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); 3898 snes->rtol = rtol; 3899 } 3900 3901 if (stol == (PetscReal)PETSC_DETERMINE) { 3902 snes->stol = snes->default_stol; 3903 } else if (stol != (PetscReal)PETSC_CURRENT) { 3904 PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3905 snes->stol = stol; 3906 } 3907 3908 if (maxit == PETSC_DETERMINE) { 3909 snes->max_its = snes->default_max_its; 3910 } else if (maxit == PETSC_UNLIMITED) { 3911 snes->max_its = PETSC_INT_MAX; 3912 } else if (maxit != PETSC_CURRENT) { 3913 PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3914 snes->max_its = maxit; 3915 } 3916 3917 if (maxf == PETSC_DETERMINE) { 3918 snes->max_funcs = snes->default_max_funcs; 3919 } else if (maxf == PETSC_UNLIMITED || maxf == -1) { 3920 snes->max_funcs = PETSC_UNLIMITED; 3921 } else if (maxf != PETSC_CURRENT) { 3922 PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf); 3923 snes->max_funcs = maxf; 3924 } 3925 PetscFunctionReturn(PETSC_SUCCESS); 3926 } 3927 3928 /*@ 3929 SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3930 3931 Logically Collective 3932 3933 Input Parameters: 3934 + snes - the `SNES` context 3935 - 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 3936 is stopped due to divergence. 3937 3938 Options Database Key: 3939 . -snes_divergence_tolerance <divtol> - Sets `divtol` 3940 3941 Level: intermediate 3942 3943 Notes: 3944 Use `PETSC_DETERMINE` to use the default value from when the object's type was set. 3945 3946 Fortran Note: 3947 Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL` 3948 3949 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()` 3950 @*/ 3951 PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 3952 { 3953 PetscFunctionBegin; 3954 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3955 PetscValidLogicalCollectiveReal(snes, divtol, 2); 3956 3957 if (divtol == (PetscReal)PETSC_DETERMINE) { 3958 snes->divtol = snes->default_divtol; 3959 } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) { 3960 snes->divtol = PETSC_UNLIMITED; 3961 } else if (divtol != (PetscReal)PETSC_CURRENT) { 3962 PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol); 3963 snes->divtol = divtol; 3964 } 3965 PetscFunctionReturn(PETSC_SUCCESS); 3966 } 3967 3968 /*@ 3969 SNESGetTolerances - Gets various parameters used in `SNES` convergence tests. 3970 3971 Not Collective 3972 3973 Input Parameter: 3974 . snes - the `SNES` context 3975 3976 Output Parameters: 3977 + atol - the absolute convergence tolerance 3978 . rtol - the relative convergence tolerance 3979 . stol - convergence tolerance in terms of the norm of the change in the solution between steps 3980 . maxit - the maximum number of iterations allowed 3981 - maxf - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound 3982 3983 Level: intermediate 3984 3985 Notes: 3986 See `SNESSetTolerances()` for details on the parameters. 3987 3988 The user can specify `NULL` for any parameter that is not needed. 3989 3990 .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()` 3991 @*/ 3992 PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 3993 { 3994 PetscFunctionBegin; 3995 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3996 if (atol) *atol = snes->abstol; 3997 if (rtol) *rtol = snes->rtol; 3998 if (stol) *stol = snes->stol; 3999 if (maxit) *maxit = snes->max_its; 4000 if (maxf) *maxf = snes->max_funcs; 4001 PetscFunctionReturn(PETSC_SUCCESS); 4002 } 4003 4004 /*@ 4005 SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 4006 4007 Not Collective 4008 4009 Input Parameters: 4010 + snes - the `SNES` context 4011 - divtol - divergence tolerance 4012 4013 Level: intermediate 4014 4015 .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()` 4016 @*/ 4017 PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 4018 { 4019 PetscFunctionBegin; 4020 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4021 if (divtol) *divtol = snes->divtol; 4022 PetscFunctionReturn(PETSC_SUCCESS); 4023 } 4024 4025 PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 4026 4027 PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 4028 { 4029 PetscDrawLG lg; 4030 PetscReal x, y, per; 4031 PetscViewer v = (PetscViewer)monctx; 4032 static PetscReal prev; /* should be in the context */ 4033 PetscDraw draw; 4034 4035 PetscFunctionBegin; 4036 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 4037 PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 4038 if (!n) PetscCall(PetscDrawLGReset(lg)); 4039 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4040 PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 4041 x = (PetscReal)n; 4042 if (rnorm > 0.0) y = PetscLog10Real(rnorm); 4043 else y = -15.0; 4044 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4045 if (n < 20 || !(n % 5) || snes->reason) { 4046 PetscCall(PetscDrawLGDraw(lg)); 4047 PetscCall(PetscDrawLGSave(lg)); 4048 } 4049 4050 PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 4051 if (!n) PetscCall(PetscDrawLGReset(lg)); 4052 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4053 PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element")); 4054 PetscCall(SNESMonitorRange_Private(snes, n, &per)); 4055 x = (PetscReal)n; 4056 y = 100.0 * per; 4057 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4058 if (n < 20 || !(n % 5) || snes->reason) { 4059 PetscCall(PetscDrawLGDraw(lg)); 4060 PetscCall(PetscDrawLGSave(lg)); 4061 } 4062 4063 PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 4064 if (!n) { 4065 prev = rnorm; 4066 PetscCall(PetscDrawLGReset(lg)); 4067 } 4068 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4069 PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 4070 x = (PetscReal)n; 4071 y = (prev - rnorm) / prev; 4072 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4073 if (n < 20 || !(n % 5) || snes->reason) { 4074 PetscCall(PetscDrawLGDraw(lg)); 4075 PetscCall(PetscDrawLGSave(lg)); 4076 } 4077 4078 PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 4079 if (!n) PetscCall(PetscDrawLGReset(lg)); 4080 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 4081 PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 4082 x = (PetscReal)n; 4083 y = (prev - rnorm) / (prev * per); 4084 if (n > 2) { /*skip initial crazy value */ 4085 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 4086 } 4087 if (n < 20 || !(n % 5) || snes->reason) { 4088 PetscCall(PetscDrawLGDraw(lg)); 4089 PetscCall(PetscDrawLGSave(lg)); 4090 } 4091 prev = rnorm; 4092 PetscFunctionReturn(PETSC_SUCCESS); 4093 } 4094 4095 /*@ 4096 SNESConverged - Run the convergence test and update the `SNESConvergedReason`. 4097 4098 Collective 4099 4100 Input Parameters: 4101 + snes - the `SNES` context 4102 . it - current iteration 4103 . xnorm - 2-norm of current iterate 4104 . snorm - 2-norm of current step 4105 - fnorm - 2-norm of function 4106 4107 Level: developer 4108 4109 Note: 4110 This routine is called by the `SNESSolve()` implementations. 4111 It does not typically need to be called by the user. 4112 4113 .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 4114 @*/ 4115 PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm) 4116 { 4117 PetscFunctionBegin; 4118 if (!snes->reason) { 4119 if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP); 4120 if (it == snes->max_its && !snes->reason) { 4121 if (snes->normschedule == SNES_NORM_ALWAYS) { 4122 PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its)); 4123 snes->reason = SNES_DIVERGED_MAX_IT; 4124 } else snes->reason = SNES_CONVERGED_ITS; 4125 } 4126 } 4127 PetscFunctionReturn(PETSC_SUCCESS); 4128 } 4129 4130 /*@ 4131 SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database 4132 4133 Collective 4134 4135 Input Parameters: 4136 + snes - nonlinear solver context obtained from `SNESCreate()` 4137 . iter - current iteration number 4138 - rnorm - current relative norm of the residual 4139 4140 Level: developer 4141 4142 Note: 4143 This routine is called by the `SNESSolve()` implementations. 4144 It does not typically need to be called by the user. 4145 4146 .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()` 4147 @*/ 4148 PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 4149 { 4150 PetscInt i, n = snes->numbermonitors; 4151 4152 PetscFunctionBegin; 4153 if (n > 0) SNESCheckFunctionNorm(snes, rnorm); 4154 PetscCall(VecLockReadPush(snes->vec_sol)); 4155 for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 4156 PetscCall(VecLockReadPop(snes->vec_sol)); 4157 PetscFunctionReturn(PETSC_SUCCESS); 4158 } 4159 4160 /* ------------ Routines to set performance monitoring options ----------- */ 4161 4162 /*MC 4163 SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 4164 4165 Synopsis: 4166 #include <petscsnes.h> 4167 PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx) 4168 4169 Collective 4170 4171 Input Parameters: 4172 + snes - the `SNES` context 4173 . its - iteration number 4174 . norm - 2-norm function value (may be estimated) 4175 - mctx - [optional] monitoring context 4176 4177 Level: advanced 4178 4179 .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()` 4180 M*/ 4181 4182 /*@C 4183 SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 4184 iteration of the `SNES` nonlinear solver to display the iteration's 4185 progress. 4186 4187 Logically Collective 4188 4189 Input Parameters: 4190 + snes - the `SNES` context 4191 . f - the monitor function, for the calling sequence see `SNESMonitorFunction` 4192 . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired) 4193 - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4194 4195 Options Database Keys: 4196 + -snes_monitor - sets `SNESMonitorDefault()` 4197 . -snes_monitor draw::draw_lg - sets line graph monitor, 4198 - -snes_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to `SNESMonitorSet()`, but does not cancel those set via 4199 the options database. 4200 4201 Level: intermediate 4202 4203 Note: 4204 Several different monitoring routines may be set by calling 4205 `SNESMonitorSet()` multiple times; all will be called in the 4206 order in which they were set. 4207 4208 Fortran Note: 4209 Only a single monitor function can be set for each `SNES` object 4210 4211 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn` 4212 @*/ 4213 PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy) 4214 { 4215 PetscInt i; 4216 PetscBool identical; 4217 4218 PetscFunctionBegin; 4219 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4220 for (i = 0; i < snes->numbermonitors; i++) { 4221 PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 4222 if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4223 } 4224 PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 4225 snes->monitor[snes->numbermonitors] = f; 4226 snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4227 snes->monitorcontext[snes->numbermonitors++] = mctx; 4228 PetscFunctionReturn(PETSC_SUCCESS); 4229 } 4230 4231 /*@ 4232 SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 4233 4234 Logically Collective 4235 4236 Input Parameter: 4237 . snes - the `SNES` context 4238 4239 Options Database Key: 4240 . -snes_monitor_cancel - cancels all monitors that have been hardwired 4241 into a code by calls to `SNESMonitorSet()`, but does not cancel those 4242 set via the options database 4243 4244 Level: intermediate 4245 4246 Note: 4247 There is no way to clear one specific monitor from a `SNES` object. 4248 4249 .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()` 4250 @*/ 4251 PetscErrorCode SNESMonitorCancel(SNES snes) 4252 { 4253 PetscInt i; 4254 4255 PetscFunctionBegin; 4256 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4257 for (i = 0; i < snes->numbermonitors; i++) { 4258 if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4259 } 4260 snes->numbermonitors = 0; 4261 PetscFunctionReturn(PETSC_SUCCESS); 4262 } 4263 4264 /*MC 4265 SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4266 4267 Synopsis: 4268 #include <petscsnes.h> 4269 PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx) 4270 4271 Collective 4272 4273 Input Parameters: 4274 + snes - the `SNES` context 4275 . it - current iteration (0 is the first and is before any Newton step) 4276 . xnorm - 2-norm of current iterate 4277 . gnorm - 2-norm of current step 4278 . f - 2-norm of function 4279 - cctx - [optional] convergence context 4280 4281 Output Parameter: 4282 . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4283 4284 Level: intermediate 4285 4286 .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()` 4287 M*/ 4288 4289 /*@C 4290 SNESSetConvergenceTest - Sets the function that is to be used 4291 to test for convergence of the nonlinear iterative solution. 4292 4293 Logically Collective 4294 4295 Input Parameters: 4296 + snes - the `SNES` context 4297 . SNESConvergenceTestFunction - routine to test for convergence 4298 . cctx - [optional] context for private data for the convergence routine (may be `NULL`) 4299 - destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran) 4300 4301 Level: advanced 4302 4303 .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 4304 @*/ 4305 PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *)) 4306 { 4307 PetscFunctionBegin; 4308 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4309 if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 4310 if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP)); 4311 snes->ops->converged = SNESConvergenceTestFunction; 4312 snes->ops->convergeddestroy = destroy; 4313 snes->cnvP = cctx; 4314 PetscFunctionReturn(PETSC_SUCCESS); 4315 } 4316 4317 /*@ 4318 SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation 4319 4320 Not Collective 4321 4322 Input Parameter: 4323 . snes - the `SNES` context 4324 4325 Output Parameter: 4326 . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4327 4328 Options Database Key: 4329 . -snes_converged_reason - prints the reason to standard out 4330 4331 Level: intermediate 4332 4333 Note: 4334 Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4335 4336 .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4337 @*/ 4338 PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4339 { 4340 PetscFunctionBegin; 4341 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4342 PetscAssertPointer(reason, 2); 4343 *reason = snes->reason; 4344 PetscFunctionReturn(PETSC_SUCCESS); 4345 } 4346 4347 /*@C 4348 SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4349 4350 Not Collective 4351 4352 Input Parameter: 4353 . snes - the `SNES` context 4354 4355 Output Parameter: 4356 . strreason - a human readable string that describes `SNES` converged reason 4357 4358 Level: beginner 4359 4360 .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()` 4361 @*/ 4362 PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4363 { 4364 PetscFunctionBegin; 4365 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4366 PetscAssertPointer(strreason, 2); 4367 *strreason = SNESConvergedReasons[snes->reason]; 4368 PetscFunctionReturn(PETSC_SUCCESS); 4369 } 4370 4371 /*@ 4372 SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 4373 4374 Not Collective 4375 4376 Input Parameters: 4377 + snes - the `SNES` context 4378 - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 4379 manual pages for the individual convergence tests for complete lists 4380 4381 Level: developer 4382 4383 Developer Note: 4384 Called inside the various `SNESSolve()` implementations 4385 4386 .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 4387 @*/ 4388 PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4389 { 4390 PetscFunctionBegin; 4391 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4392 PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason"); 4393 snes->reason = reason; 4394 PetscFunctionReturn(PETSC_SUCCESS); 4395 } 4396 4397 /*@ 4398 SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history. 4399 4400 Logically Collective 4401 4402 Input Parameters: 4403 + snes - iterative context obtained from `SNESCreate()` 4404 . a - array to hold history, this array will contain the function norms computed at each step 4405 . its - integer array holds the number of linear iterations for each solve. 4406 . na - size of `a` and `its` 4407 - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4408 else it continues storing new values for new nonlinear solves after the old ones 4409 4410 Level: intermediate 4411 4412 Notes: 4413 If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` (or, deprecated, `PETSC_DEFAULT`) then a 4414 default array of length 1,000 is allocated. 4415 4416 This routine is useful, e.g., when running a code for purposes 4417 of accurate performance monitoring, when no I/O should be done 4418 during the section of code that is being timed. 4419 4420 If the arrays run out of space after a number of iterations then the later values are not saved in the history 4421 4422 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4423 @*/ 4424 PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4425 { 4426 PetscFunctionBegin; 4427 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4428 if (a) PetscAssertPointer(a, 2); 4429 if (its) PetscAssertPointer(its, 3); 4430 if (!a) { 4431 if (na == PETSC_DECIDE) na = 1000; 4432 PetscCall(PetscCalloc2(na, &a, na, &its)); 4433 snes->conv_hist_alloc = PETSC_TRUE; 4434 } 4435 snes->conv_hist = a; 4436 snes->conv_hist_its = its; 4437 snes->conv_hist_max = (size_t)na; 4438 snes->conv_hist_len = 0; 4439 snes->conv_hist_reset = reset; 4440 PetscFunctionReturn(PETSC_SUCCESS); 4441 } 4442 4443 #if defined(PETSC_HAVE_MATLAB) 4444 #include <engine.h> /* MATLAB include file */ 4445 #include <mex.h> /* MATLAB include file */ 4446 4447 PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4448 { 4449 mxArray *mat; 4450 PetscInt i; 4451 PetscReal *ar; 4452 4453 mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4454 ar = (PetscReal *)mxGetData(mat); 4455 for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 4456 return mat; 4457 } 4458 #endif 4459 4460 /*@C 4461 SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history. 4462 4463 Not Collective 4464 4465 Input Parameter: 4466 . snes - iterative context obtained from `SNESCreate()` 4467 4468 Output Parameters: 4469 + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4470 . its - integer array holds the number of linear iterations (or 4471 negative if not converged) for each solve. 4472 - na - size of `a` and `its` 4473 4474 Level: intermediate 4475 4476 Note: 4477 This routine is useful, e.g., when running a code for purposes 4478 of accurate performance monitoring, when no I/O should be done 4479 during the section of code that is being timed. 4480 4481 Fortran Notes: 4482 Return the arrays with ``SNESRestoreConvergenceHistory()` 4483 4484 Use the arguments 4485 .vb 4486 PetscReal, pointer :: a(:) 4487 PetscInt, pointer :: its(:) 4488 .ve 4489 4490 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4491 @*/ 4492 PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4493 { 4494 PetscFunctionBegin; 4495 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4496 if (a) *a = snes->conv_hist; 4497 if (its) *its = snes->conv_hist_its; 4498 if (na) *na = (PetscInt)snes->conv_hist_len; 4499 PetscFunctionReturn(PETSC_SUCCESS); 4500 } 4501 4502 /*@C 4503 SNESSetUpdate - Sets the general-purpose update function called 4504 at the beginning of every iteration of the nonlinear solve. Specifically 4505 it is called just before the Jacobian is "evaluated" and after the function 4506 evaluation. 4507 4508 Logically Collective 4509 4510 Input Parameters: 4511 + snes - The nonlinear solver context 4512 - func - The update function; for calling sequence see `SNESUpdateFn` 4513 4514 Level: advanced 4515 4516 Notes: 4517 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 4518 to `SNESSetFunction()`, or `SNESSetPicard()` 4519 This is not used by most users, and it is intended to provide a general hook that is run 4520 right before the direction step is computed. 4521 4522 Users are free to modify the current residual vector, 4523 the current linearization point, or any other vector associated to the specific solver used. 4524 If such modifications take place, it is the user responsibility to update all the relevant 4525 vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like 4526 .vb 4527 PetscErrorCode update(SNES snes, PetscInt iteration) 4528 { 4529 PetscFunctionBeginUser; 4530 if (iteration > 0) { 4531 // update the model parameters here 4532 Vec x,f; 4533 PetscCall(SNESGetSolution(snes,&x)); 4534 PetcCall(SNESGetFunction(snes,&f,NULL,NULL)); 4535 PetscCall(SNESComputeFunction(snes,x,f)); 4536 } 4537 PetscFunctionReturn(PETSC_SUCCESS); 4538 } 4539 .ve 4540 4541 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. 4542 4543 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 4544 `SNESMonitorSet()` 4545 @*/ 4546 PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func) 4547 { 4548 PetscFunctionBegin; 4549 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4550 snes->ops->update = func; 4551 PetscFunctionReturn(PETSC_SUCCESS); 4552 } 4553 4554 /*@ 4555 SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 4556 4557 Collective 4558 4559 Input Parameters: 4560 + snes - iterative context obtained from `SNESCreate()` 4561 - viewer - the viewer to display the reason 4562 4563 Options Database Keys: 4564 + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4565 - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4566 4567 Level: beginner 4568 4569 Note: 4570 To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4571 use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 4572 4573 .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`, 4574 `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4575 `SNESConvergedReasonViewFromOptions()`, 4576 `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 4577 @*/ 4578 PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4579 { 4580 PetscViewerFormat format; 4581 PetscBool isAscii; 4582 4583 PetscFunctionBegin; 4584 if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 4585 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 4586 if (isAscii) { 4587 PetscCall(PetscViewerGetFormat(viewer, &format)); 4588 PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1)); 4589 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 4590 DM dm; 4591 Vec u; 4592 PetscDS prob; 4593 PetscInt Nf, f; 4594 PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 4595 void **exactCtx; 4596 PetscReal error; 4597 4598 PetscCall(SNESGetDM(snes, &dm)); 4599 PetscCall(SNESGetSolution(snes, &u)); 4600 PetscCall(DMGetDS(dm, &prob)); 4601 PetscCall(PetscDSGetNumFields(prob, &Nf)); 4602 PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 4603 for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 4604 PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 4605 PetscCall(PetscFree2(exactSol, exactCtx)); 4606 if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 4607 else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 4608 } 4609 if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 4610 if (((PetscObject)snes)->prefix) { 4611 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 4612 } else { 4613 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 4614 } 4615 } else if (snes->reason <= 0) { 4616 if (((PetscObject)snes)->prefix) { 4617 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve did not converge due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 4618 } else { 4619 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 4620 } 4621 } 4622 PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1)); 4623 } 4624 PetscFunctionReturn(PETSC_SUCCESS); 4625 } 4626 4627 /*@C 4628 SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4629 end of the nonlinear solver to display the convergence reason of the nonlinear solver. 4630 4631 Logically Collective 4632 4633 Input Parameters: 4634 + snes - the `SNES` context 4635 . f - the `SNESConvergedReason` view function 4636 . vctx - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired) 4637 - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence 4638 4639 Calling sequence of `f`: 4640 + snes - the `SNES` context 4641 - vctx - [optional] context for private data for the function 4642 4643 Options Database Keys: 4644 + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4645 - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by 4646 calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database. 4647 4648 Level: intermediate 4649 4650 Note: 4651 Several different converged reason view routines may be set by calling 4652 `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4653 order in which they were set. 4654 4655 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`, 4656 `PetscCtxDestroyFn` 4657 @*/ 4658 PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy) 4659 { 4660 PetscInt i; 4661 PetscBool identical; 4662 4663 PetscFunctionBegin; 4664 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4665 for (i = 0; i < snes->numberreasonviews; i++) { 4666 PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 4667 if (identical) PetscFunctionReturn(PETSC_SUCCESS); 4668 } 4669 PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4670 snes->reasonview[snes->numberreasonviews] = f; 4671 snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4672 snes->reasonviewcontext[snes->numberreasonviews++] = vctx; 4673 PetscFunctionReturn(PETSC_SUCCESS); 4674 } 4675 4676 /*@ 4677 SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()` 4678 All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist. 4679 4680 Collective 4681 4682 Input Parameter: 4683 . snes - the `SNES` object 4684 4685 Level: advanced 4686 4687 .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4688 `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 4689 @*/ 4690 PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4691 { 4692 static PetscBool incall = PETSC_FALSE; 4693 4694 PetscFunctionBegin; 4695 if (incall) PetscFunctionReturn(PETSC_SUCCESS); 4696 incall = PETSC_TRUE; 4697 4698 /* All user-provided viewers are called first, if they exist. */ 4699 for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4700 4701 /* Call PETSc default routine if users ask for it */ 4702 if (snes->convergedreasonviewer) { 4703 PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat)); 4704 PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer)); 4705 PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer)); 4706 } 4707 incall = PETSC_FALSE; 4708 PetscFunctionReturn(PETSC_SUCCESS); 4709 } 4710 4711 /*@ 4712 SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object 4713 4714 Collective 4715 4716 Input Parameters: 4717 + snes - the `SNES` context 4718 . b - the constant part of the equation $F(x) = b$, or `NULL` to use zero. 4719 - x - the solution vector. 4720 4721 Level: beginner 4722 4723 Note: 4724 The user should initialize the vector, `x`, with the initial guess 4725 for the nonlinear solve prior to calling `SNESSolve()` . 4726 4727 .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4728 `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4729 `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()` 4730 @*/ 4731 PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4732 { 4733 PetscBool flg; 4734 PetscInt grid; 4735 Vec xcreated = NULL; 4736 DM dm; 4737 4738 PetscFunctionBegin; 4739 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4740 if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4741 if (x) PetscCheckSameComm(snes, 1, x, 3); 4742 if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4743 if (b) PetscCheckSameComm(snes, 1, b, 2); 4744 4745 /* High level operations using the nonlinear solver */ 4746 { 4747 PetscViewer viewer; 4748 PetscViewerFormat format; 4749 PetscInt num; 4750 PetscBool flg; 4751 static PetscBool incall = PETSC_FALSE; 4752 4753 if (!incall) { 4754 /* Estimate the convergence rate of the discretization */ 4755 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 4756 if (flg) { 4757 PetscConvEst conv; 4758 DM dm; 4759 PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 4760 PetscInt Nf; 4761 4762 incall = PETSC_TRUE; 4763 PetscCall(SNESGetDM(snes, &dm)); 4764 PetscCall(DMGetNumFields(dm, &Nf)); 4765 PetscCall(PetscCalloc1(Nf, &alpha)); 4766 PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 4767 PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 4768 PetscCall(PetscConvEstSetFromOptions(conv)); 4769 PetscCall(PetscConvEstSetUp(conv)); 4770 PetscCall(PetscConvEstGetConvRate(conv, alpha)); 4771 PetscCall(PetscViewerPushFormat(viewer, format)); 4772 PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 4773 PetscCall(PetscViewerPopFormat(viewer)); 4774 PetscCall(PetscViewerDestroy(&viewer)); 4775 PetscCall(PetscConvEstDestroy(&conv)); 4776 PetscCall(PetscFree(alpha)); 4777 incall = PETSC_FALSE; 4778 } 4779 /* Adaptively refine the initial grid */ 4780 num = 1; 4781 PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 4782 if (flg) { 4783 DMAdaptor adaptor; 4784 4785 incall = PETSC_TRUE; 4786 PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4787 PetscCall(DMAdaptorSetSolver(adaptor, snes)); 4788 PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 4789 PetscCall(DMAdaptorSetFromOptions(adaptor)); 4790 PetscCall(DMAdaptorSetUp(adaptor)); 4791 PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 4792 PetscCall(DMAdaptorDestroy(&adaptor)); 4793 incall = PETSC_FALSE; 4794 } 4795 /* Use grid sequencing to adapt */ 4796 num = 0; 4797 PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 4798 if (num) { 4799 DMAdaptor adaptor; 4800 const char *prefix; 4801 4802 incall = PETSC_TRUE; 4803 PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4804 PetscCall(SNESGetOptionsPrefix(snes, &prefix)); 4805 PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix)); 4806 PetscCall(DMAdaptorSetSolver(adaptor, snes)); 4807 PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 4808 PetscCall(DMAdaptorSetFromOptions(adaptor)); 4809 PetscCall(DMAdaptorSetUp(adaptor)); 4810 PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view")); 4811 PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 4812 PetscCall(DMAdaptorDestroy(&adaptor)); 4813 incall = PETSC_FALSE; 4814 } 4815 } 4816 } 4817 if (!x) x = snes->vec_sol; 4818 if (!x) { 4819 PetscCall(SNESGetDM(snes, &dm)); 4820 PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4821 x = xcreated; 4822 } 4823 PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4824 4825 for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4826 for (grid = 0; grid < snes->gridsequence + 1; grid++) { 4827 /* set solution vector */ 4828 if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 4829 PetscCall(VecDestroy(&snes->vec_sol)); 4830 snes->vec_sol = x; 4831 PetscCall(SNESGetDM(snes, &dm)); 4832 4833 /* set affine vector if provided */ 4834 if (b) PetscCall(PetscObjectReference((PetscObject)b)); 4835 PetscCall(VecDestroy(&snes->vec_rhs)); 4836 snes->vec_rhs = b; 4837 4838 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"); 4839 PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4840 PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector"); 4841 if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); 4842 PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 4843 PetscCall(SNESSetUp(snes)); 4844 4845 if (!grid) { 4846 if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4847 } 4848 4849 if (snes->conv_hist_reset) snes->conv_hist_len = 0; 4850 PetscCall(SNESResetCounters(snes)); 4851 snes->reason = SNES_CONVERGED_ITERATING; 4852 PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4853 PetscUseTypeMethod(snes, solve); 4854 PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 4855 PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name); 4856 snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 4857 4858 if (snes->lagjac_persist) snes->jac_iter += snes->iter; 4859 if (snes->lagpre_persist) snes->pre_iter += snes->iter; 4860 4861 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 4862 if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4863 /* Call converged reason views. This may involve user-provided viewers as well */ 4864 PetscCall(SNESConvergedReasonViewFromOptions(snes)); 4865 4866 if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 4867 if (snes->reason < 0) break; 4868 if (grid < snes->gridsequence) { 4869 DM fine; 4870 Vec xnew; 4871 Mat interp; 4872 4873 PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 4874 PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 4875 PetscCall(DMGetCoordinatesLocalSetUp(fine)); 4876 PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 4877 PetscCall(DMCreateGlobalVector(fine, &xnew)); 4878 PetscCall(MatInterpolate(interp, x, xnew)); 4879 PetscCall(DMInterpolate(snes->dm, interp, fine)); 4880 PetscCall(MatDestroy(&interp)); 4881 x = xnew; 4882 4883 PetscCall(SNESReset(snes)); 4884 PetscCall(SNESSetDM(snes, fine)); 4885 PetscCall(SNESResetFromOptions(snes)); 4886 PetscCall(DMDestroy(&fine)); 4887 PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4888 } 4889 } 4890 PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 4891 PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 4892 PetscCall(DMMonitor(snes->dm)); 4893 PetscCall(SNESMonitorPauseFinal_Internal(snes)); 4894 4895 PetscCall(VecDestroy(&xcreated)); 4896 PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 4897 PetscFunctionReturn(PETSC_SUCCESS); 4898 } 4899 4900 /* --------- Internal routines for SNES Package --------- */ 4901 4902 /*@ 4903 SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES` 4904 4905 Collective 4906 4907 Input Parameters: 4908 + snes - the `SNES` context 4909 - type - a known method 4910 4911 Options Database Key: 4912 . -snes_type <type> - Sets the method; use -help for a list 4913 of available methods (for instance, newtonls or newtontr) 4914 4915 Level: intermediate 4916 4917 Notes: 4918 See `SNESType` for available methods (for instance) 4919 + `SNESNEWTONLS` - Newton's method with line search 4920 (systems of nonlinear equations) 4921 - `SNESNEWTONTR` - Newton's method with trust region 4922 (systems of nonlinear equations) 4923 4924 Normally, it is best to use the `SNESSetFromOptions()` command and then 4925 set the `SNES` solver type from the options database rather than by using 4926 this routine. Using the options database provides the user with 4927 maximum flexibility in evaluating the many nonlinear solvers. 4928 The `SNESSetType()` routine is provided for those situations where it 4929 is necessary to set the nonlinear solver independently of the command 4930 line or options database. This might be the case, for example, when 4931 the choice of solver changes during the execution of the program, 4932 and the user's application is taking responsibility for choosing the 4933 appropriate method. 4934 4935 Developer Note: 4936 `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4937 the constructor in that list and calls it to create the specific object. 4938 4939 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 4940 @*/ 4941 PetscErrorCode SNESSetType(SNES snes, SNESType type) 4942 { 4943 PetscBool match; 4944 PetscErrorCode (*r)(SNES); 4945 4946 PetscFunctionBegin; 4947 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4948 PetscAssertPointer(type, 2); 4949 4950 PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 4951 if (match) PetscFunctionReturn(PETSC_SUCCESS); 4952 4953 PetscCall(PetscFunctionListFind(SNESList, type, &r)); 4954 PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 4955 /* Destroy the previous private SNES context */ 4956 PetscTryTypeMethod(snes, destroy); 4957 /* Reinitialize type-specific function pointers in SNESOps structure */ 4958 snes->ops->reset = NULL; 4959 snes->ops->setup = NULL; 4960 snes->ops->solve = NULL; 4961 snes->ops->view = NULL; 4962 snes->ops->setfromoptions = NULL; 4963 snes->ops->destroy = NULL; 4964 4965 /* It may happen the user has customized the line search before calling SNESSetType */ 4966 if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 4967 4968 /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 4969 snes->setupcalled = PETSC_FALSE; 4970 4971 PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 4972 PetscCall((*r)(snes)); 4973 PetscFunctionReturn(PETSC_SUCCESS); 4974 } 4975 4976 /*@ 4977 SNESGetType - Gets the `SNES` method type and name (as a string). 4978 4979 Not Collective 4980 4981 Input Parameter: 4982 . snes - nonlinear solver context 4983 4984 Output Parameter: 4985 . type - `SNES` method (a character string) 4986 4987 Level: intermediate 4988 4989 .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 4990 @*/ 4991 PetscErrorCode SNESGetType(SNES snes, SNESType *type) 4992 { 4993 PetscFunctionBegin; 4994 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4995 PetscAssertPointer(type, 2); 4996 *type = ((PetscObject)snes)->type_name; 4997 PetscFunctionReturn(PETSC_SUCCESS); 4998 } 4999 5000 /*@ 5001 SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 5002 5003 Logically Collective 5004 5005 Input Parameters: 5006 + snes - the `SNES` context obtained from `SNESCreate()` 5007 - u - the solution vector 5008 5009 Level: beginner 5010 5011 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 5012 @*/ 5013 PetscErrorCode SNESSetSolution(SNES snes, Vec u) 5014 { 5015 DM dm; 5016 5017 PetscFunctionBegin; 5018 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5019 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 5020 PetscCall(PetscObjectReference((PetscObject)u)); 5021 PetscCall(VecDestroy(&snes->vec_sol)); 5022 5023 snes->vec_sol = u; 5024 5025 PetscCall(SNESGetDM(snes, &dm)); 5026 PetscCall(DMShellSetGlobalVector(dm, u)); 5027 PetscFunctionReturn(PETSC_SUCCESS); 5028 } 5029 5030 /*@ 5031 SNESGetSolution - Returns the vector where the approximate solution is 5032 stored. This is the fine grid solution when using `SNESSetGridSequence()`. 5033 5034 Not Collective, but `x` is parallel if `snes` is parallel 5035 5036 Input Parameter: 5037 . snes - the `SNES` context 5038 5039 Output Parameter: 5040 . x - the solution 5041 5042 Level: intermediate 5043 5044 .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 5045 @*/ 5046 PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 5047 { 5048 PetscFunctionBegin; 5049 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5050 PetscAssertPointer(x, 2); 5051 *x = snes->vec_sol; 5052 PetscFunctionReturn(PETSC_SUCCESS); 5053 } 5054 5055 /*@ 5056 SNESGetSolutionUpdate - Returns the vector where the solution update is 5057 stored. 5058 5059 Not Collective, but `x` is parallel if `snes` is parallel 5060 5061 Input Parameter: 5062 . snes - the `SNES` context 5063 5064 Output Parameter: 5065 . x - the solution update 5066 5067 Level: advanced 5068 5069 .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 5070 @*/ 5071 PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 5072 { 5073 PetscFunctionBegin; 5074 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5075 PetscAssertPointer(x, 2); 5076 *x = snes->vec_sol_update; 5077 PetscFunctionReturn(PETSC_SUCCESS); 5078 } 5079 5080 /*@C 5081 SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 5082 5083 Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet. 5084 5085 Input Parameter: 5086 . snes - the `SNES` context 5087 5088 Output Parameters: 5089 + r - the vector that is used to store residuals (or `NULL` if you don't want it) 5090 . f - the function (or `NULL` if you don't want it); for calling sequence see `SNESFunctionFn` 5091 - ctx - the function context (or `NULL` if you don't want it) 5092 5093 Level: advanced 5094 5095 Note: 5096 The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function 5097 5098 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn` 5099 @*/ 5100 PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx) 5101 { 5102 DM dm; 5103 5104 PetscFunctionBegin; 5105 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5106 if (r) { 5107 if (!snes->vec_func) { 5108 if (snes->vec_rhs) { 5109 PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 5110 } else if (snes->vec_sol) { 5111 PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 5112 } else if (snes->dm) { 5113 PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 5114 } 5115 } 5116 *r = snes->vec_func; 5117 } 5118 PetscCall(SNESGetDM(snes, &dm)); 5119 PetscCall(DMSNESGetFunction(dm, f, ctx)); 5120 PetscFunctionReturn(PETSC_SUCCESS); 5121 } 5122 5123 /*@C 5124 SNESGetNGS - Returns the function and context set with `SNESSetNGS()` 5125 5126 Input Parameter: 5127 . snes - the `SNES` context 5128 5129 Output Parameters: 5130 + f - the function (or `NULL`) see `SNESNGSFn` for calling sequence 5131 - ctx - the function context (or `NULL`) 5132 5133 Level: advanced 5134 5135 .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn` 5136 @*/ 5137 PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx) 5138 { 5139 DM dm; 5140 5141 PetscFunctionBegin; 5142 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5143 PetscCall(SNESGetDM(snes, &dm)); 5144 PetscCall(DMSNESGetNGS(dm, f, ctx)); 5145 PetscFunctionReturn(PETSC_SUCCESS); 5146 } 5147 5148 /*@ 5149 SNESSetOptionsPrefix - Sets the prefix used for searching for all 5150 `SNES` options in the database. 5151 5152 Logically Collective 5153 5154 Input Parameters: 5155 + snes - the `SNES` context 5156 - prefix - the prefix to prepend to all option names 5157 5158 Level: advanced 5159 5160 Note: 5161 A hyphen (-) must NOT be given at the beginning of the prefix name. 5162 The first character of all runtime options is AUTOMATICALLY the hyphen. 5163 5164 .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 5165 @*/ 5166 PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5167 { 5168 PetscFunctionBegin; 5169 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5170 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 5171 if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 5172 if (snes->linesearch) { 5173 PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 5174 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 5175 } 5176 PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 5177 PetscFunctionReturn(PETSC_SUCCESS); 5178 } 5179 5180 /*@ 5181 SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5182 `SNES` options in the database. 5183 5184 Logically Collective 5185 5186 Input Parameters: 5187 + snes - the `SNES` context 5188 - prefix - the prefix to prepend to all option names 5189 5190 Level: advanced 5191 5192 Note: 5193 A hyphen (-) must NOT be given at the beginning of the prefix name. 5194 The first character of all runtime options is AUTOMATICALLY the hyphen. 5195 5196 .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 5197 @*/ 5198 PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5199 { 5200 PetscFunctionBegin; 5201 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5202 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 5203 if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 5204 if (snes->linesearch) { 5205 PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 5206 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 5207 } 5208 PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 5209 PetscFunctionReturn(PETSC_SUCCESS); 5210 } 5211 5212 /*@ 5213 SNESGetOptionsPrefix - Gets the prefix used for searching for all 5214 `SNES` options in the database. 5215 5216 Not Collective 5217 5218 Input Parameter: 5219 . snes - the `SNES` context 5220 5221 Output Parameter: 5222 . prefix - pointer to the prefix string used 5223 5224 Level: advanced 5225 5226 .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 5227 @*/ 5228 PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5229 { 5230 PetscFunctionBegin; 5231 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5232 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 5233 PetscFunctionReturn(PETSC_SUCCESS); 5234 } 5235 5236 /*@C 5237 SNESRegister - Adds a method to the nonlinear solver package. 5238 5239 Not Collective 5240 5241 Input Parameters: 5242 + sname - name of a new user-defined solver 5243 - function - routine to create method context 5244 5245 Level: advanced 5246 5247 Note: 5248 `SNESRegister()` may be called multiple times to add several user-defined solvers. 5249 5250 Example Usage: 5251 .vb 5252 SNESRegister("my_solver", MySolverCreate); 5253 .ve 5254 5255 Then, your solver can be chosen with the procedural interface via 5256 .vb 5257 SNESSetType(snes, "my_solver") 5258 .ve 5259 or at runtime via the option 5260 .vb 5261 -snes_type my_solver 5262 .ve 5263 5264 .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()` 5265 @*/ 5266 PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5267 { 5268 PetscFunctionBegin; 5269 PetscCall(SNESInitializePackage()); 5270 PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 5271 PetscFunctionReturn(PETSC_SUCCESS); 5272 } 5273 5274 PetscErrorCode SNESTestLocalMin(SNES snes) 5275 { 5276 PetscInt N, i, j; 5277 Vec u, uh, fh; 5278 PetscScalar value; 5279 PetscReal norm; 5280 5281 PetscFunctionBegin; 5282 PetscCall(SNESGetSolution(snes, &u)); 5283 PetscCall(VecDuplicate(u, &uh)); 5284 PetscCall(VecDuplicate(u, &fh)); 5285 5286 /* currently only works for sequential */ 5287 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 5288 PetscCall(VecGetSize(u, &N)); 5289 for (i = 0; i < N; i++) { 5290 PetscCall(VecCopy(u, uh)); 5291 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5292 for (j = -10; j < 11; j++) { 5293 value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 5294 PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5295 PetscCall(SNESComputeFunction(snes, uh, fh)); 5296 PetscCall(VecNorm(fh, NORM_2, &norm)); 5297 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5298 value = -value; 5299 PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5300 } 5301 } 5302 PetscCall(VecDestroy(&uh)); 5303 PetscCall(VecDestroy(&fh)); 5304 PetscFunctionReturn(PETSC_SUCCESS); 5305 } 5306 5307 /*@ 5308 SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 5309 computing relative tolerance for linear solvers within an inexact 5310 Newton method. 5311 5312 Logically Collective 5313 5314 Input Parameters: 5315 + snes - `SNES` context 5316 - flag - `PETSC_TRUE` or `PETSC_FALSE` 5317 5318 Options Database Keys: 5319 + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 5320 . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 5321 . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 5322 . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 5323 . -snes_ksp_ew_gamma <gamma> - Sets gamma 5324 . -snes_ksp_ew_alpha <alpha> - Sets alpha 5325 . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 5326 - -snes_ksp_ew_threshold <threshold> - Sets threshold 5327 5328 Level: advanced 5329 5330 Note: 5331 The default is to use a constant relative tolerance for 5332 the inner linear solvers. Alternatively, one can use the 5333 Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance 5334 is reset at each Newton iteration according progress of the nonlinear 5335 solver. 5336 5337 .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 5338 @*/ 5339 PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5340 { 5341 PetscFunctionBegin; 5342 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5343 PetscValidLogicalCollectiveBool(snes, flag, 2); 5344 snes->ksp_ewconv = flag; 5345 PetscFunctionReturn(PETSC_SUCCESS); 5346 } 5347 5348 /*@ 5349 SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 5350 for computing relative tolerance for linear solvers within an 5351 inexact Newton method. 5352 5353 Not Collective 5354 5355 Input Parameter: 5356 . snes - `SNES` context 5357 5358 Output Parameter: 5359 . flag - `PETSC_TRUE` or `PETSC_FALSE` 5360 5361 Level: advanced 5362 5363 .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 5364 @*/ 5365 PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5366 { 5367 PetscFunctionBegin; 5368 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5369 PetscAssertPointer(flag, 2); 5370 *flag = snes->ksp_ewconv; 5371 PetscFunctionReturn(PETSC_SUCCESS); 5372 } 5373 5374 /*@ 5375 SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 5376 convergence criteria for the linear solvers within an inexact 5377 Newton method. 5378 5379 Logically Collective 5380 5381 Input Parameters: 5382 + snes - `SNES` context 5383 . version - version 1, 2 (default is 2), 3 or 4 5384 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 5385 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5386 . gamma - multiplicative factor for version 2 rtol computation 5387 (0 <= gamma2 <= 1) 5388 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 5389 . alpha2 - power for safeguard 5390 - threshold - threshold for imposing safeguard (0 < threshold < 1) 5391 5392 Level: advanced 5393 5394 Notes: 5395 Version 3 was contributed by Luis Chacon, June 2006. 5396 5397 Use `PETSC_CURRENT` to retain the default for any of the parameters. 5398 5399 .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 5400 @*/ 5401 PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5402 { 5403 SNESKSPEW *kctx; 5404 5405 PetscFunctionBegin; 5406 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5407 kctx = (SNESKSPEW *)snes->kspconvctx; 5408 PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5409 PetscValidLogicalCollectiveInt(snes, version, 2); 5410 PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5411 PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5412 PetscValidLogicalCollectiveReal(snes, gamma, 5); 5413 PetscValidLogicalCollectiveReal(snes, alpha, 6); 5414 PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5415 PetscValidLogicalCollectiveReal(snes, threshold, 8); 5416 5417 if (version != PETSC_CURRENT) kctx->version = version; 5418 if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0; 5419 if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max; 5420 if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma; 5421 if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha; 5422 if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2; 5423 if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold; 5424 5425 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); 5426 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); 5427 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); 5428 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); 5429 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); 5430 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); 5431 PetscFunctionReturn(PETSC_SUCCESS); 5432 } 5433 5434 /*@ 5435 SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 5436 convergence criteria for the linear solvers within an inexact 5437 Newton method. 5438 5439 Not Collective 5440 5441 Input Parameter: 5442 . snes - `SNES` context 5443 5444 Output Parameters: 5445 + version - version 1, 2 (default is 2), 3 or 4 5446 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 5447 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5448 . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 5449 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 5450 . alpha2 - power for safeguard 5451 - threshold - threshold for imposing safeguard (0 < threshold < 1) 5452 5453 Level: advanced 5454 5455 .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 5456 @*/ 5457 PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5458 { 5459 SNESKSPEW *kctx; 5460 5461 PetscFunctionBegin; 5462 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5463 kctx = (SNESKSPEW *)snes->kspconvctx; 5464 PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5465 if (version) *version = kctx->version; 5466 if (rtol_0) *rtol_0 = kctx->rtol_0; 5467 if (rtol_max) *rtol_max = kctx->rtol_max; 5468 if (gamma) *gamma = kctx->gamma; 5469 if (alpha) *alpha = kctx->alpha; 5470 if (alpha2) *alpha2 = kctx->alpha2; 5471 if (threshold) *threshold = kctx->threshold; 5472 PetscFunctionReturn(PETSC_SUCCESS); 5473 } 5474 5475 PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5476 { 5477 SNES snes = (SNES)ctx; 5478 SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 5479 PetscReal rtol = PETSC_CURRENT, stol; 5480 5481 PetscFunctionBegin; 5482 if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 5483 if (!snes->iter) { 5484 rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 5485 PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 5486 } else { 5487 PetscCheck(kctx->version >= 1 && kctx->version <= 4, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only versions 1-4 are supported: %" PetscInt_FMT, kctx->version); 5488 if (kctx->version == 1) { 5489 rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 5490 stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 5491 if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 5492 } else if (kctx->version == 2) { 5493 rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 5494 stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 5495 if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 5496 } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 5497 rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 5498 /* safeguard: avoid sharp decrease of rtol */ 5499 stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 5500 stol = PetscMax(rtol, stol); 5501 rtol = PetscMin(kctx->rtol_0, stol); 5502 /* safeguard: avoid oversolving */ 5503 stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 5504 stol = PetscMax(rtol, stol); 5505 rtol = PetscMin(kctx->rtol_0, stol); 5506 } else /* if (kctx->version == 4) */ { 5507 /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 5508 PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 5509 PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 5510 PetscReal rk = ared / pred; 5511 if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 5512 else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 5513 else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 5514 else rtol = kctx->v4_m2 * kctx->rtol_last; 5515 5516 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; 5517 kctx->rtol_last_2 = kctx->rtol_last; 5518 kctx->rk_last_2 = kctx->rk_last; 5519 kctx->rk_last = rk; 5520 } 5521 } 5522 /* safeguard: avoid rtol greater than rtol_max */ 5523 rtol = PetscMin(rtol, kctx->rtol_max); 5524 PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT)); 5525 PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 5526 PetscFunctionReturn(PETSC_SUCCESS); 5527 } 5528 5529 PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx) 5530 { 5531 SNES snes = (SNES)ctx; 5532 SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 5533 PCSide pcside; 5534 Vec lres; 5535 5536 PetscFunctionBegin; 5537 if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS); 5538 PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 5539 kctx->norm_last = snes->norm; 5540 if (kctx->version == 1 || kctx->version == 4) { 5541 PC pc; 5542 PetscBool getRes; 5543 5544 PetscCall(KSPGetPC(ksp, &pc)); 5545 PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 5546 if (!getRes) { 5547 KSPNormType normtype; 5548 5549 PetscCall(KSPGetNormType(ksp, &normtype)); 5550 getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 5551 } 5552 PetscCall(KSPGetPCSide(ksp, &pcside)); 5553 if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 5554 PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 5555 } else { 5556 /* KSP residual is preconditioned residual */ 5557 /* compute true linear residual norm */ 5558 Mat J; 5559 PetscCall(KSPGetOperators(ksp, &J, NULL)); 5560 PetscCall(VecDuplicate(b, &lres)); 5561 PetscCall(MatMult(J, x, lres)); 5562 PetscCall(VecAYPX(lres, -1.0, b)); 5563 PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 5564 PetscCall(VecDestroy(&lres)); 5565 } 5566 } 5567 PetscFunctionReturn(PETSC_SUCCESS); 5568 } 5569 5570 /*@ 5571 SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5572 5573 Not Collective, but if `snes` is parallel, then `ksp` is parallel 5574 5575 Input Parameter: 5576 . snes - the `SNES` context 5577 5578 Output Parameter: 5579 . ksp - the `KSP` context 5580 5581 Level: beginner 5582 5583 Notes: 5584 The user can then directly manipulate the `KSP` context to set various 5585 options, etc. Likewise, the user can then extract and manipulate the 5586 `PC` contexts as well. 5587 5588 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. 5589 5590 .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5591 @*/ 5592 PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5593 { 5594 PetscFunctionBegin; 5595 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5596 PetscAssertPointer(ksp, 2); 5597 5598 if (!snes->ksp) { 5599 PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 5600 PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5601 5602 PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes)); 5603 PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes)); 5604 5605 PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 5606 PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5607 } 5608 *ksp = snes->ksp; 5609 PetscFunctionReturn(PETSC_SUCCESS); 5610 } 5611 5612 #include <petsc/private/dmimpl.h> 5613 /*@ 5614 SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners 5615 5616 Logically Collective 5617 5618 Input Parameters: 5619 + snes - the nonlinear solver context 5620 - dm - the `DM`, cannot be `NULL` 5621 5622 Level: intermediate 5623 5624 Note: 5625 A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5626 even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5627 problems using the same function space. 5628 5629 .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 5630 @*/ 5631 PetscErrorCode SNESSetDM(SNES snes, DM dm) 5632 { 5633 KSP ksp; 5634 DMSNES sdm; 5635 5636 PetscFunctionBegin; 5637 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5638 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 5639 PetscCall(PetscObjectReference((PetscObject)dm)); 5640 if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 5641 if (snes->dm->dmsnes && !dm->dmsnes) { 5642 PetscCall(DMCopyDMSNES(snes->dm, dm)); 5643 PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5644 if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 5645 } 5646 PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 5647 PetscCall(DMDestroy(&snes->dm)); 5648 } 5649 snes->dm = dm; 5650 snes->dmAuto = PETSC_FALSE; 5651 5652 PetscCall(SNESGetKSP(snes, &ksp)); 5653 PetscCall(KSPSetDM(ksp, dm)); 5654 PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5655 if (snes->npc) { 5656 PetscCall(SNESSetDM(snes->npc, snes->dm)); 5657 PetscCall(SNESSetNPCSide(snes, snes->npcside)); 5658 } 5659 PetscFunctionReturn(PETSC_SUCCESS); 5660 } 5661 5662 /*@ 5663 SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners 5664 5665 Not Collective but `dm` obtained is parallel on `snes` 5666 5667 Input Parameter: 5668 . snes - the `SNES` context 5669 5670 Output Parameter: 5671 . dm - the `DM` 5672 5673 Level: intermediate 5674 5675 .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 5676 @*/ 5677 PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5678 { 5679 PetscFunctionBegin; 5680 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5681 if (!snes->dm) { 5682 PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5683 snes->dmAuto = PETSC_TRUE; 5684 } 5685 *dm = snes->dm; 5686 PetscFunctionReturn(PETSC_SUCCESS); 5687 } 5688 5689 /*@ 5690 SNESSetNPC - Sets the nonlinear preconditioner to be used. 5691 5692 Collective 5693 5694 Input Parameters: 5695 + snes - iterative context obtained from `SNESCreate()` 5696 - npc - the `SNES` nonlinear preconditioner object 5697 5698 Options Database Key: 5699 . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5700 5701 Level: developer 5702 5703 Notes: 5704 This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API. 5705 5706 Only some `SNESType` can use a nonlinear preconditioner 5707 5708 .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 5709 @*/ 5710 PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5711 { 5712 PetscFunctionBegin; 5713 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5714 PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5715 PetscCheckSameComm(snes, 1, npc, 2); 5716 PetscCall(PetscObjectReference((PetscObject)npc)); 5717 PetscCall(SNESDestroy(&snes->npc)); 5718 snes->npc = npc; 5719 PetscFunctionReturn(PETSC_SUCCESS); 5720 } 5721 5722 /*@ 5723 SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 5724 5725 Not Collective; but any changes to the obtained the `pc` object must be applied collectively 5726 5727 Input Parameter: 5728 . snes - iterative context obtained from `SNESCreate()` 5729 5730 Output Parameter: 5731 . pc - the `SNES` preconditioner context 5732 5733 Options Database Key: 5734 . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5735 5736 Level: advanced 5737 5738 Notes: 5739 If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will 5740 be used as the nonlinear preconditioner for the current `SNES`. 5741 5742 The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 5743 `SNES`. These may be overwritten if needed. 5744 5745 Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner 5746 5747 .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 5748 @*/ 5749 PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5750 { 5751 const char *optionsprefix; 5752 5753 PetscFunctionBegin; 5754 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5755 PetscAssertPointer(pc, 2); 5756 if (!snes->npc) { 5757 void *ctx; 5758 5759 PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 5760 PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 5761 PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 5762 PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 5763 PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5764 if (snes->ops->usercompute) { 5765 PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy)); 5766 } else { 5767 PetscCall(SNESGetApplicationContext(snes, &ctx)); 5768 PetscCall(SNESSetApplicationContext(snes->npc, ctx)); 5769 } 5770 PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 5771 } 5772 *pc = snes->npc; 5773 PetscFunctionReturn(PETSC_SUCCESS); 5774 } 5775 5776 /*@ 5777 SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES` 5778 5779 Not Collective 5780 5781 Input Parameter: 5782 . snes - iterative context obtained from `SNESCreate()` 5783 5784 Output Parameter: 5785 . has_npc - whether the `SNES` has a nonlinear preconditioner or not 5786 5787 Level: developer 5788 5789 .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()` 5790 @*/ 5791 PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5792 { 5793 PetscFunctionBegin; 5794 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5795 PetscAssertPointer(has_npc, 2); 5796 *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE; 5797 PetscFunctionReturn(PETSC_SUCCESS); 5798 } 5799 5800 /*@ 5801 SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`. 5802 5803 Logically Collective 5804 5805 Input Parameter: 5806 . snes - iterative context obtained from `SNESCreate()` 5807 5808 Output Parameter: 5809 . side - the preconditioning side, where side is one of 5810 .vb 5811 PC_LEFT - left preconditioning 5812 PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5813 .ve 5814 5815 Options Database Key: 5816 . -snes_npc_side <right,left> - nonlinear preconditioner side 5817 5818 Level: intermediate 5819 5820 Note: 5821 `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 5822 5823 .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5824 @*/ 5825 PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5826 { 5827 PetscFunctionBegin; 5828 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5829 PetscValidLogicalCollectiveEnum(snes, side, 2); 5830 if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 5831 PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5832 snes->npcside = side; 5833 PetscFunctionReturn(PETSC_SUCCESS); 5834 } 5835 5836 /*@ 5837 SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`. 5838 5839 Not Collective 5840 5841 Input Parameter: 5842 . snes - iterative context obtained from `SNESCreate()` 5843 5844 Output Parameter: 5845 . side - the preconditioning side, where side is one of 5846 .vb 5847 `PC_LEFT` - left preconditioning 5848 `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5849 .ve 5850 5851 Level: intermediate 5852 5853 .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide` 5854 @*/ 5855 PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5856 { 5857 PetscFunctionBegin; 5858 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5859 PetscAssertPointer(side, 2); 5860 *side = snes->npcside; 5861 PetscFunctionReturn(PETSC_SUCCESS); 5862 } 5863 5864 /*@ 5865 SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES` 5866 5867 Collective 5868 5869 Input Parameters: 5870 + snes - iterative context obtained from `SNESCreate()` 5871 - linesearch - the linesearch object 5872 5873 Level: developer 5874 5875 Note: 5876 This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it 5877 to configure it using the API). 5878 5879 .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()` 5880 @*/ 5881 PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5882 { 5883 PetscFunctionBegin; 5884 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5885 PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 5886 PetscCheckSameComm(snes, 1, linesearch, 2); 5887 PetscCall(PetscObjectReference((PetscObject)linesearch)); 5888 PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5889 5890 snes->linesearch = linesearch; 5891 PetscFunctionReturn(PETSC_SUCCESS); 5892 } 5893 5894 /*@ 5895 SNESGetLineSearch - Returns the line search associated with the `SNES`. 5896 5897 Not Collective 5898 5899 Input Parameter: 5900 . snes - iterative context obtained from `SNESCreate()` 5901 5902 Output Parameter: 5903 . linesearch - linesearch context 5904 5905 Level: beginner 5906 5907 Notes: 5908 It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`. 5909 5910 You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options. 5911 5912 .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()` 5913 @*/ 5914 PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5915 { 5916 const char *optionsprefix; 5917 5918 PetscFunctionBegin; 5919 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5920 PetscAssertPointer(linesearch, 2); 5921 if (!snes->linesearch) { 5922 PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 5923 PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 5924 PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 5925 PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 5926 PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 5927 } 5928 *linesearch = snes->linesearch; 5929 PetscFunctionReturn(PETSC_SUCCESS); 5930 } 5931