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