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