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