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