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 on snes 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(0); 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(0); 66 } 67 68 /*@ 69 SNESSetAlwaysComputesFinalResidual - tells the `SNES` to always compute the residual at the final solution 70 71 Logically Collective on snes 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(0); 91 } 92 93 /*@ 94 SNESGetAlwaysComputesFinalResidual - checks if the `SNES` always computes the residual at the final solution 95 96 Logically Collective on snes 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(0); 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 on snes 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(0); 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 on snes 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(0); 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 on snes 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(0); 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 on snes 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(0); 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(0); 240 } 241 242 /*@ 243 SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()`; 244 245 Logically Collective on snes 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(0); 264 } 265 266 /*@C 267 SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`. 268 269 Collective on snes 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(0); 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 on snes 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(0); 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 on snes 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(0); 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(0); 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(0); 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(0); 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(0); 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(0); 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(0); 766 } 767 768 static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes) 769 { 770 PetscInt i; 771 772 PetscFunctionBegin; 773 if (!snes->pauseFinal) PetscFunctionReturn(0); 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(0); 803 } 804 805 /*@C 806 SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 807 808 Collective on snes 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(0); 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(0); 869 } 870 871 /*@ 872 SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options. 873 874 Collective on snes 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(0); 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 on snes 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(0); 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 on snes 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(0); 1197 } 1198 1199 /*@ 1200 SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers. 1201 1202 Logically Collective on snes 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(0); 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(0); 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(0); 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(0); 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(0); 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(0); 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(0); 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(0); 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(0); 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(0); 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(0); 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 on snes 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(0); 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(0); 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(0); 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 on snes 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(0); 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(0); 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(0); 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 on snes 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 on snes 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(0); 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 on snes 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(0); 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(0); 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 on snes 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(0); 1953 } 1954 1955 /*@ 1956 SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring 1957 of the `SNES` method. 1958 1959 Logically Collective on snes 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(0); 1975 } 1976 1977 /*@ 1978 SNESSetFunctionNorm - Sets the last computed residual norm. 1979 1980 Logically Collective on snes 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(0); 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(0); 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(0); 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(0); 2071 } 2072 2073 /*@C 2074 SNESSetFunctionType - Sets the `SNESFunctionType` 2075 of the `SNES` method. 2076 2077 Logically Collective on snes 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(0); 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 on snes 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(0); 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 on snes 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(0); 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(0); 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(0); 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(0); 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 on snes 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(0); 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(0); 2334 } 2335 2336 /*@C 2337 SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the problem 2338 2339 Logically Collective on snes 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(0); 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 on snes 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(0); 2389 } 2390 2391 /*@ 2392 SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`. 2393 2394 Collective on snes 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(0); 2451 } 2452 2453 /*@ 2454 SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`. 2455 2456 Collective on snes 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(0); 2506 } 2507 2508 /*@ 2509 SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`. 2510 2511 Collective on snes 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(0); 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(0); 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(0); 2712 } 2713 2714 /*@ 2715 SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`. 2716 2717 Collective on snes 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(0); 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(0); 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(0); 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(0); 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 on snes 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 on snes 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(0); 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(0); 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(0); 3132 } 3133 3134 /*@ 3135 SNESSetUp - Sets up the internal data structures for the later use 3136 of a nonlinear solver. 3137 3138 Collective on snes 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 PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *); 3161 PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *); 3162 PetscErrorCode (*func)(SNES, Vec, Vec, void *); 3163 Vec f, fpc; 3164 void *funcctx; 3165 PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *); 3166 void *jacctx, *appctx; 3167 Mat j, jpre; 3168 3169 PetscFunctionBegin; 3170 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3171 if (snes->setupcalled) PetscFunctionReturn(0); 3172 PetscCall(PetscLogEventBegin(SNES_Setup, snes, 0, 0, 0)); 3173 3174 if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS)); 3175 3176 PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL)); 3177 3178 PetscCall(SNESGetDM(snes, &dm)); 3179 PetscCall(DMGetDMSNES(dm, &sdm)); 3180 PetscCall(SNESSetDefaultComputeJacobian(snes)); 3181 3182 if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func)); 3183 3184 if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 3185 3186 if (snes->linesearch) { 3187 PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 3188 PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction)); 3189 } 3190 3191 if (snes->npc && snes->npcside == PC_LEFT) { 3192 snes->mf = PETSC_TRUE; 3193 snes->mf_operator = PETSC_FALSE; 3194 } 3195 3196 if (snes->npc) { 3197 /* copy the DM over */ 3198 PetscCall(SNESGetDM(snes, &dm)); 3199 PetscCall(SNESSetDM(snes->npc, dm)); 3200 3201 PetscCall(SNESGetFunction(snes, &f, &func, &funcctx)); 3202 PetscCall(VecDuplicate(f, &fpc)); 3203 PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx)); 3204 PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx)); 3205 PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx)); 3206 PetscCall(SNESGetApplicationContext(snes, &appctx)); 3207 PetscCall(SNESSetApplicationContext(snes->npc, appctx)); 3208 PetscCall(VecDestroy(&fpc)); 3209 3210 /* copy the function pointers over */ 3211 PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc)); 3212 3213 /* default to 1 iteration */ 3214 PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs)); 3215 if (snes->npcside == PC_RIGHT) { 3216 PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY)); 3217 } else { 3218 PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE)); 3219 } 3220 PetscCall(SNESSetFromOptions(snes->npc)); 3221 3222 /* copy the line search context over */ 3223 if (snes->linesearch && snes->npc->linesearch) { 3224 PetscCall(SNESGetLineSearch(snes, &linesearch)); 3225 PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch)); 3226 PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx)); 3227 PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx)); 3228 PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx)); 3229 PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx)); 3230 PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch)); 3231 } 3232 } 3233 if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version)); 3234 if (snes->ops->usercompute && !snes->user) PetscCall((*snes->ops->usercompute)(snes, (void **)&snes->user)); 3235 3236 snes->jac_iter = 0; 3237 snes->pre_iter = 0; 3238 3239 PetscTryTypeMethod(snes, setup); 3240 3241 PetscCall(SNESSetDefaultComputeJacobian(snes)); 3242 3243 if (snes->npc && snes->npcside == PC_LEFT) { 3244 if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3245 if (snes->linesearch) { 3246 PetscCall(SNESGetLineSearch(snes, &linesearch)); 3247 PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC)); 3248 } 3249 } 3250 } 3251 PetscCall(PetscLogEventEnd(SNES_Setup, snes, 0, 0, 0)); 3252 snes->setupcalled = PETSC_TRUE; 3253 PetscFunctionReturn(0); 3254 } 3255 3256 /*@ 3257 SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s 3258 3259 Collective on snes 3260 3261 Input Parameter: 3262 . snes - iterative context obtained from `SNESCreate()` 3263 3264 Level: intermediate 3265 3266 Notes: 3267 Call this if you wish to reuse a `SNES` but with different size vectors 3268 3269 Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()` 3270 3271 .seealso: `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()` 3272 @*/ 3273 PetscErrorCode SNESReset(SNES snes) 3274 { 3275 PetscFunctionBegin; 3276 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3277 if (snes->ops->userdestroy && snes->user) { 3278 PetscCall((*snes->ops->userdestroy)((void **)&snes->user)); 3279 snes->user = NULL; 3280 } 3281 if (snes->npc) PetscCall(SNESReset(snes->npc)); 3282 3283 PetscTryTypeMethod(snes, reset); 3284 if (snes->ksp) PetscCall(KSPReset(snes->ksp)); 3285 3286 if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch)); 3287 3288 PetscCall(VecDestroy(&snes->vec_rhs)); 3289 PetscCall(VecDestroy(&snes->vec_sol)); 3290 PetscCall(VecDestroy(&snes->vec_sol_update)); 3291 PetscCall(VecDestroy(&snes->vec_func)); 3292 PetscCall(MatDestroy(&snes->jacobian)); 3293 PetscCall(MatDestroy(&snes->jacobian_pre)); 3294 PetscCall(MatDestroy(&snes->picard)); 3295 PetscCall(VecDestroyVecs(snes->nwork, &snes->work)); 3296 PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork)); 3297 3298 snes->alwayscomputesfinalresidual = PETSC_FALSE; 3299 3300 snes->nwork = snes->nvwork = 0; 3301 snes->setupcalled = PETSC_FALSE; 3302 PetscFunctionReturn(0); 3303 } 3304 3305 /*@ 3306 SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object. 3307 3308 Collective on snes 3309 3310 Input Parameter: 3311 . snes - iterative context obtained from `SNESCreate()` 3312 3313 Level: intermediate 3314 3315 .seealso: `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()` 3316 @*/ 3317 PetscErrorCode SNESConvergedReasonViewCancel(SNES snes) 3318 { 3319 PetscInt i; 3320 3321 PetscFunctionBegin; 3322 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3323 for (i = 0; i < snes->numberreasonviews; i++) { 3324 if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i])); 3325 } 3326 snes->numberreasonviews = 0; 3327 PetscFunctionReturn(0); 3328 } 3329 3330 /*@C 3331 SNESDestroy - Destroys the nonlinear solver context that was created 3332 with `SNESCreate()`. 3333 3334 Collective on snes 3335 3336 Input Parameter: 3337 . snes - the `SNES` context 3338 3339 Level: beginner 3340 3341 .seealso: `SNES`, `SNESCreate()`, `SNESSolve()` 3342 @*/ 3343 PetscErrorCode SNESDestroy(SNES *snes) 3344 { 3345 PetscFunctionBegin; 3346 if (!*snes) PetscFunctionReturn(0); 3347 PetscValidHeaderSpecific((*snes), SNES_CLASSID, 1); 3348 if (--((PetscObject)(*snes))->refct > 0) { 3349 *snes = NULL; 3350 PetscFunctionReturn(0); 3351 } 3352 3353 PetscCall(SNESReset((*snes))); 3354 PetscCall(SNESDestroy(&(*snes)->npc)); 3355 3356 /* if memory was published with SAWs then destroy it */ 3357 PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes)); 3358 PetscTryTypeMethod((*snes), destroy); 3359 3360 if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes)); 3361 PetscCall(DMDestroy(&(*snes)->dm)); 3362 PetscCall(KSPDestroy(&(*snes)->ksp)); 3363 PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch)); 3364 3365 PetscCall(PetscFree((*snes)->kspconvctx)); 3366 if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP)); 3367 if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its)); 3368 PetscCall(SNESMonitorCancel((*snes))); 3369 PetscCall(SNESConvergedReasonViewCancel((*snes))); 3370 PetscCall(PetscHeaderDestroy(snes)); 3371 PetscFunctionReturn(0); 3372 } 3373 3374 /* ----------- Routines to set solver parameters ---------- */ 3375 3376 /*@ 3377 SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve. 3378 3379 Logically Collective on snes 3380 3381 Input Parameters: 3382 + snes - the `SNES` context 3383 - lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3384 the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3385 3386 Options Database Keys: 3387 + -snes_lag_jacobian_persists <true,false> - sets the persistence 3388 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3389 . -snes_lag_preconditioner_persists <true,false> - sets the persistence 3390 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3391 3392 Notes: 3393 The default is 1 3394 The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called 3395 3396 `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves. 3397 3398 Level: intermediate 3399 3400 .seealso: `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`, 3401 `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()` 3402 @*/ 3403 PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag) 3404 { 3405 PetscFunctionBegin; 3406 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3407 PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 3408 PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3409 PetscValidLogicalCollectiveInt(snes, lag, 2); 3410 snes->lagpreconditioner = lag; 3411 PetscFunctionReturn(0); 3412 } 3413 3414 /*@ 3415 SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do 3416 3417 Logically Collective on snes 3418 3419 Input Parameters: 3420 + snes - the `SNES` context 3421 - steps - the number of refinements to do, defaults to 0 3422 3423 Options Database Key: 3424 . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess 3425 3426 Level: intermediate 3427 3428 Note: 3429 Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3430 3431 .seealso: `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()` 3432 @*/ 3433 PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps) 3434 { 3435 PetscFunctionBegin; 3436 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3437 PetscValidLogicalCollectiveInt(snes, steps, 2); 3438 snes->gridsequence = steps; 3439 PetscFunctionReturn(0); 3440 } 3441 3442 /*@ 3443 SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do 3444 3445 Logically Collective on snes 3446 3447 Input Parameter: 3448 . snes - the `SNES` context 3449 3450 Output Parameter: 3451 . steps - the number of refinements to do, defaults to 0 3452 3453 Options Database Key: 3454 . -snes_grid_sequence <steps> - set number of refinements 3455 3456 Level: intermediate 3457 3458 Note: 3459 Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing. 3460 3461 .seealso: `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()` 3462 @*/ 3463 PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps) 3464 { 3465 PetscFunctionBegin; 3466 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3467 *steps = snes->gridsequence; 3468 PetscFunctionReturn(0); 3469 } 3470 3471 /*@ 3472 SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt 3473 3474 Not Collective 3475 3476 Input Parameter: 3477 . snes - the `SNES` context 3478 3479 Output Parameter: 3480 . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3481 the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3482 3483 Options Database Keys: 3484 + -snes_lag_jacobian_persists <true,false> - sets the persistence 3485 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3486 . -snes_lag_preconditioner_persists <true,false> - sets the persistence 3487 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3488 3489 Notes: 3490 The default is 1 3491 3492 The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3493 3494 Level: intermediate 3495 3496 .seealso: `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3497 @*/ 3498 PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag) 3499 { 3500 PetscFunctionBegin; 3501 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3502 *lag = snes->lagpreconditioner; 3503 PetscFunctionReturn(0); 3504 } 3505 3506 /*@ 3507 SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how 3508 often the preconditioner is rebuilt. 3509 3510 Logically Collective on snes 3511 3512 Input Parameters: 3513 + snes - the `SNES` context 3514 - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3515 the Jacobian is built etc. -2 means rebuild at next chance but then never again 3516 3517 Options Database Keys: 3518 + -snes_lag_jacobian_persists <true,false> - sets the persistence 3519 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3520 . -snes_lag_preconditioner_persists <true,false> - sets the persistence 3521 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag. 3522 3523 Notes: 3524 The default is 1 3525 3526 The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3527 3528 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 3529 at the next Newton step but never again (unless it is reset to another value) 3530 3531 Level: intermediate 3532 3533 .seealso: `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3534 @*/ 3535 PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag) 3536 { 3537 PetscFunctionBegin; 3538 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3539 PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater"); 3540 PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0"); 3541 PetscValidLogicalCollectiveInt(snes, lag, 2); 3542 snes->lagjacobian = lag; 3543 PetscFunctionReturn(0); 3544 } 3545 3546 /*@ 3547 SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt 3548 3549 Not Collective 3550 3551 Input Parameter: 3552 . snes - the `SNES` context 3553 3554 Output Parameter: 3555 . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3556 the Jacobian is built etc. 3557 3558 Notes: 3559 The default is 1 3560 3561 The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called. 3562 3563 Level: intermediate 3564 3565 .seealso: `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()` 3566 3567 @*/ 3568 PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag) 3569 { 3570 PetscFunctionBegin; 3571 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3572 *lag = snes->lagjacobian; 3573 PetscFunctionReturn(0); 3574 } 3575 3576 /*@ 3577 SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves 3578 3579 Logically collective on snes 3580 3581 Input Parameters: 3582 + snes - the `SNES` context 3583 - flg - jacobian lagging persists if true 3584 3585 Options Database Keys: 3586 + -snes_lag_jacobian_persists <true,false> - sets the persistence 3587 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3588 . -snes_lag_preconditioner_persists <true,false> - sets the persistence 3589 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3590 3591 Notes: 3592 Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that. 3593 3594 This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 3595 several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 3596 timesteps may present huge efficiency gains. 3597 3598 Level: advanced 3599 3600 .seealso: `SNES, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagJacobianPersists()` 3601 @*/ 3602 PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg) 3603 { 3604 PetscFunctionBegin; 3605 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3606 PetscValidLogicalCollectiveBool(snes, flg, 2); 3607 snes->lagjac_persist = flg; 3608 PetscFunctionReturn(0); 3609 } 3610 3611 /*@ 3612 SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves 3613 3614 Logically Collective on snes 3615 3616 Input Parameters: 3617 + snes - the `SNES` context 3618 - flg - preconditioner lagging persists if true 3619 3620 Options Database Keys: 3621 + -snes_lag_jacobian_persists <true,false> - sets the persistence 3622 . -snes_lag_jacobian <-2,1,2,...> - sets the lag 3623 . -snes_lag_preconditioner_persists <true,false> - sets the persistence 3624 - -snes_lag_preconditioner <-2,1,2,...> - sets the lag 3625 3626 Notes: 3627 Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that. 3628 3629 This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 3630 by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 3631 several timesteps may present huge efficiency gains. 3632 3633 Level: developer 3634 3635 .seealso: `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()` 3636 @*/ 3637 PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg) 3638 { 3639 PetscFunctionBegin; 3640 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3641 PetscValidLogicalCollectiveBool(snes, flg, 2); 3642 snes->lagpre_persist = flg; 3643 PetscFunctionReturn(0); 3644 } 3645 3646 /*@ 3647 SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm 3648 3649 Logically Collective on snes 3650 3651 Input Parameters: 3652 + snes - the `SNES` context 3653 - force - `PETSC_TRUE` require at least one iteration 3654 3655 Options Database Key: 3656 . -snes_force_iteration <force> - Sets forcing an iteration 3657 3658 Note: 3659 This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution 3660 3661 Level: intermediate 3662 3663 .seealso: `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()` 3664 @*/ 3665 PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force) 3666 { 3667 PetscFunctionBegin; 3668 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3669 snes->forceiteration = force; 3670 PetscFunctionReturn(0); 3671 } 3672 3673 /*@ 3674 SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm 3675 3676 Logically Collective on snes 3677 3678 Input Parameters: 3679 . snes - the `SNES` context 3680 3681 Output Parameter: 3682 . force - PETSC_TRUE requires at least one iteration. 3683 3684 Level: intermediate 3685 3686 .seealso: `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()` 3687 @*/ 3688 PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force) 3689 { 3690 PetscFunctionBegin; 3691 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3692 *force = snes->forceiteration; 3693 PetscFunctionReturn(0); 3694 } 3695 3696 /*@ 3697 SNESSetTolerances - Sets `SNES` various parameters used in convergence tests. 3698 3699 Logically Collective on snes 3700 3701 Input Parameters: 3702 + snes - the `SNES` context 3703 . abstol - absolute convergence tolerance 3704 . rtol - relative convergence tolerance 3705 . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 3706 . maxit - maximum number of iterations, default 50. 3707 - maxf - maximum number of function evaluations (-1 indicates no limit), default 1000 3708 3709 Options Database Keys: 3710 + -snes_atol <abstol> - Sets abstol 3711 . -snes_rtol <rtol> - Sets rtol 3712 . -snes_stol <stol> - Sets stol 3713 . -snes_max_it <maxit> - Sets maxit 3714 - -snes_max_funcs <maxf> - Sets maxf 3715 3716 Level: intermediate 3717 3718 .seealso: `SNESolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()` 3719 @*/ 3720 PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf) 3721 { 3722 PetscFunctionBegin; 3723 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3724 PetscValidLogicalCollectiveReal(snes, abstol, 2); 3725 PetscValidLogicalCollectiveReal(snes, rtol, 3); 3726 PetscValidLogicalCollectiveReal(snes, stol, 4); 3727 PetscValidLogicalCollectiveInt(snes, maxit, 5); 3728 PetscValidLogicalCollectiveInt(snes, maxf, 6); 3729 3730 if (abstol != PETSC_DEFAULT) { 3731 PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol); 3732 snes->abstol = abstol; 3733 } 3734 if (rtol != PETSC_DEFAULT) { 3735 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); 3736 snes->rtol = rtol; 3737 } 3738 if (stol != PETSC_DEFAULT) { 3739 PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol); 3740 snes->stol = stol; 3741 } 3742 if (maxit != PETSC_DEFAULT) { 3743 PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit); 3744 snes->max_its = maxit; 3745 } 3746 if (maxf != PETSC_DEFAULT) { 3747 PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf); 3748 snes->max_funcs = maxf; 3749 } 3750 snes->tolerancesset = PETSC_TRUE; 3751 PetscFunctionReturn(0); 3752 } 3753 3754 /*@ 3755 SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test. 3756 3757 Logically Collective on snes 3758 3759 Input Parameters: 3760 + snes - the `SNES` context 3761 - divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4 3762 3763 Options Database Key: 3764 . -snes_divergence_tolerance <divtol> - Sets divtol 3765 3766 Level: intermediate 3767 3768 .seealso: `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance` 3769 @*/ 3770 PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol) 3771 { 3772 PetscFunctionBegin; 3773 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3774 PetscValidLogicalCollectiveReal(snes, divtol, 2); 3775 3776 if (divtol != PETSC_DEFAULT) { 3777 snes->divtol = divtol; 3778 } else { 3779 snes->divtol = 1.0e4; 3780 } 3781 PetscFunctionReturn(0); 3782 } 3783 3784 /*@ 3785 SNESGetTolerances - Gets various parameters used in convergence tests. 3786 3787 Not Collective 3788 3789 Input Parameters: 3790 + snes - the `SNES` context 3791 . atol - absolute convergence tolerance 3792 . rtol - relative convergence tolerance 3793 . stol - convergence tolerance in terms of the norm 3794 of the change in the solution between steps 3795 . maxit - maximum number of iterations 3796 - maxf - maximum number of function evaluations 3797 3798 Note: 3799 The user can specify NULL for any parameter that is not needed. 3800 3801 Level: intermediate 3802 3803 .seealso: `SNES`, `SNESSetTolerances()` 3804 @*/ 3805 PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf) 3806 { 3807 PetscFunctionBegin; 3808 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3809 if (atol) *atol = snes->abstol; 3810 if (rtol) *rtol = snes->rtol; 3811 if (stol) *stol = snes->stol; 3812 if (maxit) *maxit = snes->max_its; 3813 if (maxf) *maxf = snes->max_funcs; 3814 PetscFunctionReturn(0); 3815 } 3816 3817 /*@ 3818 SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 3819 3820 Not Collective 3821 3822 Input Parameters: 3823 + snes - the `SNES` context 3824 - divtol - divergence tolerance 3825 3826 Level: intermediate 3827 3828 .seealso: `SNES`, `SNESSetDivergenceTolerance()` 3829 @*/ 3830 PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol) 3831 { 3832 PetscFunctionBegin; 3833 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3834 if (divtol) *divtol = snes->divtol; 3835 PetscFunctionReturn(0); 3836 } 3837 3838 /*@ 3839 SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance. 3840 3841 Logically Collective on snes 3842 3843 Input Parameters: 3844 + snes - the `SNES` context 3845 - tol - tolerance 3846 3847 Options Database Key: 3848 . -snes_trtol <tol> - Sets tol 3849 3850 Level: intermediate 3851 3852 .seealso: `SNES`, `SNESNEWTONTRDC`, `SNESSetTolerances()` 3853 @*/ 3854 PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol) 3855 { 3856 PetscFunctionBegin; 3857 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 3858 PetscValidLogicalCollectiveReal(snes, tol, 2); 3859 snes->deltatol = tol; 3860 PetscFunctionReturn(0); 3861 } 3862 3863 PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *); 3864 3865 PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx) 3866 { 3867 PetscDrawLG lg; 3868 PetscReal x, y, per; 3869 PetscViewer v = (PetscViewer)monctx; 3870 static PetscReal prev; /* should be in the context */ 3871 PetscDraw draw; 3872 3873 PetscFunctionBegin; 3874 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4); 3875 PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg)); 3876 if (!n) PetscCall(PetscDrawLGReset(lg)); 3877 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 3878 PetscCall(PetscDrawSetTitle(draw, "Residual norm")); 3879 x = (PetscReal)n; 3880 if (rnorm > 0.0) y = PetscLog10Real(rnorm); 3881 else y = -15.0; 3882 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 3883 if (n < 20 || !(n % 5) || snes->reason) { 3884 PetscCall(PetscDrawLGDraw(lg)); 3885 PetscCall(PetscDrawLGSave(lg)); 3886 } 3887 3888 PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg)); 3889 if (!n) PetscCall(PetscDrawLGReset(lg)); 3890 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 3891 PetscCall(PetscDrawSetTitle(draw, "% elemts > .2*max elemt")); 3892 PetscCall(SNESMonitorRange_Private(snes, n, &per)); 3893 x = (PetscReal)n; 3894 y = 100.0 * per; 3895 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 3896 if (n < 20 || !(n % 5) || snes->reason) { 3897 PetscCall(PetscDrawLGDraw(lg)); 3898 PetscCall(PetscDrawLGSave(lg)); 3899 } 3900 3901 PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg)); 3902 if (!n) { 3903 prev = rnorm; 3904 PetscCall(PetscDrawLGReset(lg)); 3905 } 3906 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 3907 PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm")); 3908 x = (PetscReal)n; 3909 y = (prev - rnorm) / prev; 3910 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 3911 if (n < 20 || !(n % 5) || snes->reason) { 3912 PetscCall(PetscDrawLGDraw(lg)); 3913 PetscCall(PetscDrawLGSave(lg)); 3914 } 3915 3916 PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg)); 3917 if (!n) PetscCall(PetscDrawLGReset(lg)); 3918 PetscCall(PetscDrawLGGetDraw(lg, &draw)); 3919 PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)")); 3920 x = (PetscReal)n; 3921 y = (prev - rnorm) / (prev * per); 3922 if (n > 2) { /*skip initial crazy value */ 3923 PetscCall(PetscDrawLGAddPoint(lg, &x, &y)); 3924 } 3925 if (n < 20 || !(n % 5) || snes->reason) { 3926 PetscCall(PetscDrawLGDraw(lg)); 3927 PetscCall(PetscDrawLGSave(lg)); 3928 } 3929 prev = rnorm; 3930 PetscFunctionReturn(0); 3931 } 3932 3933 /*@ 3934 SNESMonitor - runs the user provided monitor routines, if they exist 3935 3936 Collective on snes 3937 3938 Input Parameters: 3939 + snes - nonlinear solver context obtained from `SNESCreate()` 3940 . iter - iteration number 3941 - rnorm - relative norm of the residual 3942 3943 Note: 3944 This routine is called by the `SNES` implementations. 3945 It does not typically need to be called by the user. 3946 3947 Level: developer 3948 3949 .seealso: `SNES`, `SNESMonitorSet()` 3950 @*/ 3951 PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm) 3952 { 3953 PetscInt i, n = snes->numbermonitors; 3954 3955 PetscFunctionBegin; 3956 PetscCall(VecLockReadPush(snes->vec_sol)); 3957 for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i])); 3958 PetscCall(VecLockReadPop(snes->vec_sol)); 3959 PetscFunctionReturn(0); 3960 } 3961 3962 /* ------------ Routines to set performance monitoring options ----------- */ 3963 3964 /*MC 3965 SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver 3966 3967 Synopsis: 3968 #include <petscsnes.h> 3969 $ PetscErrorCode SNESMonitorFunction(SNES snes,PetscInt its, PetscReal norm,void *mctx) 3970 3971 Collective on snes 3972 3973 Input Parameters: 3974 + snes - the `SNES` context 3975 . its - iteration number 3976 . norm - 2-norm function value (may be estimated) 3977 - mctx - [optional] monitoring context 3978 3979 Level: advanced 3980 3981 .seealso: `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()` 3982 M*/ 3983 3984 /*@C 3985 SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 3986 iteration of the nonlinear solver to display the iteration's 3987 progress. 3988 3989 Logically Collective on snes 3990 3991 Input Parameters: 3992 + snes - the `SNES` context 3993 . f - the monitor function, see `SNESMonitorFunction` for the calling sequence 3994 . mctx - [optional] user-defined context for private data for the 3995 monitor routine (use NULL if no context is desired) 3996 - monitordestroy - [optional] routine that frees monitor context 3997 (may be NULL) 3998 3999 Options Database Keys: 4000 + -snes_monitor - sets `SNESMonitorDefault()` 4001 . -snes_monitor draw::draw_lg - sets line graph monitor, 4002 - -snes_monitor_cancel - cancels all monitors that have 4003 been hardwired into a code by 4004 calls to SNESMonitorSet(), but 4005 does not cancel those set via 4006 the options database. 4007 4008 Note: 4009 Several different monitoring routines may be set by calling 4010 `SNESMonitorSet()` multiple times; all will be called in the 4011 order in which they were set. 4012 4013 Fortran Note: 4014 Only a single monitor function can be set for each `SNES` object 4015 4016 Level: intermediate 4017 4018 .seealso: `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction` 4019 @*/ 4020 PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **)) 4021 { 4022 PetscInt i; 4023 PetscBool identical; 4024 4025 PetscFunctionBegin; 4026 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4027 for (i = 0; i < snes->numbermonitors; i++) { 4028 PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical)); 4029 if (identical) PetscFunctionReturn(0); 4030 } 4031 PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 4032 snes->monitor[snes->numbermonitors] = f; 4033 snes->monitordestroy[snes->numbermonitors] = monitordestroy; 4034 snes->monitorcontext[snes->numbermonitors++] = (void *)mctx; 4035 PetscFunctionReturn(0); 4036 } 4037 4038 /*@ 4039 SNESMonitorCancel - Clears all the monitor functions for a `SNES` object. 4040 4041 Logically Collective on snes 4042 4043 Input Parameters: 4044 . snes - the `SNES` context 4045 4046 Options Database Key: 4047 . -snes_monitor_cancel - cancels all monitors that have been hardwired 4048 into a code by calls to SNESMonitorSet(), but does not cancel those 4049 set via the options database 4050 4051 Note: 4052 There is no way to clear one specific monitor from a `SNES` object. 4053 4054 Level: intermediate 4055 4056 .seealso: `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()` 4057 @*/ 4058 PetscErrorCode SNESMonitorCancel(SNES snes) 4059 { 4060 PetscInt i; 4061 4062 PetscFunctionBegin; 4063 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4064 for (i = 0; i < snes->numbermonitors; i++) { 4065 if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i])); 4066 } 4067 snes->numbermonitors = 0; 4068 PetscFunctionReturn(0); 4069 } 4070 4071 /*MC 4072 SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4073 4074 Synopsis: 4075 #include <petscsnes.h> 4076 $ PetscErrorCode SNESConvergenceTest(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gnorm,PetscReal f,SNESConvergedReason *reason,void *cctx) 4077 4078 Collective on snes 4079 4080 Input Parameters: 4081 + snes - the `SNES` context 4082 . it - current iteration (0 is the first and is before any Newton step) 4083 . xnorm - 2-norm of current iterate 4084 . gnorm - 2-norm of current step 4085 . f - 2-norm of function 4086 - cctx - [optional] convergence context 4087 4088 Output Parameter: 4089 . reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected 4090 4091 Level: intermediate 4092 4093 .seealso: `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()` 4094 M*/ 4095 4096 /*@C 4097 SNESSetConvergenceTest - Sets the function that is to be used 4098 to test for convergence of the nonlinear iterative solution. 4099 4100 Logically Collective on snes 4101 4102 Input Parameters: 4103 + snes - the `SNES` context 4104 . `SNESConvergenceTestFunction` - routine to test for convergence 4105 . cctx - [optional] context for private data for the convergence routine (may be NULL) 4106 - destroy - [optional] destructor for the context (may be NULL; PETSC_NULL_FUNCTION in Fortran) 4107 4108 Level: advanced 4109 4110 .seealso: `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction` 4111 @*/ 4112 PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *)) 4113 { 4114 PetscFunctionBegin; 4115 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4116 if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 4117 if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP)); 4118 snes->ops->converged = SNESConvergenceTestFunction; 4119 snes->ops->convergeddestroy = destroy; 4120 snes->cnvP = cctx; 4121 PetscFunctionReturn(0); 4122 } 4123 4124 /*@ 4125 SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped. 4126 4127 Not Collective 4128 4129 Input Parameter: 4130 . snes - the `SNES` context 4131 4132 Output Parameter: 4133 . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists 4134 4135 Options Database Key: 4136 . -snes_converged_reason - prints the reason to standard out 4137 4138 Level: intermediate 4139 4140 Note: 4141 Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`. 4142 4143 .seealso: `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()` 4144 @*/ 4145 PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason) 4146 { 4147 PetscFunctionBegin; 4148 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4149 PetscValidPointer(reason, 2); 4150 *reason = snes->reason; 4151 PetscFunctionReturn(0); 4152 } 4153 4154 /*@C 4155 SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason` 4156 4157 Not Collective 4158 4159 Input Parameter: 4160 . snes - the `SNES` context 4161 4162 Output Parameter: 4163 . strreason - a human readable string that describes SNES converged reason 4164 4165 Level: beginner 4166 4167 .seealso: `SNES`, `SNESGetConvergedReason()` 4168 @*/ 4169 PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason) 4170 { 4171 PetscFunctionBegin; 4172 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4173 PetscValidPointer(strreason, 2); 4174 *strreason = SNESConvergedReasons[snes->reason]; 4175 PetscFunctionReturn(0); 4176 } 4177 4178 /*@ 4179 SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped. 4180 4181 Not Collective 4182 4183 Input Parameters: 4184 + snes - the `SNES` context 4185 - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the 4186 manual pages for the individual convergence tests for complete lists 4187 4188 Level: developer 4189 4190 Developer Note: 4191 Called inside the various `SNESSolve()` implementations 4192 4193 .seealso: `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason` 4194 @*/ 4195 PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason) 4196 { 4197 PetscFunctionBegin; 4198 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4199 snes->reason = reason; 4200 PetscFunctionReturn(0); 4201 } 4202 4203 /*@ 4204 SNESSetConvergenceHistory - Sets the array used to hold the convergence history. 4205 4206 Logically Collective on snes 4207 4208 Input Parameters: 4209 + snes - iterative context obtained from `SNESCreate()` 4210 . a - array to hold history, this array will contain the function norms computed at each step 4211 . its - integer array holds the number of linear iterations for each solve. 4212 . na - size of a and its 4213 - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero, 4214 else it continues storing new values for new nonlinear solves after the old ones 4215 4216 Notes: 4217 If 'a' and 'its' are NULL then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a 4218 default array of length 10000 is allocated. 4219 4220 This routine is useful, e.g., when running a code for purposes 4221 of accurate performance monitoring, when no I/O should be done 4222 during the section of code that is being timed. 4223 4224 Level: intermediate 4225 4226 .seealso: `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()` 4227 @*/ 4228 PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset) 4229 { 4230 PetscFunctionBegin; 4231 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4232 if (a) PetscValidRealPointer(a, 2); 4233 if (its) PetscValidIntPointer(its, 3); 4234 if (!a) { 4235 if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000; 4236 PetscCall(PetscCalloc2(na, &a, na, &its)); 4237 snes->conv_hist_alloc = PETSC_TRUE; 4238 } 4239 snes->conv_hist = a; 4240 snes->conv_hist_its = its; 4241 snes->conv_hist_max = (size_t)na; 4242 snes->conv_hist_len = 0; 4243 snes->conv_hist_reset = reset; 4244 PetscFunctionReturn(0); 4245 } 4246 4247 #if defined(PETSC_HAVE_MATLAB) 4248 #include <engine.h> /* MATLAB include file */ 4249 #include <mex.h> /* MATLAB include file */ 4250 4251 PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4252 { 4253 mxArray *mat; 4254 PetscInt i; 4255 PetscReal *ar; 4256 4257 mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL); 4258 ar = (PetscReal *)mxGetData(mat); 4259 for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 4260 return mat; 4261 } 4262 #endif 4263 4264 /*@C 4265 SNESGetConvergenceHistory - Gets the array used to hold the convergence history. 4266 4267 Not Collective 4268 4269 Input Parameter: 4270 . snes - iterative context obtained from `SNESCreate()` 4271 4272 Output Parameters: 4273 + a - array to hold history, usually was set with `SNESSetConvergenceHistory()` 4274 . its - integer array holds the number of linear iterations (or 4275 negative if not converged) for each solve. 4276 - na - size of a and its 4277 4278 Notes: 4279 The calling sequence for this routine in Fortran is 4280 $ call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr) 4281 4282 This routine is useful, e.g., when running a code for purposes 4283 of accurate performance monitoring, when no I/O should be done 4284 during the section of code that is being timed. 4285 4286 Level: intermediate 4287 4288 .seealso: `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()` 4289 @*/ 4290 PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na) 4291 { 4292 PetscFunctionBegin; 4293 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4294 if (a) *a = snes->conv_hist; 4295 if (its) *its = snes->conv_hist_its; 4296 if (na) *na = (PetscInt)snes->conv_hist_len; 4297 PetscFunctionReturn(0); 4298 } 4299 4300 /*@C 4301 SNESSetUpdate - Sets the general-purpose update function called 4302 at the beginning of every iteration of the nonlinear solve. Specifically 4303 it is called just before the Jacobian is "evaluated". 4304 4305 Logically Collective on snes 4306 4307 Input Parameters: 4308 + snes - The nonlinear solver context 4309 - func - The function 4310 4311 Calling sequence of func: 4312 $ func (SNES snes, PetscInt step); 4313 4314 . step - The current step of the iteration 4315 4316 Level: advanced 4317 4318 Note: 4319 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 4320 to `SNESSetFunction()`, or `SNESSetPicard()` 4321 This is not used by most users. 4322 4323 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. 4324 4325 .seealso: `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESSolve()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`, 4326 `SNESMonitorSet()`, `SNESSetDivergenceTest()` 4327 @*/ 4328 PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES, PetscInt)) 4329 { 4330 PetscFunctionBegin; 4331 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4332 snes->ops->update = func; 4333 PetscFunctionReturn(0); 4334 } 4335 4336 /* 4337 SNESScaleStep_Private - Scales a step so that its length is less than the 4338 positive parameter delta. 4339 4340 Input Parameters: 4341 + snes - the `SNES` context 4342 . y - approximate solution of linear system 4343 . fnorm - 2-norm of current function 4344 - delta - trust region size 4345 4346 Output Parameters: 4347 + gpnorm - predicted function norm at the new point, assuming local 4348 linearization. The value is zero if the step lies within the trust 4349 region, and exceeds zero otherwise. 4350 - ynorm - 2-norm of the step 4351 4352 Level: developer 4353 4354 Note: 4355 For non-trust region methods such as `SNESNEWTONLS`, the parameter delta 4356 is set to be the maximum allowable step size. 4357 */ 4358 PetscErrorCode SNESScaleStep_Private(SNES snes, Vec y, PetscReal *fnorm, PetscReal *delta, PetscReal *gpnorm, PetscReal *ynorm) 4359 { 4360 PetscReal nrm; 4361 PetscScalar cnorm; 4362 4363 PetscFunctionBegin; 4364 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4365 PetscValidHeaderSpecific(y, VEC_CLASSID, 2); 4366 PetscCheckSameComm(snes, 1, y, 2); 4367 4368 PetscCall(VecNorm(y, NORM_2, &nrm)); 4369 if (nrm > *delta) { 4370 nrm = *delta / nrm; 4371 *gpnorm = (1.0 - nrm) * (*fnorm); 4372 cnorm = nrm; 4373 PetscCall(VecScale(y, cnorm)); 4374 *ynorm = *delta; 4375 } else { 4376 *gpnorm = 0.0; 4377 *ynorm = nrm; 4378 } 4379 PetscFunctionReturn(0); 4380 } 4381 4382 /*@C 4383 SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer 4384 4385 Collective on snes 4386 4387 Parameter: 4388 + snes - iterative context obtained from `SNESCreate()` 4389 - viewer - the viewer to display the reason 4390 4391 Options Database Keys: 4392 + -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4393 - -snes_converged_reason ::failed - only print reason and number of iterations when diverged 4394 4395 Note: 4396 To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default, 4397 use `PETSC_VIEWER_FAILED` to only display a reason if it fails. 4398 4399 Level: beginner 4400 4401 .seealso: `SNESConvergedReason`, `PetscViewer`, `SNES`, 4402 `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, 4403 `SNESConvergedReasonViewFromOptions()`, 4404 `PetscViewerPushFormat()`, `PetscViewerPopFormat()` 4405 @*/ 4406 PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer) 4407 { 4408 PetscViewerFormat format; 4409 PetscBool isAscii; 4410 4411 PetscFunctionBegin; 4412 if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 4413 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii)); 4414 if (isAscii) { 4415 PetscCall(PetscViewerGetFormat(viewer, &format)); 4416 PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel)); 4417 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 4418 DM dm; 4419 Vec u; 4420 PetscDS prob; 4421 PetscInt Nf, f; 4422 PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 4423 void **exactCtx; 4424 PetscReal error; 4425 4426 PetscCall(SNESGetDM(snes, &dm)); 4427 PetscCall(SNESGetSolution(snes, &u)); 4428 PetscCall(DMGetDS(dm, &prob)); 4429 PetscCall(PetscDSGetNumFields(prob, &Nf)); 4430 PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx)); 4431 for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f])); 4432 PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error)); 4433 PetscCall(PetscFree2(exactSol, exactCtx)); 4434 if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n")); 4435 else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error)); 4436 } 4437 if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) { 4438 if (((PetscObject)snes)->prefix) { 4439 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 4440 } else { 4441 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 4442 } 4443 } else if (snes->reason <= 0) { 4444 if (((PetscObject)snes)->prefix) { 4445 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve did not converge due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter)); 4446 } else { 4447 PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter)); 4448 } 4449 } 4450 PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel)); 4451 } 4452 PetscFunctionReturn(0); 4453 } 4454 4455 /*@C 4456 SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the 4457 end of the nonlinear solver to display the conver reason of the nonlinear solver. 4458 4459 Logically Collective on snes 4460 4461 Input Parameters: 4462 + snes - the `SNES` context 4463 . f - the snes converged reason view function 4464 . vctx - [optional] user-defined context for private data for the 4465 snes converged reason view routine (use NULL if no context is desired) 4466 - reasonviewdestroy - [optional] routine that frees reasonview context 4467 (may be NULL) 4468 4469 Options Database Keys: 4470 + -snes_converged_reason - sets a default `SNESConvergedReasonView()` 4471 - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have 4472 been hardwired into a code by 4473 calls to `SNESConvergedReasonViewSet()`, but 4474 does not cancel those set via 4475 the options database. 4476 4477 Note: 4478 Several different converged reason view routines may be set by calling 4479 `SNESConvergedReasonViewSet()` multiple times; all will be called in the 4480 order in which they were set. 4481 4482 Level: intermediate 4483 4484 .seealso: `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()` 4485 @*/ 4486 PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES, void *), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **)) 4487 { 4488 PetscInt i; 4489 PetscBool identical; 4490 4491 PetscFunctionBegin; 4492 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4493 for (i = 0; i < snes->numberreasonviews; i++) { 4494 PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical)); 4495 if (identical) PetscFunctionReturn(0); 4496 } 4497 PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set"); 4498 snes->reasonview[snes->numberreasonviews] = f; 4499 snes->reasonviewdestroy[snes->numberreasonviews] = reasonviewdestroy; 4500 snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx; 4501 PetscFunctionReturn(0); 4502 } 4503 4504 /*@ 4505 SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed. 4506 All the user-provided convergedReasonView routines will be involved as well, if they exist. 4507 4508 Collective on snes 4509 4510 Input Parameters: 4511 . snes - the `SNES` object 4512 4513 Level: advanced 4514 4515 .seealso: `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, 4516 `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()` 4517 @*/ 4518 PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes) 4519 { 4520 PetscViewer viewer; 4521 PetscBool flg; 4522 static PetscBool incall = PETSC_FALSE; 4523 PetscViewerFormat format; 4524 PetscInt i; 4525 4526 PetscFunctionBegin; 4527 if (incall) PetscFunctionReturn(0); 4528 incall = PETSC_TRUE; 4529 4530 /* All user-provided viewers are called first, if they exist. */ 4531 for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i])); 4532 4533 /* Call PETSc default routine if users ask for it */ 4534 PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg)); 4535 if (flg) { 4536 PetscCall(PetscViewerPushFormat(viewer, format)); 4537 PetscCall(SNESConvergedReasonView(snes, viewer)); 4538 PetscCall(PetscViewerPopFormat(viewer)); 4539 PetscCall(PetscViewerDestroy(&viewer)); 4540 } 4541 incall = PETSC_FALSE; 4542 PetscFunctionReturn(0); 4543 } 4544 4545 /*@ 4546 SNESSolve - Solves a nonlinear system F(x) = b. 4547 Call `SNESSolve()` after calling `SNESCreate()` and optional routines of the form `SNESSetXXX()`. 4548 4549 Collective on snes 4550 4551 Input Parameters: 4552 + snes - the `SNES` context 4553 . b - the constant part of the equation F(x) = b, or NULL to use zero. 4554 - x - the solution vector. 4555 4556 Note: 4557 The user should initialize the vector,x, with the initial guess 4558 for the nonlinear solve prior to calling `SNESSolve()`. In particular, 4559 to employ an initial guess of zero, the user should explicitly set 4560 this vector to zero by calling `VecSet()`. 4561 4562 Level: beginner 4563 4564 .seealso: `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`, 4565 `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`, 4566 `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()` 4567 @*/ 4568 PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x) 4569 { 4570 PetscBool flg; 4571 PetscInt grid; 4572 Vec xcreated = NULL; 4573 DM dm; 4574 4575 PetscFunctionBegin; 4576 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4577 if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4578 if (x) PetscCheckSameComm(snes, 1, x, 3); 4579 if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4580 if (b) PetscCheckSameComm(snes, 1, b, 2); 4581 4582 /* High level operations using the nonlinear solver */ 4583 { 4584 PetscViewer viewer; 4585 PetscViewerFormat format; 4586 PetscInt num; 4587 PetscBool flg; 4588 static PetscBool incall = PETSC_FALSE; 4589 4590 if (!incall) { 4591 /* Estimate the convergence rate of the discretization */ 4592 PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg)); 4593 if (flg) { 4594 PetscConvEst conv; 4595 DM dm; 4596 PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 4597 PetscInt Nf; 4598 4599 incall = PETSC_TRUE; 4600 PetscCall(SNESGetDM(snes, &dm)); 4601 PetscCall(DMGetNumFields(dm, &Nf)); 4602 PetscCall(PetscCalloc1(Nf, &alpha)); 4603 PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv)); 4604 PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes)); 4605 PetscCall(PetscConvEstSetFromOptions(conv)); 4606 PetscCall(PetscConvEstSetUp(conv)); 4607 PetscCall(PetscConvEstGetConvRate(conv, alpha)); 4608 PetscCall(PetscViewerPushFormat(viewer, format)); 4609 PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 4610 PetscCall(PetscViewerPopFormat(viewer)); 4611 PetscCall(PetscViewerDestroy(&viewer)); 4612 PetscCall(PetscConvEstDestroy(&conv)); 4613 PetscCall(PetscFree(alpha)); 4614 incall = PETSC_FALSE; 4615 } 4616 /* Adaptively refine the initial grid */ 4617 num = 1; 4618 PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg)); 4619 if (flg) { 4620 DMAdaptor adaptor; 4621 4622 incall = PETSC_TRUE; 4623 PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4624 PetscCall(DMAdaptorSetSolver(adaptor, snes)); 4625 PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 4626 PetscCall(DMAdaptorSetFromOptions(adaptor)); 4627 PetscCall(DMAdaptorSetUp(adaptor)); 4628 PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x)); 4629 PetscCall(DMAdaptorDestroy(&adaptor)); 4630 incall = PETSC_FALSE; 4631 } 4632 /* Use grid sequencing to adapt */ 4633 num = 0; 4634 PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL)); 4635 if (num) { 4636 DMAdaptor adaptor; 4637 4638 incall = PETSC_TRUE; 4639 PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor)); 4640 PetscCall(DMAdaptorSetSolver(adaptor, snes)); 4641 PetscCall(DMAdaptorSetSequenceLength(adaptor, num)); 4642 PetscCall(DMAdaptorSetFromOptions(adaptor)); 4643 PetscCall(DMAdaptorSetUp(adaptor)); 4644 PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x)); 4645 PetscCall(DMAdaptorDestroy(&adaptor)); 4646 incall = PETSC_FALSE; 4647 } 4648 } 4649 } 4650 if (!x) x = snes->vec_sol; 4651 if (!x) { 4652 PetscCall(SNESGetDM(snes, &dm)); 4653 PetscCall(DMCreateGlobalVector(dm, &xcreated)); 4654 x = xcreated; 4655 } 4656 PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre")); 4657 4658 for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4659 for (grid = 0; grid < snes->gridsequence + 1; grid++) { 4660 /* set solution vector */ 4661 if (!grid) PetscCall(PetscObjectReference((PetscObject)x)); 4662 PetscCall(VecDestroy(&snes->vec_sol)); 4663 snes->vec_sol = x; 4664 PetscCall(SNESGetDM(snes, &dm)); 4665 4666 /* set affine vector if provided */ 4667 if (b) PetscCall(PetscObjectReference((PetscObject)b)); 4668 PetscCall(VecDestroy(&snes->vec_rhs)); 4669 snes->vec_rhs = b; 4670 4671 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"); 4672 PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector"); 4673 PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right hand side vector"); 4674 if (!snes->vec_sol_update /* && snes->vec_sol */) { PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); } 4675 PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol)); 4676 PetscCall(SNESSetUp(snes)); 4677 4678 if (!grid) { 4679 if (snes->ops->computeinitialguess) PetscCallBack("SNES callback initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP)); 4680 } 4681 4682 if (snes->conv_hist_reset) snes->conv_hist_len = 0; 4683 if (snes->counters_reset) { 4684 snes->nfuncs = 0; 4685 snes->linear_its = 0; 4686 snes->numFailures = 0; 4687 } 4688 4689 PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0)); 4690 PetscUseTypeMethod(snes, solve); 4691 PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0)); 4692 PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver returned without setting converged reason"); 4693 snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 4694 4695 if (snes->lagjac_persist) snes->jac_iter += snes->iter; 4696 if (snes->lagpre_persist) snes->pre_iter += snes->iter; 4697 4698 PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg)); 4699 if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes)); 4700 /* Call converged reason views. This may involve user-provided viewers as well */ 4701 PetscCall(SNESConvergedReasonViewFromOptions(snes)); 4702 4703 if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged"); 4704 if (snes->reason < 0) break; 4705 if (grid < snes->gridsequence) { 4706 DM fine; 4707 Vec xnew; 4708 Mat interp; 4709 4710 PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine)); 4711 PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing"); 4712 PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL)); 4713 PetscCall(DMCreateGlobalVector(fine, &xnew)); 4714 PetscCall(MatInterpolate(interp, x, xnew)); 4715 PetscCall(DMInterpolate(snes->dm, interp, fine)); 4716 PetscCall(MatDestroy(&interp)); 4717 x = xnew; 4718 4719 PetscCall(SNESReset(snes)); 4720 PetscCall(SNESSetDM(snes, fine)); 4721 PetscCall(SNESResetFromOptions(snes)); 4722 PetscCall(DMDestroy(&fine)); 4723 PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)))); 4724 } 4725 } 4726 PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view")); 4727 PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution")); 4728 PetscCall(DMMonitor(snes->dm)); 4729 PetscCall(SNESMonitorPauseFinal_Internal(snes)); 4730 4731 PetscCall(VecDestroy(&xcreated)); 4732 PetscCall(PetscObjectSAWsBlock((PetscObject)snes)); 4733 PetscFunctionReturn(0); 4734 } 4735 4736 /* --------- Internal routines for SNES Package --------- */ 4737 4738 /*@C 4739 SNESSetType - Sets the method for the nonlinear solver. 4740 4741 Collective on snes 4742 4743 Input Parameters: 4744 + snes - the `SNES` context 4745 - type - a known method 4746 4747 Options Database Key: 4748 . -snes_type <type> - Sets the method; use -help for a list 4749 of available methods (for instance, newtonls or newtontr) 4750 4751 Notes: 4752 See "petsc/include/petscsnes.h" for available methods (for instance) 4753 + `SNESNEWTONLS` - Newton's method with line search 4754 (systems of nonlinear equations) 4755 - `SNESNEWTONTRDC` - Newton's method with trust region 4756 (systems of nonlinear equations) 4757 4758 Normally, it is best to use the `SNESSetFromOptions()` command and then 4759 set the `SNES` solver type from the options database rather than by using 4760 this routine. Using the options database provides the user with 4761 maximum flexibility in evaluating the many nonlinear solvers. 4762 The `SNESSetType()` routine is provided for those situations where it 4763 is necessary to set the nonlinear solver independently of the command 4764 line or options database. This might be the case, for example, when 4765 the choice of solver changes during the execution of the program, 4766 and the user's application is taking responsibility for choosing the 4767 appropriate method. 4768 4769 Developer Note: 4770 `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates 4771 the constructor in that list and calls it to create the specific object. 4772 4773 Level: intermediate 4774 4775 .seealso: `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()` 4776 @*/ 4777 PetscErrorCode SNESSetType(SNES snes, SNESType type) 4778 { 4779 PetscBool match; 4780 PetscErrorCode (*r)(SNES); 4781 4782 PetscFunctionBegin; 4783 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4784 PetscValidCharPointer(type, 2); 4785 4786 PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match)); 4787 if (match) PetscFunctionReturn(0); 4788 4789 PetscCall(PetscFunctionListFind(SNESList, type, &r)); 4790 PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type); 4791 /* Destroy the previous private SNES context */ 4792 PetscTryTypeMethod(snes, destroy); 4793 /* Reinitialize function pointers in SNESOps structure */ 4794 snes->ops->setup = NULL; 4795 snes->ops->solve = NULL; 4796 snes->ops->view = NULL; 4797 snes->ops->setfromoptions = NULL; 4798 snes->ops->destroy = NULL; 4799 4800 /* It may happen the user has customized the line search before calling SNESSetType */ 4801 if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 4802 4803 /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 4804 snes->setupcalled = PETSC_FALSE; 4805 4806 PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type)); 4807 PetscCall((*r)(snes)); 4808 PetscFunctionReturn(0); 4809 } 4810 4811 /*@C 4812 SNESGetType - Gets the `SNES` method type and name (as a string). 4813 4814 Not Collective 4815 4816 Input Parameter: 4817 . snes - nonlinear solver context 4818 4819 Output Parameter: 4820 . type - `SNES` method (a character string) 4821 4822 Level: intermediate 4823 4824 .seealso: `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES` 4825 @*/ 4826 PetscErrorCode SNESGetType(SNES snes, SNESType *type) 4827 { 4828 PetscFunctionBegin; 4829 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4830 PetscValidPointer(type, 2); 4831 *type = ((PetscObject)snes)->type_name; 4832 PetscFunctionReturn(0); 4833 } 4834 4835 /*@ 4836 SNESSetSolution - Sets the solution vector for use by the `SNES` routines. 4837 4838 Logically Collective on snes 4839 4840 Input Parameters: 4841 + snes - the `SNES` context obtained from `SNESCreate()` 4842 - u - the solution vector 4843 4844 Level: beginner 4845 4846 .seealso: `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec` 4847 @*/ 4848 PetscErrorCode SNESSetSolution(SNES snes, Vec u) 4849 { 4850 DM dm; 4851 4852 PetscFunctionBegin; 4853 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4854 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 4855 PetscCall(PetscObjectReference((PetscObject)u)); 4856 PetscCall(VecDestroy(&snes->vec_sol)); 4857 4858 snes->vec_sol = u; 4859 4860 PetscCall(SNESGetDM(snes, &dm)); 4861 PetscCall(DMShellSetGlobalVector(dm, u)); 4862 PetscFunctionReturn(0); 4863 } 4864 4865 /*@ 4866 SNESGetSolution - Returns the vector where the approximate solution is 4867 stored. This is the fine grid solution when using `SNESSetGridSequence()`. 4868 4869 Not Collective, but x is parallel if snes is parallel 4870 4871 Input Parameter: 4872 . snes - the `SNES` context 4873 4874 Output Parameter: 4875 . x - the solution 4876 4877 Level: intermediate 4878 4879 .seealso: `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()` 4880 @*/ 4881 PetscErrorCode SNESGetSolution(SNES snes, Vec *x) 4882 { 4883 PetscFunctionBegin; 4884 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4885 PetscValidPointer(x, 2); 4886 *x = snes->vec_sol; 4887 PetscFunctionReturn(0); 4888 } 4889 4890 /*@ 4891 SNESGetSolutionUpdate - Returns the vector where the solution update is 4892 stored. 4893 4894 Not Collective, but x is parallel if snes is parallel 4895 4896 Input Parameter: 4897 . snes - the `SNES` context 4898 4899 Output Parameter: 4900 . x - the solution update 4901 4902 Level: advanced 4903 4904 .seealso: `SNES`, `SNESGetSolution()`, `SNESGetFunction()` 4905 @*/ 4906 PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x) 4907 { 4908 PetscFunctionBegin; 4909 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4910 PetscValidPointer(x, 2); 4911 *x = snes->vec_sol_update; 4912 PetscFunctionReturn(0); 4913 } 4914 4915 /*@C 4916 SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()` 4917 4918 Not Collective, but r is parallel if snes is parallel. Collective if r is requested, but has not been created yet. 4919 4920 Input Parameter: 4921 . snes - the `SNES` context 4922 4923 Output Parameters: 4924 + r - the vector that is used to store residuals (or NULL if you don't want it) 4925 . f - the function (or NULL if you don't want it); see `SNESFunction` for calling sequence details 4926 - ctx - the function context (or NULL if you don't want it) 4927 4928 Level: advanced 4929 4930 Note: 4931 The vector r DOES NOT, in general, contain the current value of the `SNES` nonlinear function 4932 4933 .seealso: `SNES, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunction` 4934 @*/ 4935 PetscErrorCode SNESGetFunction(SNES snes, Vec *r, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx) 4936 { 4937 DM dm; 4938 4939 PetscFunctionBegin; 4940 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4941 if (r) { 4942 if (!snes->vec_func) { 4943 if (snes->vec_rhs) { 4944 PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func)); 4945 } else if (snes->vec_sol) { 4946 PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func)); 4947 } else if (snes->dm) { 4948 PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func)); 4949 } 4950 } 4951 *r = snes->vec_func; 4952 } 4953 PetscCall(SNESGetDM(snes, &dm)); 4954 PetscCall(DMSNESGetFunction(dm, f, ctx)); 4955 PetscFunctionReturn(0); 4956 } 4957 4958 /*@C 4959 SNESGetNGS - Returns the `SNESNGS` function and context set with `SNESSetNGS()` 4960 4961 Input Parameter: 4962 . snes - the `SNES` context 4963 4964 Output Parameters: 4965 + f - the function (or NULL) see `SNESNGSFunction` for details 4966 - ctx - the function context (or NULL) 4967 4968 Level: advanced 4969 4970 .seealso: `SNESSetNGS()`, `SNESGetFunction()` 4971 @*/ 4972 4973 PetscErrorCode SNESGetNGS(SNES snes, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx) 4974 { 4975 DM dm; 4976 4977 PetscFunctionBegin; 4978 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4979 PetscCall(SNESGetDM(snes, &dm)); 4980 PetscCall(DMSNESGetNGS(dm, f, ctx)); 4981 PetscFunctionReturn(0); 4982 } 4983 4984 /*@C 4985 SNESSetOptionsPrefix - Sets the prefix used for searching for all 4986 `SNES` options in the database. 4987 4988 Logically Collective on snes 4989 4990 Input Parameters: 4991 + snes - the `SNES` context 4992 - prefix - the prefix to prepend to all option names 4993 4994 Note: 4995 A hyphen (-) must NOT be given at the beginning of the prefix name. 4996 The first character of all runtime options is AUTOMATICALLY the hyphen. 4997 4998 Level: advanced 4999 5000 .seealso: `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()` 5001 @*/ 5002 PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[]) 5003 { 5004 PetscFunctionBegin; 5005 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5006 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix)); 5007 if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 5008 if (snes->linesearch) { 5009 PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 5010 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix)); 5011 } 5012 PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix)); 5013 PetscFunctionReturn(0); 5014 } 5015 5016 /*@C 5017 SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 5018 `SNES` options in the database. 5019 5020 Logically Collective on snes 5021 5022 Input Parameters: 5023 + snes - the `SNES` context 5024 - prefix - the prefix to prepend to all option names 5025 5026 Note: 5027 A hyphen (-) must NOT be given at the beginning of the prefix name. 5028 The first character of all runtime options is AUTOMATICALLY the hyphen. 5029 5030 Level: advanced 5031 5032 .seealso: `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()` 5033 @*/ 5034 PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[]) 5035 { 5036 PetscFunctionBegin; 5037 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5038 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix)); 5039 if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp)); 5040 if (snes->linesearch) { 5041 PetscCall(SNESGetLineSearch(snes, &snes->linesearch)); 5042 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix)); 5043 } 5044 PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix)); 5045 PetscFunctionReturn(0); 5046 } 5047 5048 /*@C 5049 SNESGetOptionsPrefix - Gets the prefix used for searching for all 5050 `SNES` options in the database. 5051 5052 Not Collective 5053 5054 Input Parameter: 5055 . snes - the `SNES` context 5056 5057 Output Parameter: 5058 . prefix - pointer to the prefix string used 5059 5060 Fortran Note: 5061 On the fortran side, the user should pass in a string 'prefix' of 5062 sufficient length to hold the prefix. 5063 5064 Level: advanced 5065 5066 .seealso: `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()` 5067 @*/ 5068 PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[]) 5069 { 5070 PetscFunctionBegin; 5071 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5072 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix)); 5073 PetscFunctionReturn(0); 5074 } 5075 5076 /*@C 5077 SNESRegister - Adds a method to the nonlinear solver package. 5078 5079 Not collective 5080 5081 Input Parameters: 5082 + name_solver - name of a new user-defined solver 5083 - routine_create - routine to create method context 5084 5085 Note: 5086 `SNESRegister()` may be called multiple times to add several user-defined solvers. 5087 5088 Sample usage: 5089 .vb 5090 SNESRegister("my_solver",MySolverCreate); 5091 .ve 5092 5093 Then, your solver can be chosen with the procedural interface via 5094 $ SNESSetType(snes,"my_solver") 5095 or at runtime via the option 5096 $ -snes_type my_solver 5097 5098 Level: advanced 5099 5100 .seealso: `SNESRegisterAll()`, `SNESRegisterDestroy()` 5101 @*/ 5102 PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES)) 5103 { 5104 PetscFunctionBegin; 5105 PetscCall(SNESInitializePackage()); 5106 PetscCall(PetscFunctionListAdd(&SNESList, sname, function)); 5107 PetscFunctionReturn(0); 5108 } 5109 5110 PetscErrorCode SNESTestLocalMin(SNES snes) 5111 { 5112 PetscInt N, i, j; 5113 Vec u, uh, fh; 5114 PetscScalar value; 5115 PetscReal norm; 5116 5117 PetscFunctionBegin; 5118 PetscCall(SNESGetSolution(snes, &u)); 5119 PetscCall(VecDuplicate(u, &uh)); 5120 PetscCall(VecDuplicate(u, &fh)); 5121 5122 /* currently only works for sequential */ 5123 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n")); 5124 PetscCall(VecGetSize(u, &N)); 5125 for (i = 0; i < N; i++) { 5126 PetscCall(VecCopy(u, uh)); 5127 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i)); 5128 for (j = -10; j < 11; j++) { 5129 value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0); 5130 PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5131 PetscCall(SNESComputeFunction(snes, uh, fh)); 5132 PetscCall(VecNorm(fh, NORM_2, &norm)); 5133 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), " j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm)); 5134 value = -value; 5135 PetscCall(VecSetValue(uh, i, value, ADD_VALUES)); 5136 } 5137 } 5138 PetscCall(VecDestroy(&uh)); 5139 PetscCall(VecDestroy(&fh)); 5140 PetscFunctionReturn(0); 5141 } 5142 5143 /*@ 5144 SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for 5145 computing relative tolerance for linear solvers within an inexact 5146 Newton method. 5147 5148 Logically Collective on snes 5149 5150 Input Parameters: 5151 + snes - `SNES` context 5152 - flag - `PETSC_TRUE` or `PETSC_FALSE` 5153 5154 Options Database Keys: 5155 + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 5156 . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 5157 . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 5158 . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 5159 . -snes_ksp_ew_gamma <gamma> - Sets gamma 5160 . -snes_ksp_ew_alpha <alpha> - Sets alpha 5161 . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 5162 - -snes_ksp_ew_threshold <threshold> - Sets threshold 5163 5164 Note: 5165 The default is to use a constant relative tolerance for 5166 the inner linear solvers. Alternatively, one can use the 5167 Eisenstat-Walker method, where the relative convergence tolerance 5168 is reset at each Newton iteration according progress of the nonlinear 5169 solver. 5170 5171 Level: advanced 5172 5173 Reference: 5174 . - * S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an inexact Newton method", SISC 17 (1), pp.16-32, 1996. 5175 5176 .seealso: `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 5177 @*/ 5178 PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag) 5179 { 5180 PetscFunctionBegin; 5181 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5182 PetscValidLogicalCollectiveBool(snes, flag, 2); 5183 snes->ksp_ewconv = flag; 5184 PetscFunctionReturn(0); 5185 } 5186 5187 /*@ 5188 SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method 5189 for computing relative tolerance for linear solvers within an 5190 inexact Newton method. 5191 5192 Not Collective 5193 5194 Input Parameter: 5195 . snes - `SNES` context 5196 5197 Output Parameter: 5198 . flag - `PETSC_TRUE` or `PETSC_FALSE` 5199 5200 Level: advanced 5201 5202 .seealso: `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()` 5203 @*/ 5204 PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5205 { 5206 PetscFunctionBegin; 5207 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5208 PetscValidBoolPointer(flag, 2); 5209 *flag = snes->ksp_ewconv; 5210 PetscFunctionReturn(0); 5211 } 5212 5213 /*@ 5214 SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 5215 convergence criteria for the linear solvers within an inexact 5216 Newton method. 5217 5218 Logically Collective on snes 5219 5220 Input Parameters: 5221 + snes - `SNES` context 5222 . version - version 1, 2 (default is 2), 3 or 4 5223 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 5224 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5225 . gamma - multiplicative factor for version 2 rtol computation 5226 (0 <= gamma2 <= 1) 5227 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 5228 . alpha2 - power for safeguard 5229 - threshold - threshold for imposing safeguard (0 < threshold < 1) 5230 5231 Notes: 5232 Version 3 was contributed by Luis Chacon, June 2006. 5233 5234 Use `PETSC_DEFAULT` to retain the default for any of the parameters. 5235 5236 Level: advanced 5237 5238 .seealso: `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()` 5239 @*/ 5240 PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold) 5241 { 5242 SNESKSPEW *kctx; 5243 5244 PetscFunctionBegin; 5245 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5246 kctx = (SNESKSPEW *)snes->kspconvctx; 5247 PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5248 PetscValidLogicalCollectiveInt(snes, version, 2); 5249 PetscValidLogicalCollectiveReal(snes, rtol_0, 3); 5250 PetscValidLogicalCollectiveReal(snes, rtol_max, 4); 5251 PetscValidLogicalCollectiveReal(snes, gamma, 5); 5252 PetscValidLogicalCollectiveReal(snes, alpha, 6); 5253 PetscValidLogicalCollectiveReal(snes, alpha2, 7); 5254 PetscValidLogicalCollectiveReal(snes, threshold, 8); 5255 5256 if (version != PETSC_DEFAULT) kctx->version = version; 5257 if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0; 5258 if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max; 5259 if (gamma != PETSC_DEFAULT) kctx->gamma = gamma; 5260 if (alpha != PETSC_DEFAULT) kctx->alpha = alpha; 5261 if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2; 5262 if (threshold != PETSC_DEFAULT) kctx->threshold = threshold; 5263 5264 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); 5265 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); 5266 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); 5267 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); 5268 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); 5269 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); 5270 PetscFunctionReturn(0); 5271 } 5272 5273 /*@ 5274 SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 5275 convergence criteria for the linear solvers within an inexact 5276 Newton method. 5277 5278 Not Collective 5279 5280 Input Parameter: 5281 . snes - `SNES` context 5282 5283 Output Parameters: 5284 + version - version 1, 2 (default is 2), 3 or 4 5285 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 5286 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5287 . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 5288 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 5289 . alpha2 - power for safeguard 5290 - threshold - threshold for imposing safeguard (0 < threshold < 1) 5291 5292 Level: advanced 5293 5294 .seealso: `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()` 5295 @*/ 5296 PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold) 5297 { 5298 SNESKSPEW *kctx; 5299 5300 PetscFunctionBegin; 5301 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5302 kctx = (SNESKSPEW *)snes->kspconvctx; 5303 PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing"); 5304 if (version) *version = kctx->version; 5305 if (rtol_0) *rtol_0 = kctx->rtol_0; 5306 if (rtol_max) *rtol_max = kctx->rtol_max; 5307 if (gamma) *gamma = kctx->gamma; 5308 if (alpha) *alpha = kctx->alpha; 5309 if (alpha2) *alpha2 = kctx->alpha2; 5310 if (threshold) *threshold = kctx->threshold; 5311 PetscFunctionReturn(0); 5312 } 5313 5314 PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes) 5315 { 5316 SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 5317 PetscReal rtol = PETSC_DEFAULT, stol; 5318 5319 PetscFunctionBegin; 5320 if (!snes->ksp_ewconv) PetscFunctionReturn(0); 5321 if (!snes->iter) { 5322 rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 5323 PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first)); 5324 } else { 5325 PetscCheck(kctx->version >= 1 && kctx->version <= 4, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only versions 1-4 are supported: %" PetscInt_FMT, kctx->version); 5326 if (kctx->version == 1) { 5327 rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last; 5328 stol = PetscPowReal(kctx->rtol_last, kctx->alpha2); 5329 if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 5330 } else if (kctx->version == 2) { 5331 rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 5332 stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 5333 if (stol > kctx->threshold) rtol = PetscMax(rtol, stol); 5334 } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 5335 rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha); 5336 /* safeguard: avoid sharp decrease of rtol */ 5337 stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha); 5338 stol = PetscMax(rtol, stol); 5339 rtol = PetscMin(kctx->rtol_0, stol); 5340 /* safeguard: avoid oversolving */ 5341 stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm; 5342 stol = PetscMax(rtol, stol); 5343 rtol = PetscMin(kctx->rtol_0, stol); 5344 } else /* if (kctx->version == 4) */ { 5345 /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */ 5346 PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm); 5347 PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last); 5348 PetscReal rk = ared / pred; 5349 if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1; 5350 else if (rk < kctx->v4_p2) rtol = kctx->rtol_last; 5351 else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last; 5352 else rtol = kctx->v4_m2 * kctx->rtol_last; 5353 5354 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) { 5355 rtol = kctx->v4_m4 * kctx->rtol_last; 5356 //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); 5357 } else { 5358 //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); 5359 } 5360 kctx->rtol_last_2 = kctx->rtol_last; 5361 kctx->rk_last_2 = kctx->rk_last; 5362 kctx->rk_last = rk; 5363 } 5364 } 5365 /* safeguard: avoid rtol greater than rtol_max */ 5366 rtol = PetscMin(rtol, kctx->rtol_max); 5367 PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT)); 5368 PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol)); 5369 PetscFunctionReturn(0); 5370 } 5371 5372 PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes) 5373 { 5374 SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx; 5375 PCSide pcside; 5376 Vec lres; 5377 5378 PetscFunctionBegin; 5379 if (!snes->ksp_ewconv) PetscFunctionReturn(0); 5380 PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL)); 5381 kctx->norm_last = snes->norm; 5382 if (kctx->version == 1 || kctx->version == 4) { 5383 PC pc; 5384 PetscBool getRes; 5385 5386 PetscCall(KSPGetPC(ksp, &pc)); 5387 PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes)); 5388 if (!getRes) { 5389 KSPNormType normtype; 5390 5391 PetscCall(KSPGetNormType(ksp, &normtype)); 5392 getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED); 5393 } 5394 PetscCall(KSPGetPCSide(ksp, &pcside)); 5395 if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */ 5396 PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last)); 5397 } else { 5398 /* KSP residual is preconditioned residual */ 5399 /* compute true linear residual norm */ 5400 Mat J; 5401 PetscCall(KSPGetOperators(ksp, &J, NULL)); 5402 PetscCall(VecDuplicate(b, &lres)); 5403 PetscCall(MatMult(J, x, lres)); 5404 PetscCall(VecAYPX(lres, -1.0, b)); 5405 PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last)); 5406 PetscCall(VecDestroy(&lres)); 5407 } 5408 } 5409 PetscFunctionReturn(0); 5410 } 5411 5412 /*@ 5413 SNESGetKSP - Returns the `KSP` context for a `SNES` solver. 5414 5415 Not Collective, but if snes is parallel, then ksp is parallel 5416 5417 Input Parameter: 5418 . snes - the `SNES` context 5419 5420 Output Parameter: 5421 . ksp - the `KSP` context 5422 5423 Notes: 5424 The user can then directly manipulate the `KSP` context to set various 5425 options, etc. Likewise, the user can then extract and manipulate the 5426 `PC` contexts as well. 5427 5428 Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function 5429 5430 Level: beginner 5431 5432 .seealso: `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()` 5433 @*/ 5434 PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp) 5435 { 5436 PetscFunctionBegin; 5437 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5438 PetscValidPointer(ksp, 2); 5439 5440 if (!snes->ksp) { 5441 PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp)); 5442 PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1)); 5443 5444 PetscCall(KSPSetPreSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPreSolve_SNESEW, snes)); 5445 PetscCall(KSPSetPostSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPostSolve_SNESEW, snes)); 5446 5447 PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes)); 5448 PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options)); 5449 } 5450 *ksp = snes->ksp; 5451 PetscFunctionReturn(0); 5452 } 5453 5454 #include <petsc/private/dmimpl.h> 5455 /*@ 5456 SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners 5457 5458 Logically Collective on snes 5459 5460 Input Parameters: 5461 + snes - the nonlinear solver context 5462 - dm - the dm, cannot be NULL 5463 5464 Note: 5465 A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 5466 even when not using interfaces like `DMSNESSetFunction()`. Use `DMClone()` to get a distinct `DM` when solving different 5467 problems using the same function space. 5468 5469 Level: intermediate 5470 5471 .seealso: `DM`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()` 5472 @*/ 5473 PetscErrorCode SNESSetDM(SNES snes, DM dm) 5474 { 5475 KSP ksp; 5476 DMSNES sdm; 5477 5478 PetscFunctionBegin; 5479 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5480 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 5481 PetscCall(PetscObjectReference((PetscObject)dm)); 5482 if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 5483 if (snes->dm->dmsnes && !dm->dmsnes) { 5484 PetscCall(DMCopyDMSNES(snes->dm, dm)); 5485 PetscCall(DMGetDMSNES(snes->dm, &sdm)); 5486 if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 5487 } 5488 PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes)); 5489 PetscCall(DMDestroy(&snes->dm)); 5490 } 5491 snes->dm = dm; 5492 snes->dmAuto = PETSC_FALSE; 5493 5494 PetscCall(SNESGetKSP(snes, &ksp)); 5495 PetscCall(KSPSetDM(ksp, dm)); 5496 PetscCall(KSPSetDMActive(ksp, PETSC_FALSE)); 5497 if (snes->npc) { 5498 PetscCall(SNESSetDM(snes->npc, snes->dm)); 5499 PetscCall(SNESSetNPCSide(snes, snes->npcside)); 5500 } 5501 PetscFunctionReturn(0); 5502 } 5503 5504 /*@ 5505 SNESGetDM - Gets the `DM` that may be used by some preconditioners 5506 5507 Not Collective but dm obtained is parallel on snes 5508 5509 Input Parameter: 5510 . snes - the preconditioner context 5511 5512 Output Parameter: 5513 . dm - the dm 5514 5515 Level: intermediate 5516 5517 .seealso: `DM`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()` 5518 @*/ 5519 PetscErrorCode SNESGetDM(SNES snes, DM *dm) 5520 { 5521 PetscFunctionBegin; 5522 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5523 if (!snes->dm) { 5524 PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm)); 5525 snes->dmAuto = PETSC_TRUE; 5526 } 5527 *dm = snes->dm; 5528 PetscFunctionReturn(0); 5529 } 5530 5531 /*@ 5532 SNESSetNPC - Sets the nonlinear preconditioner to be used. 5533 5534 Collective on snes 5535 5536 Input Parameters: 5537 + snes - iterative context obtained from `SNESCreate()` 5538 - npc - the preconditioner object 5539 5540 Notes: 5541 Use `SNESGetNPC()` to retrieve the preconditioner context (for example, 5542 to configure it using the API). 5543 5544 Only some `SNESType` can use a nonlinear preconditioner 5545 5546 Level: developer 5547 5548 .seealso: `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()` 5549 @*/ 5550 PetscErrorCode SNESSetNPC(SNES snes, SNES npc) 5551 { 5552 PetscFunctionBegin; 5553 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5554 PetscValidHeaderSpecific(npc, SNES_CLASSID, 2); 5555 PetscCheckSameComm(snes, 1, npc, 2); 5556 PetscCall(PetscObjectReference((PetscObject)npc)); 5557 PetscCall(SNESDestroy(&snes->npc)); 5558 snes->npc = npc; 5559 PetscFunctionReturn(0); 5560 } 5561 5562 /*@ 5563 SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver. 5564 5565 Not Collective; but any changes to the obtained the npc object must be applied collectively 5566 5567 Input Parameter: 5568 . snes - iterative context obtained from `SNESCreate()` 5569 5570 Output Parameter: 5571 . npc - preconditioner context 5572 5573 Options Database Key: 5574 . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner 5575 5576 Notes: 5577 If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created. 5578 5579 The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original 5580 `SNES` 5581 5582 Level: developer 5583 5584 .seealso: `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()` 5585 @*/ 5586 PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5587 { 5588 const char *optionsprefix; 5589 5590 PetscFunctionBegin; 5591 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5592 PetscValidPointer(pc, 2); 5593 if (!snes->npc) { 5594 PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc)); 5595 PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1)); 5596 PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 5597 PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix)); 5598 PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_")); 5599 PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE)); 5600 } 5601 *pc = snes->npc; 5602 PetscFunctionReturn(0); 5603 } 5604 5605 /*@ 5606 SNESHasNPC - Returns whether a nonlinear preconditioner exists 5607 5608 Not Collective 5609 5610 Input Parameter: 5611 . snes - iterative context obtained from `SNESCreate()` 5612 5613 Output Parameter: 5614 . has_npc - whether the `SNES` has an NPC or not 5615 5616 Level: developer 5617 5618 .seealso: `SNESSetNPC()`, `SNESGetNPC()` 5619 @*/ 5620 PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5621 { 5622 PetscFunctionBegin; 5623 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5624 *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE); 5625 PetscFunctionReturn(0); 5626 } 5627 5628 /*@ 5629 SNESSetNPCSide - Sets the preconditioning side. 5630 5631 Logically Collective on snes 5632 5633 Input Parameter: 5634 . snes - iterative context obtained from `SNESCreate()` 5635 5636 Output Parameter: 5637 . side - the preconditioning side, where side is one of 5638 .vb 5639 PC_LEFT - left preconditioning 5640 PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5641 .ve 5642 5643 Options Database Key: 5644 . -snes_npc_side <right,left> - nonlinear preconditioner side 5645 5646 Note: 5647 `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning. 5648 5649 Level: intermediate 5650 5651 .seealso: `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()` 5652 @*/ 5653 PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side) 5654 { 5655 PetscFunctionBegin; 5656 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5657 PetscValidLogicalCollectiveEnum(snes, side, 2); 5658 if (side == PC_SIDE_DEFAULT) side = PC_RIGHT; 5659 PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported"); 5660 snes->npcside = side; 5661 PetscFunctionReturn(0); 5662 } 5663 5664 /*@ 5665 SNESGetNPCSide - Gets the preconditioning side. 5666 5667 Not Collective 5668 5669 Input Parameter: 5670 . snes - iterative context obtained from `SNESCreate()` 5671 5672 Output Parameter: 5673 . side - the preconditioning side, where side is one of 5674 .vb 5675 `PC_LEFT` - left preconditioning 5676 `PC_RIGHT` - right preconditioning (default for most nonlinear solvers) 5677 .ve 5678 5679 Level: intermediate 5680 5681 .seealso: `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()` 5682 @*/ 5683 PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side) 5684 { 5685 PetscFunctionBegin; 5686 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5687 PetscValidPointer(side, 2); 5688 *side = snes->npcside; 5689 PetscFunctionReturn(0); 5690 } 5691 5692 /*@ 5693 SNESSetLineSearch - Sets the linesearch on the `SNES` instance. 5694 5695 Collective on snes 5696 5697 Input Parameters: 5698 + snes - iterative context obtained from `SNESCreate()` 5699 - linesearch - the linesearch object 5700 5701 Note: 5702 Use `SNESGetLineSearch()` to retrieve the preconditioner context (for example, 5703 to configure it using the API). 5704 5705 Level: developer 5706 5707 .seealso: `SNESGetLineSearch()` 5708 @*/ 5709 PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5710 { 5711 PetscFunctionBegin; 5712 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5713 PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 5714 PetscCheckSameComm(snes, 1, linesearch, 2); 5715 PetscCall(PetscObjectReference((PetscObject)linesearch)); 5716 PetscCall(SNESLineSearchDestroy(&snes->linesearch)); 5717 5718 snes->linesearch = linesearch; 5719 5720 PetscFunctionReturn(0); 5721 } 5722 5723 /*@ 5724 SNESGetLineSearch - Returns a pointer to the line search context set with `SNESSetLineSearch()` 5725 or creates a default line search instance associated with the `SNES` and returns it. 5726 5727 Not Collective 5728 5729 Input Parameter: 5730 . snes - iterative context obtained from `SNESCreate()` 5731 5732 Output Parameter: 5733 . linesearch - linesearch context 5734 5735 Level: beginner 5736 5737 .seealso: `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()` 5738 @*/ 5739 PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5740 { 5741 const char *optionsprefix; 5742 5743 PetscFunctionBegin; 5744 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5745 PetscValidPointer(linesearch, 2); 5746 if (!snes->linesearch) { 5747 PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix)); 5748 PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch)); 5749 PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes)); 5750 PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix)); 5751 PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1)); 5752 } 5753 *linesearch = snes->linesearch; 5754 PetscFunctionReturn(0); 5755 } 5756