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