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