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