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