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