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