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