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