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