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