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