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