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