xref: /petsc/src/snes/interface/snes.c (revision 67f7d742d70e61a8a21ffc5235261ec57ea3c5cd)
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  = 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, &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)(&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 == PETSC_DETERMINE) {
3909     snes->max_its = snes->default_max_its;
3910   } else if (maxit == 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 == PETSC_DETERMINE) {
3918     snes->max_funcs = snes->default_max_funcs;
3919   } else if (maxf == 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 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()`
3949 @*/
3950 PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3951 {
3952   PetscFunctionBegin;
3953   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3954   PetscValidLogicalCollectiveReal(snes, divtol, 2);
3955 
3956   if (divtol == (PetscReal)PETSC_DETERMINE) {
3957     snes->divtol = snes->default_divtol;
3958   } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) {
3959     snes->divtol = PETSC_UNLIMITED;
3960   } else if (divtol != (PetscReal)PETSC_CURRENT) {
3961     PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol);
3962     snes->divtol = divtol;
3963   }
3964   PetscFunctionReturn(PETSC_SUCCESS);
3965 }
3966 
3967 /*@
3968   SNESGetTolerances - Gets various parameters used in convergence tests.
3969 
3970   Not Collective
3971 
3972   Input Parameter:
3973 . snes - the `SNES` context
3974 
3975   Output Parameters:
3976 + atol  - absolute convergence tolerance
3977 . rtol  - relative convergence tolerance
3978 . stol  - convergence tolerance in terms of the norm of the change in the solution between steps
3979 . maxit - maximum number of iterations
3980 - maxf  - maximum number of function evaluations, `PETSC_UNLIMITED` indicates no bound
3981 
3982   Level: intermediate
3983 
3984   Note:
3985   The user can specify `NULL` for any parameter that is not needed.
3986 
3987 .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
3988 @*/
3989 PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3990 {
3991   PetscFunctionBegin;
3992   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3993   if (atol) *atol = snes->abstol;
3994   if (rtol) *rtol = snes->rtol;
3995   if (stol) *stol = snes->stol;
3996   if (maxit) *maxit = snes->max_its;
3997   if (maxf) *maxf = snes->max_funcs;
3998   PetscFunctionReturn(PETSC_SUCCESS);
3999 }
4000 
4001 /*@
4002   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
4003 
4004   Not Collective
4005 
4006   Input Parameters:
4007 + snes   - the `SNES` context
4008 - divtol - divergence tolerance
4009 
4010   Level: intermediate
4011 
4012 .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
4013 @*/
4014 PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
4015 {
4016   PetscFunctionBegin;
4017   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4018   if (divtol) *divtol = snes->divtol;
4019   PetscFunctionReturn(PETSC_SUCCESS);
4020 }
4021 
4022 PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
4023 
4024 PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
4025 {
4026   PetscDrawLG      lg;
4027   PetscReal        x, y, per;
4028   PetscViewer      v = (PetscViewer)monctx;
4029   static PetscReal prev; /* should be in the context */
4030   PetscDraw        draw;
4031 
4032   PetscFunctionBegin;
4033   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
4034   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
4035   if (!n) PetscCall(PetscDrawLGReset(lg));
4036   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4037   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
4038   x = (PetscReal)n;
4039   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
4040   else y = -15.0;
4041   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4042   if (n < 20 || !(n % 5) || snes->reason) {
4043     PetscCall(PetscDrawLGDraw(lg));
4044     PetscCall(PetscDrawLGSave(lg));
4045   }
4046 
4047   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
4048   if (!n) PetscCall(PetscDrawLGReset(lg));
4049   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4050   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
4051   PetscCall(SNESMonitorRange_Private(snes, n, &per));
4052   x = (PetscReal)n;
4053   y = 100.0 * per;
4054   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4055   if (n < 20 || !(n % 5) || snes->reason) {
4056     PetscCall(PetscDrawLGDraw(lg));
4057     PetscCall(PetscDrawLGSave(lg));
4058   }
4059 
4060   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
4061   if (!n) {
4062     prev = rnorm;
4063     PetscCall(PetscDrawLGReset(lg));
4064   }
4065   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4066   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
4067   x = (PetscReal)n;
4068   y = (prev - rnorm) / prev;
4069   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4070   if (n < 20 || !(n % 5) || snes->reason) {
4071     PetscCall(PetscDrawLGDraw(lg));
4072     PetscCall(PetscDrawLGSave(lg));
4073   }
4074 
4075   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
4076   if (!n) PetscCall(PetscDrawLGReset(lg));
4077   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4078   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
4079   x = (PetscReal)n;
4080   y = (prev - rnorm) / (prev * per);
4081   if (n > 2) { /*skip initial crazy value */
4082     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4083   }
4084   if (n < 20 || !(n % 5) || snes->reason) {
4085     PetscCall(PetscDrawLGDraw(lg));
4086     PetscCall(PetscDrawLGSave(lg));
4087   }
4088   prev = rnorm;
4089   PetscFunctionReturn(PETSC_SUCCESS);
4090 }
4091 
4092 /*@
4093   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
4094 
4095   Collective
4096 
4097   Input Parameters:
4098 + snes  - the `SNES` context
4099 . it    - current iteration
4100 . xnorm - 2-norm of current iterate
4101 . snorm - 2-norm of current step
4102 - fnorm - 2-norm of function
4103 
4104   Level: developer
4105 
4106   Note:
4107   This routine is called by the `SNESSolve()` implementations.
4108   It does not typically need to be called by the user.
4109 
4110 .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4111 @*/
4112 PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
4113 {
4114   PetscFunctionBegin;
4115   if (!snes->reason) {
4116     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
4117     if (it == snes->max_its && !snes->reason) {
4118       if (snes->normschedule == SNES_NORM_ALWAYS) {
4119         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
4120         snes->reason = SNES_DIVERGED_MAX_IT;
4121       } else snes->reason = SNES_CONVERGED_ITS;
4122     }
4123   }
4124   PetscFunctionReturn(PETSC_SUCCESS);
4125 }
4126 
4127 /*@
4128   SNESMonitor - runs the user provided monitor routines, if they exist
4129 
4130   Collective
4131 
4132   Input Parameters:
4133 + snes  - nonlinear solver context obtained from `SNESCreate()`
4134 . iter  - iteration number
4135 - rnorm - relative norm of the residual
4136 
4137   Level: developer
4138 
4139   Note:
4140   This routine is called by the `SNESSolve()` implementations.
4141   It does not typically need to be called by the user.
4142 
4143 .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4144 @*/
4145 PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4146 {
4147   PetscInt i, n = snes->numbermonitors;
4148 
4149   PetscFunctionBegin;
4150   if (n > 0) SNESCheckFunctionNorm(snes, rnorm);
4151   PetscCall(VecLockReadPush(snes->vec_sol));
4152   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
4153   PetscCall(VecLockReadPop(snes->vec_sol));
4154   PetscFunctionReturn(PETSC_SUCCESS);
4155 }
4156 
4157 /* ------------ Routines to set performance monitoring options ----------- */
4158 
4159 /*MC
4160     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4161 
4162      Synopsis:
4163      #include <petscsnes.h>
4164     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4165 
4166      Collective
4167 
4168     Input Parameters:
4169 +    snes - the `SNES` context
4170 .    its - iteration number
4171 .    norm - 2-norm function value (may be estimated)
4172 -    mctx - [optional] monitoring context
4173 
4174    Level: advanced
4175 
4176 .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
4177 M*/
4178 
4179 /*@C
4180   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
4181   iteration of the nonlinear solver to display the iteration's
4182   progress.
4183 
4184   Logically Collective
4185 
4186   Input Parameters:
4187 + snes           - the `SNES` context
4188 . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4189 . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
4190 - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
4191 
4192   Options Database Keys:
4193 + -snes_monitor               - sets `SNESMonitorDefault()`
4194 . -snes_monitor draw::draw_lg - sets line graph monitor,
4195 - -snes_monitor_cancel        - cancels all monitors that have been hardwired into a code by calls to `SNESMonitorSet()`, but does not cancel those set via
4196                                 the options database.
4197 
4198   Level: intermediate
4199 
4200   Note:
4201   Several different monitoring routines may be set by calling
4202   `SNESMonitorSet()` multiple times; all will be called in the
4203   order in which they were set.
4204 
4205   Fortran Note:
4206   Only a single monitor function can be set for each `SNES` object
4207 
4208 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn`
4209 @*/
4210 PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy)
4211 {
4212   PetscInt  i;
4213   PetscBool identical;
4214 
4215   PetscFunctionBegin;
4216   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4217   for (i = 0; i < snes->numbermonitors; i++) {
4218     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
4219     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4220   }
4221   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
4222   snes->monitor[snes->numbermonitors]          = f;
4223   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4224   snes->monitorcontext[snes->numbermonitors++] = mctx;
4225   PetscFunctionReturn(PETSC_SUCCESS);
4226 }
4227 
4228 /*@
4229   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
4230 
4231   Logically Collective
4232 
4233   Input Parameter:
4234 . snes - the `SNES` context
4235 
4236   Options Database Key:
4237 . -snes_monitor_cancel - cancels all monitors that have been hardwired
4238     into a code by calls to `SNESMonitorSet()`, but does not cancel those
4239     set via the options database
4240 
4241   Level: intermediate
4242 
4243   Note:
4244   There is no way to clear one specific monitor from a `SNES` object.
4245 
4246 .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
4247 @*/
4248 PetscErrorCode SNESMonitorCancel(SNES snes)
4249 {
4250   PetscInt i;
4251 
4252   PetscFunctionBegin;
4253   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4254   for (i = 0; i < snes->numbermonitors; i++) {
4255     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4256   }
4257   snes->numbermonitors = 0;
4258   PetscFunctionReturn(PETSC_SUCCESS);
4259 }
4260 
4261 /*MC
4262     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4263 
4264      Synopsis:
4265      #include <petscsnes.h>
4266      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4267 
4268      Collective
4269 
4270     Input Parameters:
4271 +    snes - the `SNES` context
4272 .    it - current iteration (0 is the first and is before any Newton step)
4273 .    xnorm - 2-norm of current iterate
4274 .    gnorm - 2-norm of current step
4275 .    f - 2-norm of function
4276 -    cctx - [optional] convergence context
4277 
4278     Output Parameter:
4279 .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4280 
4281    Level: intermediate
4282 
4283 .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4284 M*/
4285 
4286 /*@C
4287   SNESSetConvergenceTest - Sets the function that is to be used
4288   to test for convergence of the nonlinear iterative solution.
4289 
4290   Logically Collective
4291 
4292   Input Parameters:
4293 + snes                        - the `SNES` context
4294 . SNESConvergenceTestFunction - routine to test for convergence
4295 . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4296 - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
4297 
4298   Level: advanced
4299 
4300 .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
4301 @*/
4302 PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4303 {
4304   PetscFunctionBegin;
4305   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4306   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
4307   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4308   snes->ops->converged        = SNESConvergenceTestFunction;
4309   snes->ops->convergeddestroy = destroy;
4310   snes->cnvP                  = cctx;
4311   PetscFunctionReturn(PETSC_SUCCESS);
4312 }
4313 
4314 /*@
4315   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4316 
4317   Not Collective
4318 
4319   Input Parameter:
4320 . snes - the `SNES` context
4321 
4322   Output Parameter:
4323 . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4324 
4325   Options Database Key:
4326 . -snes_converged_reason - prints the reason to standard out
4327 
4328   Level: intermediate
4329 
4330   Note:
4331   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4332 
4333 .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4334 @*/
4335 PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4336 {
4337   PetscFunctionBegin;
4338   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4339   PetscAssertPointer(reason, 2);
4340   *reason = snes->reason;
4341   PetscFunctionReturn(PETSC_SUCCESS);
4342 }
4343 
4344 /*@C
4345   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4346 
4347   Not Collective
4348 
4349   Input Parameter:
4350 . snes - the `SNES` context
4351 
4352   Output Parameter:
4353 . strreason - a human readable string that describes `SNES` converged reason
4354 
4355   Level: beginner
4356 
4357 .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4358 @*/
4359 PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4360 {
4361   PetscFunctionBegin;
4362   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4363   PetscAssertPointer(strreason, 2);
4364   *strreason = SNESConvergedReasons[snes->reason];
4365   PetscFunctionReturn(PETSC_SUCCESS);
4366 }
4367 
4368 /*@
4369   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
4370 
4371   Not Collective
4372 
4373   Input Parameters:
4374 + snes   - the `SNES` context
4375 - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
4376             manual pages for the individual convergence tests for complete lists
4377 
4378   Level: developer
4379 
4380   Developer Note:
4381   Called inside the various `SNESSolve()` implementations
4382 
4383 .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
4384 @*/
4385 PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4386 {
4387   PetscFunctionBegin;
4388   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4389   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
4390   snes->reason = reason;
4391   PetscFunctionReturn(PETSC_SUCCESS);
4392 }
4393 
4394 /*@
4395   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4396 
4397   Logically Collective
4398 
4399   Input Parameters:
4400 + snes  - iterative context obtained from `SNESCreate()`
4401 . a     - array to hold history, this array will contain the function norms computed at each step
4402 . its   - integer array holds the number of linear iterations for each solve.
4403 . na    - size of `a` and `its`
4404 - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4405           else it continues storing new values for new nonlinear solves after the old ones
4406 
4407   Level: intermediate
4408 
4409   Notes:
4410   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` then a
4411   default array of length 1,000 is allocated.
4412 
4413   This routine is useful, e.g., when running a code for purposes
4414   of accurate performance monitoring, when no I/O should be done
4415   during the section of code that is being timed.
4416 
4417   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4418 
4419 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4420 @*/
4421 PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4422 {
4423   PetscFunctionBegin;
4424   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4425   if (a) PetscAssertPointer(a, 2);
4426   if (its) PetscAssertPointer(its, 3);
4427   if (!a) {
4428     if (na == PETSC_DECIDE) na = 1000;
4429     PetscCall(PetscCalloc2(na, &a, na, &its));
4430     snes->conv_hist_alloc = PETSC_TRUE;
4431   }
4432   snes->conv_hist       = a;
4433   snes->conv_hist_its   = its;
4434   snes->conv_hist_max   = (size_t)na;
4435   snes->conv_hist_len   = 0;
4436   snes->conv_hist_reset = reset;
4437   PetscFunctionReturn(PETSC_SUCCESS);
4438 }
4439 
4440 #if defined(PETSC_HAVE_MATLAB)
4441   #include <engine.h> /* MATLAB include file */
4442   #include <mex.h>    /* MATLAB include file */
4443 
4444 PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4445 {
4446   mxArray   *mat;
4447   PetscInt   i;
4448   PetscReal *ar;
4449 
4450   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4451   ar  = (PetscReal *)mxGetData(mat);
4452   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
4453   return mat;
4454 }
4455 #endif
4456 
4457 /*@C
4458   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4459 
4460   Not Collective
4461 
4462   Input Parameter:
4463 . snes - iterative context obtained from `SNESCreate()`
4464 
4465   Output Parameters:
4466 + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4467 . its - integer array holds the number of linear iterations (or
4468          negative if not converged) for each solve.
4469 - na  - size of `a` and `its`
4470 
4471   Level: intermediate
4472 
4473   Note:
4474   This routine is useful, e.g., when running a code for purposes
4475   of accurate performance monitoring, when no I/O should be done
4476   during the section of code that is being timed.
4477 
4478   Fortran Note:
4479   The calling sequence for this routine in Fortran is
4480 .vb
4481     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4482 .ve
4483 
4484 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4485 @*/
4486 PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4487 {
4488   PetscFunctionBegin;
4489   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4490   if (a) *a = snes->conv_hist;
4491   if (its) *its = snes->conv_hist_its;
4492   if (na) *na = (PetscInt)snes->conv_hist_len;
4493   PetscFunctionReturn(PETSC_SUCCESS);
4494 }
4495 
4496 /*@C
4497   SNESSetUpdate - Sets the general-purpose update function called
4498   at the beginning of every iteration of the nonlinear solve. Specifically
4499   it is called just before the Jacobian is "evaluated" and after the function
4500   evaluation.
4501 
4502   Logically Collective
4503 
4504   Input Parameters:
4505 + snes - The nonlinear solver context
4506 - func - The update function; for calling sequence see `SNESUpdateFn`
4507 
4508   Level: advanced
4509 
4510   Notes:
4511   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
4512   to `SNESSetFunction()`, or `SNESSetPicard()`
4513   This is not used by most users, and it is intended to provide a general hook that is run
4514   right before the direction step is computed.
4515   Users are free to modify the current residual vector,
4516   the current linearization point, or any other vector associated to the specific solver used.
4517   If such modifications take place, it is the user responsibility to update all the relevant
4518   vectors.
4519 
4520   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.
4521 
4522 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
4523          `SNESMonitorSet()`
4524 @*/
4525 PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4526 {
4527   PetscFunctionBegin;
4528   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4529   snes->ops->update = func;
4530   PetscFunctionReturn(PETSC_SUCCESS);
4531 }
4532 
4533 /*@
4534   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
4535 
4536   Collective
4537 
4538   Input Parameters:
4539 + snes   - iterative context obtained from `SNESCreate()`
4540 - viewer - the viewer to display the reason
4541 
4542   Options Database Keys:
4543 + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4544 - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4545 
4546   Level: beginner
4547 
4548   Note:
4549   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4550   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
4551 
4552 .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4553           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4554           `SNESConvergedReasonViewFromOptions()`,
4555           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
4556 @*/
4557 PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4558 {
4559   PetscViewerFormat format;
4560   PetscBool         isAscii;
4561 
4562   PetscFunctionBegin;
4563   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
4564   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
4565   if (isAscii) {
4566     PetscCall(PetscViewerGetFormat(viewer, &format));
4567     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
4568     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
4569       DM       dm;
4570       Vec      u;
4571       PetscDS  prob;
4572       PetscInt Nf, f;
4573       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
4574       void    **exactCtx;
4575       PetscReal error;
4576 
4577       PetscCall(SNESGetDM(snes, &dm));
4578       PetscCall(SNESGetSolution(snes, &u));
4579       PetscCall(DMGetDS(dm, &prob));
4580       PetscCall(PetscDSGetNumFields(prob, &Nf));
4581       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
4582       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
4583       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
4584       PetscCall(PetscFree2(exactSol, exactCtx));
4585       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
4586       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
4587     }
4588     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
4589       if (((PetscObject)snes)->prefix) {
4590         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
4591       } else {
4592         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
4593       }
4594     } else if (snes->reason <= 0) {
4595       if (((PetscObject)snes)->prefix) {
4596         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve did not converge due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
4597       } else {
4598         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
4599       }
4600     }
4601     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
4602   }
4603   PetscFunctionReturn(PETSC_SUCCESS);
4604 }
4605 
4606 /*@C
4607   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4608   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4609 
4610   Logically Collective
4611 
4612   Input Parameters:
4613 + snes              - the `SNES` context
4614 . f                 - the `SNESConvergedReason` view function
4615 . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
4616 - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
4617 
4618   Calling sequence of `f`:
4619 + snes - the `SNES` context
4620 - vctx - [optional] context for private data for the function
4621 
4622   Options Database Keys:
4623 + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4624 - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4625                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4626 
4627   Level: intermediate
4628 
4629   Note:
4630   Several different converged reason view routines may be set by calling
4631   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4632   order in which they were set.
4633 
4634 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`,
4635           `PetscCtxDestroyFn`
4636 @*/
4637 PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy)
4638 {
4639   PetscInt  i;
4640   PetscBool identical;
4641 
4642   PetscFunctionBegin;
4643   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4644   for (i = 0; i < snes->numberreasonviews; i++) {
4645     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
4646     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4647   }
4648   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4649   snes->reasonview[snes->numberreasonviews]          = f;
4650   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4651   snes->reasonviewcontext[snes->numberreasonviews++] = vctx;
4652   PetscFunctionReturn(PETSC_SUCCESS);
4653 }
4654 
4655 /*@
4656   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
4657   All the user-provided convergedReasonView routines will be involved as well, if they exist.
4658 
4659   Collective
4660 
4661   Input Parameter:
4662 . snes - the `SNES` object
4663 
4664   Level: advanced
4665 
4666 .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4667           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
4668 @*/
4669 PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4670 {
4671   static PetscBool incall = PETSC_FALSE;
4672 
4673   PetscFunctionBegin;
4674   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
4675   incall = PETSC_TRUE;
4676 
4677   /* All user-provided viewers are called first, if they exist. */
4678   for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4679 
4680   /* Call PETSc default routine if users ask for it */
4681   if (snes->convergedreasonviewer) {
4682     PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
4683     PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
4684     PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
4685   }
4686   incall = PETSC_FALSE;
4687   PetscFunctionReturn(PETSC_SUCCESS);
4688 }
4689 
4690 /*@
4691   SNESSolve - Solves a nonlinear system F(x) = b.
4692 
4693   Collective
4694 
4695   Input Parameters:
4696 + snes - the `SNES` context
4697 . b    - the constant part of the equation F(x) = b, or `NULL` to use zero.
4698 - x    - the solution vector.
4699 
4700   Level: beginner
4701 
4702   Note:
4703   The user should initialize the vector, `x`, with the initial guess
4704   for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`.  In particular,
4705   to employ an initial guess of zero, the user should explicitly set
4706   this vector to zero by calling `VecSet()`.
4707 
4708 .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4709           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4710           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()`
4711 @*/
4712 PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4713 {
4714   PetscBool flg;
4715   PetscInt  grid;
4716   Vec       xcreated = NULL;
4717   DM        dm;
4718 
4719   PetscFunctionBegin;
4720   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4721   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4722   if (x) PetscCheckSameComm(snes, 1, x, 3);
4723   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4724   if (b) PetscCheckSameComm(snes, 1, b, 2);
4725 
4726   /* High level operations using the nonlinear solver */
4727   {
4728     PetscViewer       viewer;
4729     PetscViewerFormat format;
4730     PetscInt          num;
4731     PetscBool         flg;
4732     static PetscBool  incall = PETSC_FALSE;
4733 
4734     if (!incall) {
4735       /* Estimate the convergence rate of the discretization */
4736       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
4737       if (flg) {
4738         PetscConvEst conv;
4739         DM           dm;
4740         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
4741         PetscInt     Nf;
4742 
4743         incall = PETSC_TRUE;
4744         PetscCall(SNESGetDM(snes, &dm));
4745         PetscCall(DMGetNumFields(dm, &Nf));
4746         PetscCall(PetscCalloc1(Nf, &alpha));
4747         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
4748         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
4749         PetscCall(PetscConvEstSetFromOptions(conv));
4750         PetscCall(PetscConvEstSetUp(conv));
4751         PetscCall(PetscConvEstGetConvRate(conv, alpha));
4752         PetscCall(PetscViewerPushFormat(viewer, format));
4753         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
4754         PetscCall(PetscViewerPopFormat(viewer));
4755         PetscCall(PetscViewerDestroy(&viewer));
4756         PetscCall(PetscConvEstDestroy(&conv));
4757         PetscCall(PetscFree(alpha));
4758         incall = PETSC_FALSE;
4759       }
4760       /* Adaptively refine the initial grid */
4761       num = 1;
4762       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
4763       if (flg) {
4764         DMAdaptor adaptor;
4765 
4766         incall = PETSC_TRUE;
4767         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4768         PetscCall(DMAdaptorSetSolver(adaptor, snes));
4769         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
4770         PetscCall(DMAdaptorSetFromOptions(adaptor));
4771         PetscCall(DMAdaptorSetUp(adaptor));
4772         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
4773         PetscCall(DMAdaptorDestroy(&adaptor));
4774         incall = PETSC_FALSE;
4775       }
4776       /* Use grid sequencing to adapt */
4777       num = 0;
4778       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
4779       if (num) {
4780         DMAdaptor   adaptor;
4781         const char *prefix;
4782 
4783         incall = PETSC_TRUE;
4784         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4785         PetscCall(SNESGetOptionsPrefix(snes, &prefix));
4786         PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix));
4787         PetscCall(DMAdaptorSetSolver(adaptor, snes));
4788         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
4789         PetscCall(DMAdaptorSetFromOptions(adaptor));
4790         PetscCall(DMAdaptorSetUp(adaptor));
4791         PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
4792         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
4793         PetscCall(DMAdaptorDestroy(&adaptor));
4794         incall = PETSC_FALSE;
4795       }
4796     }
4797   }
4798   if (!x) x = snes->vec_sol;
4799   if (!x) {
4800     PetscCall(SNESGetDM(snes, &dm));
4801     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4802     x = xcreated;
4803   }
4804   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4805 
4806   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4807   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
4808     /* set solution vector */
4809     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
4810     PetscCall(VecDestroy(&snes->vec_sol));
4811     snes->vec_sol = x;
4812     PetscCall(SNESGetDM(snes, &dm));
4813 
4814     /* set affine vector if provided */
4815     if (b) PetscCall(PetscObjectReference((PetscObject)b));
4816     PetscCall(VecDestroy(&snes->vec_rhs));
4817     snes->vec_rhs = b;
4818 
4819     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");
4820     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4821     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4822     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
4823     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
4824     PetscCall(SNESSetUp(snes));
4825 
4826     if (!grid) {
4827       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4828     }
4829 
4830     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
4831     PetscCall(SNESResetCounters(snes));
4832     snes->reason = SNES_CONVERGED_ITERATING;
4833     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4834     PetscUseTypeMethod(snes, solve);
4835     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
4836     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4837     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
4838 
4839     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
4840     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
4841 
4842     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
4843     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4844     /* Call converged reason views. This may involve user-provided viewers as well */
4845     PetscCall(SNESConvergedReasonViewFromOptions(snes));
4846 
4847     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
4848     if (snes->reason < 0) break;
4849     if (grid < snes->gridsequence) {
4850       DM  fine;
4851       Vec xnew;
4852       Mat interp;
4853 
4854       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
4855       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
4856       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
4857       PetscCall(DMCreateGlobalVector(fine, &xnew));
4858       PetscCall(MatInterpolate(interp, x, xnew));
4859       PetscCall(DMInterpolate(snes->dm, interp, fine));
4860       PetscCall(MatDestroy(&interp));
4861       x = xnew;
4862 
4863       PetscCall(SNESReset(snes));
4864       PetscCall(SNESSetDM(snes, fine));
4865       PetscCall(SNESResetFromOptions(snes));
4866       PetscCall(DMDestroy(&fine));
4867       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4868     }
4869   }
4870   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
4871   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
4872   PetscCall(DMMonitor(snes->dm));
4873   PetscCall(SNESMonitorPauseFinal_Internal(snes));
4874 
4875   PetscCall(VecDestroy(&xcreated));
4876   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
4877   PetscFunctionReturn(PETSC_SUCCESS);
4878 }
4879 
4880 /* --------- Internal routines for SNES Package --------- */
4881 
4882 /*@
4883   SNESSetType - Sets the method for the nonlinear solver.
4884 
4885   Collective
4886 
4887   Input Parameters:
4888 + snes - the `SNES` context
4889 - type - a known method
4890 
4891   Options Database Key:
4892 . -snes_type <type> - Sets the method; use -help for a list
4893    of available methods (for instance, newtonls or newtontr)
4894 
4895   Level: intermediate
4896 
4897   Notes:
4898   See "petsc/include/petscsnes.h" for available methods (for instance)
4899 +    `SNESNEWTONLS` - Newton's method with line search
4900   (systems of nonlinear equations)
4901 -    `SNESNEWTONTR` - Newton's method with trust region
4902   (systems of nonlinear equations)
4903 
4904   Normally, it is best to use the `SNESSetFromOptions()` command and then
4905   set the `SNES` solver type from the options database rather than by using
4906   this routine.  Using the options database provides the user with
4907   maximum flexibility in evaluating the many nonlinear solvers.
4908   The `SNESSetType()` routine is provided for those situations where it
4909   is necessary to set the nonlinear solver independently of the command
4910   line or options database.  This might be the case, for example, when
4911   the choice of solver changes during the execution of the program,
4912   and the user's application is taking responsibility for choosing the
4913   appropriate method.
4914 
4915   Developer Note:
4916   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4917   the constructor in that list and calls it to create the specific object.
4918 
4919 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
4920 @*/
4921 PetscErrorCode SNESSetType(SNES snes, SNESType type)
4922 {
4923   PetscBool match;
4924   PetscErrorCode (*r)(SNES);
4925 
4926   PetscFunctionBegin;
4927   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4928   PetscAssertPointer(type, 2);
4929 
4930   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
4931   if (match) PetscFunctionReturn(PETSC_SUCCESS);
4932 
4933   PetscCall(PetscFunctionListFind(SNESList, type, &r));
4934   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
4935   /* Destroy the previous private SNES context */
4936   PetscTryTypeMethod(snes, destroy);
4937   /* Reinitialize function pointers in SNESOps structure */
4938   snes->ops->setup          = NULL;
4939   snes->ops->solve          = NULL;
4940   snes->ops->view           = NULL;
4941   snes->ops->setfromoptions = NULL;
4942   snes->ops->destroy        = NULL;
4943 
4944   /* It may happen the user has customized the line search before calling SNESSetType */
4945   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
4946 
4947   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
4948   snes->setupcalled = PETSC_FALSE;
4949 
4950   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
4951   PetscCall((*r)(snes));
4952   PetscFunctionReturn(PETSC_SUCCESS);
4953 }
4954 
4955 /*@
4956   SNESGetType - Gets the `SNES` method type and name (as a string).
4957 
4958   Not Collective
4959 
4960   Input Parameter:
4961 . snes - nonlinear solver context
4962 
4963   Output Parameter:
4964 . type - `SNES` method (a character string)
4965 
4966   Level: intermediate
4967 
4968 .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
4969 @*/
4970 PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4971 {
4972   PetscFunctionBegin;
4973   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4974   PetscAssertPointer(type, 2);
4975   *type = ((PetscObject)snes)->type_name;
4976   PetscFunctionReturn(PETSC_SUCCESS);
4977 }
4978 
4979 /*@
4980   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
4981 
4982   Logically Collective
4983 
4984   Input Parameters:
4985 + snes - the `SNES` context obtained from `SNESCreate()`
4986 - u    - the solution vector
4987 
4988   Level: beginner
4989 
4990 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
4991 @*/
4992 PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4993 {
4994   DM dm;
4995 
4996   PetscFunctionBegin;
4997   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4998   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
4999   PetscCall(PetscObjectReference((PetscObject)u));
5000   PetscCall(VecDestroy(&snes->vec_sol));
5001 
5002   snes->vec_sol = u;
5003 
5004   PetscCall(SNESGetDM(snes, &dm));
5005   PetscCall(DMShellSetGlobalVector(dm, u));
5006   PetscFunctionReturn(PETSC_SUCCESS);
5007 }
5008 
5009 /*@
5010   SNESGetSolution - Returns the vector where the approximate solution is
5011   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
5012 
5013   Not Collective, but `x` is parallel if `snes` is parallel
5014 
5015   Input Parameter:
5016 . snes - the `SNES` context
5017 
5018   Output Parameter:
5019 . x - the solution
5020 
5021   Level: intermediate
5022 
5023 .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
5024 @*/
5025 PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
5026 {
5027   PetscFunctionBegin;
5028   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5029   PetscAssertPointer(x, 2);
5030   *x = snes->vec_sol;
5031   PetscFunctionReturn(PETSC_SUCCESS);
5032 }
5033 
5034 /*@
5035   SNESGetSolutionUpdate - Returns the vector where the solution update is
5036   stored.
5037 
5038   Not Collective, but `x` is parallel if `snes` is parallel
5039 
5040   Input Parameter:
5041 . snes - the `SNES` context
5042 
5043   Output Parameter:
5044 . x - the solution update
5045 
5046   Level: advanced
5047 
5048 .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
5049 @*/
5050 PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
5051 {
5052   PetscFunctionBegin;
5053   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5054   PetscAssertPointer(x, 2);
5055   *x = snes->vec_sol_update;
5056   PetscFunctionReturn(PETSC_SUCCESS);
5057 }
5058 
5059 /*@C
5060   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
5061 
5062   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
5063 
5064   Input Parameter:
5065 . snes - the `SNES` context
5066 
5067   Output Parameters:
5068 + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
5069 . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
5070 - ctx - the function context (or `NULL` if you don't want it)
5071 
5072   Level: advanced
5073 
5074   Note:
5075   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
5076 
5077 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
5078 @*/
5079 PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
5080 {
5081   DM dm;
5082 
5083   PetscFunctionBegin;
5084   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5085   if (r) {
5086     if (!snes->vec_func) {
5087       if (snes->vec_rhs) {
5088         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5089       } else if (snes->vec_sol) {
5090         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5091       } else if (snes->dm) {
5092         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5093       }
5094     }
5095     *r = snes->vec_func;
5096   }
5097   PetscCall(SNESGetDM(snes, &dm));
5098   PetscCall(DMSNESGetFunction(dm, f, ctx));
5099   PetscFunctionReturn(PETSC_SUCCESS);
5100 }
5101 
5102 /*@C
5103   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5104 
5105   Input Parameter:
5106 . snes - the `SNES` context
5107 
5108   Output Parameters:
5109 + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5110 - ctx - the function context (or `NULL`)
5111 
5112   Level: advanced
5113 
5114 .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5115 @*/
5116 PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5117 {
5118   DM dm;
5119 
5120   PetscFunctionBegin;
5121   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5122   PetscCall(SNESGetDM(snes, &dm));
5123   PetscCall(DMSNESGetNGS(dm, f, ctx));
5124   PetscFunctionReturn(PETSC_SUCCESS);
5125 }
5126 
5127 /*@
5128   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5129   `SNES` options in the database.
5130 
5131   Logically Collective
5132 
5133   Input Parameters:
5134 + snes   - the `SNES` context
5135 - prefix - the prefix to prepend to all option names
5136 
5137   Level: advanced
5138 
5139   Note:
5140   A hyphen (-) must NOT be given at the beginning of the prefix name.
5141   The first character of all runtime options is AUTOMATICALLY the hyphen.
5142 
5143 .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
5144 @*/
5145 PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5146 {
5147   PetscFunctionBegin;
5148   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5149   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
5150   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
5151   if (snes->linesearch) {
5152     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
5153     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
5154   }
5155   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
5156   PetscFunctionReturn(PETSC_SUCCESS);
5157 }
5158 
5159 /*@
5160   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5161   `SNES` options in the database.
5162 
5163   Logically Collective
5164 
5165   Input Parameters:
5166 + snes   - the `SNES` context
5167 - prefix - the prefix to prepend to all option names
5168 
5169   Level: advanced
5170 
5171   Note:
5172   A hyphen (-) must NOT be given at the beginning of the prefix name.
5173   The first character of all runtime options is AUTOMATICALLY the hyphen.
5174 
5175 .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
5176 @*/
5177 PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5178 {
5179   PetscFunctionBegin;
5180   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5181   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
5182   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
5183   if (snes->linesearch) {
5184     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
5185     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
5186   }
5187   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
5188   PetscFunctionReturn(PETSC_SUCCESS);
5189 }
5190 
5191 /*@
5192   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5193   `SNES` options in the database.
5194 
5195   Not Collective
5196 
5197   Input Parameter:
5198 . snes - the `SNES` context
5199 
5200   Output Parameter:
5201 . prefix - pointer to the prefix string used
5202 
5203   Level: advanced
5204 
5205   Fortran Note:
5206   The user should pass in a string 'prefix' of
5207   sufficient length to hold the prefix.
5208 
5209 .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
5210 @*/
5211 PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5212 {
5213   PetscFunctionBegin;
5214   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5215   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
5216   PetscFunctionReturn(PETSC_SUCCESS);
5217 }
5218 
5219 /*@C
5220   SNESRegister - Adds a method to the nonlinear solver package.
5221 
5222   Not Collective
5223 
5224   Input Parameters:
5225 + sname    - name of a new user-defined solver
5226 - function - routine to create method context
5227 
5228   Level: advanced
5229 
5230   Note:
5231   `SNESRegister()` may be called multiple times to add several user-defined solvers.
5232 
5233   Example Usage:
5234 .vb
5235    SNESRegister("my_solver", MySolverCreate);
5236 .ve
5237 
5238   Then, your solver can be chosen with the procedural interface via
5239 $     SNESSetType(snes, "my_solver")
5240   or at runtime via the option
5241 $     -snes_type my_solver
5242 
5243 .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
5244 @*/
5245 PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5246 {
5247   PetscFunctionBegin;
5248   PetscCall(SNESInitializePackage());
5249   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
5250   PetscFunctionReturn(PETSC_SUCCESS);
5251 }
5252 
5253 PetscErrorCode SNESTestLocalMin(SNES snes)
5254 {
5255   PetscInt    N, i, j;
5256   Vec         u, uh, fh;
5257   PetscScalar value;
5258   PetscReal   norm;
5259 
5260   PetscFunctionBegin;
5261   PetscCall(SNESGetSolution(snes, &u));
5262   PetscCall(VecDuplicate(u, &uh));
5263   PetscCall(VecDuplicate(u, &fh));
5264 
5265   /* currently only works for sequential */
5266   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
5267   PetscCall(VecGetSize(u, &N));
5268   for (i = 0; i < N; i++) {
5269     PetscCall(VecCopy(u, uh));
5270     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5271     for (j = -10; j < 11; j++) {
5272       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
5273       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5274       PetscCall(SNESComputeFunction(snes, uh, fh));
5275       PetscCall(VecNorm(fh, NORM_2, &norm));
5276       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5277       value = -value;
5278       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5279     }
5280   }
5281   PetscCall(VecDestroy(&uh));
5282   PetscCall(VecDestroy(&fh));
5283   PetscFunctionReturn(PETSC_SUCCESS);
5284 }
5285 
5286 /*@
5287   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
5288   computing relative tolerance for linear solvers within an inexact
5289   Newton method.
5290 
5291   Logically Collective
5292 
5293   Input Parameters:
5294 + snes - `SNES` context
5295 - flag - `PETSC_TRUE` or `PETSC_FALSE`
5296 
5297   Options Database Keys:
5298 + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
5299 . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
5300 . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
5301 . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
5302 . -snes_ksp_ew_gamma <gamma>         - Sets gamma
5303 . -snes_ksp_ew_alpha <alpha>         - Sets alpha
5304 . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
5305 - -snes_ksp_ew_threshold <threshold> - Sets threshold
5306 
5307   Level: advanced
5308 
5309   Note:
5310   The default is to use a constant relative tolerance for
5311   the inner linear solvers.  Alternatively, one can use the
5312   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
5313   is reset at each Newton iteration according progress of the nonlinear
5314   solver.
5315 
5316 .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
5317 @*/
5318 PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5319 {
5320   PetscFunctionBegin;
5321   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5322   PetscValidLogicalCollectiveBool(snes, flag, 2);
5323   snes->ksp_ewconv = flag;
5324   PetscFunctionReturn(PETSC_SUCCESS);
5325 }
5326 
5327 /*@
5328   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
5329   for computing relative tolerance for linear solvers within an
5330   inexact Newton method.
5331 
5332   Not Collective
5333 
5334   Input Parameter:
5335 . snes - `SNES` context
5336 
5337   Output Parameter:
5338 . flag - `PETSC_TRUE` or `PETSC_FALSE`
5339 
5340   Level: advanced
5341 
5342 .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
5343 @*/
5344 PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5345 {
5346   PetscFunctionBegin;
5347   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5348   PetscAssertPointer(flag, 2);
5349   *flag = snes->ksp_ewconv;
5350   PetscFunctionReturn(PETSC_SUCCESS);
5351 }
5352 
5353 /*@
5354   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
5355   convergence criteria for the linear solvers within an inexact
5356   Newton method.
5357 
5358   Logically Collective
5359 
5360   Input Parameters:
5361 + snes      - `SNES` context
5362 . version   - version 1, 2 (default is 2), 3 or 4
5363 . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
5364 . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5365 . gamma     - multiplicative factor for version 2 rtol computation
5366              (0 <= gamma2 <= 1)
5367 . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
5368 . alpha2    - power for safeguard
5369 - threshold - threshold for imposing safeguard (0 < threshold < 1)
5370 
5371   Level: advanced
5372 
5373   Notes:
5374   Version 3 was contributed by Luis Chacon, June 2006.
5375 
5376   Use `PETSC_CURRENT` to retain the default for any of the parameters.
5377 
5378 .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
5379 @*/
5380 PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5381 {
5382   SNESKSPEW *kctx;
5383 
5384   PetscFunctionBegin;
5385   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5386   kctx = (SNESKSPEW *)snes->kspconvctx;
5387   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5388   PetscValidLogicalCollectiveInt(snes, version, 2);
5389   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5390   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5391   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5392   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5393   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5394   PetscValidLogicalCollectiveReal(snes, threshold, 8);
5395 
5396   if (version != PETSC_CURRENT) kctx->version = version;
5397   if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0;
5398   if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max;
5399   if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma;
5400   if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha;
5401   if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2;
5402   if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold;
5403 
5404   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);
5405   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);
5406   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);
5407   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);
5408   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);
5409   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);
5410   PetscFunctionReturn(PETSC_SUCCESS);
5411 }
5412 
5413 /*@
5414   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
5415   convergence criteria for the linear solvers within an inexact
5416   Newton method.
5417 
5418   Not Collective
5419 
5420   Input Parameter:
5421 . snes - `SNES` context
5422 
5423   Output Parameters:
5424 + version   - version 1, 2 (default is 2), 3 or 4
5425 . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
5426 . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5427 . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
5428 . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
5429 . alpha2    - power for safeguard
5430 - threshold - threshold for imposing safeguard (0 < threshold < 1)
5431 
5432   Level: advanced
5433 
5434 .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
5435 @*/
5436 PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5437 {
5438   SNESKSPEW *kctx;
5439 
5440   PetscFunctionBegin;
5441   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5442   kctx = (SNESKSPEW *)snes->kspconvctx;
5443   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5444   if (version) *version = kctx->version;
5445   if (rtol_0) *rtol_0 = kctx->rtol_0;
5446   if (rtol_max) *rtol_max = kctx->rtol_max;
5447   if (gamma) *gamma = kctx->gamma;
5448   if (alpha) *alpha = kctx->alpha;
5449   if (alpha2) *alpha2 = kctx->alpha2;
5450   if (threshold) *threshold = kctx->threshold;
5451   PetscFunctionReturn(PETSC_SUCCESS);
5452 }
5453 
5454 PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5455 {
5456   SNES       snes = (SNES)ctx;
5457   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
5458   PetscReal  rtol = PETSC_CURRENT, stol;
5459 
5460   PetscFunctionBegin;
5461   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
5462   if (!snes->iter) {
5463     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
5464     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
5465   } else {
5466     PetscCheck(kctx->version >= 1 && kctx->version <= 4, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only versions 1-4 are supported: %" PetscInt_FMT, kctx->version);
5467     if (kctx->version == 1) {
5468       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
5469       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
5470       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
5471     } else if (kctx->version == 2) {
5472       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
5473       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
5474       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
5475     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
5476       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
5477       /* safeguard: avoid sharp decrease of rtol */
5478       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
5479       stol = PetscMax(rtol, stol);
5480       rtol = PetscMin(kctx->rtol_0, stol);
5481       /* safeguard: avoid oversolving */
5482       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
5483       stol = PetscMax(rtol, stol);
5484       rtol = PetscMin(kctx->rtol_0, stol);
5485     } else /* if (kctx->version == 4) */ {
5486       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
5487       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
5488       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
5489       PetscReal rk   = ared / pred;
5490       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
5491       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
5492       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
5493       else rtol = kctx->v4_m2 * kctx->rtol_last;
5494 
5495       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;
5496       kctx->rtol_last_2 = kctx->rtol_last;
5497       kctx->rk_last_2   = kctx->rk_last;
5498       kctx->rk_last     = rk;
5499     }
5500   }
5501   /* safeguard: avoid rtol greater than rtol_max */
5502   rtol = PetscMin(rtol, kctx->rtol_max);
5503   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT));
5504   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
5505   PetscFunctionReturn(PETSC_SUCCESS);
5506 }
5507 
5508 PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5509 {
5510   SNES       snes = (SNES)ctx;
5511   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
5512   PCSide     pcside;
5513   Vec        lres;
5514 
5515   PetscFunctionBegin;
5516   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
5517   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
5518   kctx->norm_last = snes->norm;
5519   if (kctx->version == 1 || kctx->version == 4) {
5520     PC        pc;
5521     PetscBool getRes;
5522 
5523     PetscCall(KSPGetPC(ksp, &pc));
5524     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
5525     if (!getRes) {
5526       KSPNormType normtype;
5527 
5528       PetscCall(KSPGetNormType(ksp, &normtype));
5529       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
5530     }
5531     PetscCall(KSPGetPCSide(ksp, &pcside));
5532     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
5533       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
5534     } else {
5535       /* KSP residual is preconditioned residual */
5536       /* compute true linear residual norm */
5537       Mat J;
5538       PetscCall(KSPGetOperators(ksp, &J, NULL));
5539       PetscCall(VecDuplicate(b, &lres));
5540       PetscCall(MatMult(J, x, lres));
5541       PetscCall(VecAYPX(lres, -1.0, b));
5542       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
5543       PetscCall(VecDestroy(&lres));
5544     }
5545   }
5546   PetscFunctionReturn(PETSC_SUCCESS);
5547 }
5548 
5549 /*@
5550   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5551 
5552   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5553 
5554   Input Parameter:
5555 . snes - the `SNES` context
5556 
5557   Output Parameter:
5558 . ksp - the `KSP` context
5559 
5560   Level: beginner
5561 
5562   Notes:
5563   The user can then directly manipulate the `KSP` context to set various
5564   options, etc.  Likewise, the user can then extract and manipulate the
5565   `PC` contexts as well.
5566 
5567   Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5568 
5569 .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5570 @*/
5571 PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5572 {
5573   PetscFunctionBegin;
5574   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5575   PetscAssertPointer(ksp, 2);
5576 
5577   if (!snes->ksp) {
5578     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
5579     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5580 
5581     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
5582     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5583 
5584     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
5585     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5586   }
5587   *ksp = snes->ksp;
5588   PetscFunctionReturn(PETSC_SUCCESS);
5589 }
5590 
5591 #include <petsc/private/dmimpl.h>
5592 /*@
5593   SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
5594 
5595   Logically Collective
5596 
5597   Input Parameters:
5598 + snes - the nonlinear solver context
5599 - dm   - the `DM`, cannot be `NULL`
5600 
5601   Level: intermediate
5602 
5603   Note:
5604   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5605   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5606   problems using the same function space.
5607 
5608 .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
5609 @*/
5610 PetscErrorCode SNESSetDM(SNES snes, DM dm)
5611 {
5612   KSP    ksp;
5613   DMSNES sdm;
5614 
5615   PetscFunctionBegin;
5616   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5617   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
5618   PetscCall(PetscObjectReference((PetscObject)dm));
5619   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
5620     if (snes->dm->dmsnes && !dm->dmsnes) {
5621       PetscCall(DMCopyDMSNES(snes->dm, dm));
5622       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5623       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
5624     }
5625     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
5626     PetscCall(DMDestroy(&snes->dm));
5627   }
5628   snes->dm     = dm;
5629   snes->dmAuto = PETSC_FALSE;
5630 
5631   PetscCall(SNESGetKSP(snes, &ksp));
5632   PetscCall(KSPSetDM(ksp, dm));
5633   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5634   if (snes->npc) {
5635     PetscCall(SNESSetDM(snes->npc, snes->dm));
5636     PetscCall(SNESSetNPCSide(snes, snes->npcside));
5637   }
5638   PetscFunctionReturn(PETSC_SUCCESS);
5639 }
5640 
5641 /*@
5642   SNESGetDM - Gets the `DM` that may be used by some solvers/preconditioners
5643 
5644   Not Collective but dm obtained is parallel on snes
5645 
5646   Input Parameter:
5647 . snes - the `SNES` context
5648 
5649   Output Parameter:
5650 . dm - the `DM`
5651 
5652   Level: intermediate
5653 
5654 .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
5655 @*/
5656 PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5657 {
5658   PetscFunctionBegin;
5659   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5660   if (!snes->dm) {
5661     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5662     snes->dmAuto = PETSC_TRUE;
5663   }
5664   *dm = snes->dm;
5665   PetscFunctionReturn(PETSC_SUCCESS);
5666 }
5667 
5668 /*@
5669   SNESSetNPC - Sets the nonlinear preconditioner to be used.
5670 
5671   Collective
5672 
5673   Input Parameters:
5674 + snes - iterative context obtained from `SNESCreate()`
5675 - npc  - the nonlinear preconditioner object
5676 
5677   Level: developer
5678 
5679   Notes:
5680   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
5681   to configure it using the API).
5682 
5683   Only some `SNESType` can use a nonlinear preconditioner
5684 
5685 .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
5686 @*/
5687 PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5688 {
5689   PetscFunctionBegin;
5690   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5691   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5692   PetscCheckSameComm(snes, 1, npc, 2);
5693   PetscCall(PetscObjectReference((PetscObject)npc));
5694   PetscCall(SNESDestroy(&snes->npc));
5695   snes->npc = npc;
5696   PetscFunctionReturn(PETSC_SUCCESS);
5697 }
5698 
5699 /*@
5700   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
5701 
5702   Not Collective; but any changes to the obtained the npc object must be applied collectively
5703 
5704   Input Parameter:
5705 . snes - iterative context obtained from `SNESCreate()`
5706 
5707   Output Parameter:
5708 . pc - preconditioner context
5709 
5710   Options Database Key:
5711 . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5712 
5713   Level: developer
5714 
5715   Notes:
5716   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5717 
5718   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5719   `SNES`
5720 
5721 .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
5722 @*/
5723 PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5724 {
5725   const char *optionsprefix;
5726 
5727   PetscFunctionBegin;
5728   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5729   PetscAssertPointer(pc, 2);
5730   if (!snes->npc) {
5731     void *ctx;
5732 
5733     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
5734     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
5735     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
5736     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
5737     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5738     if (snes->ops->usercompute) {
5739       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy));
5740     } else {
5741       PetscCall(SNESGetApplicationContext(snes, &ctx));
5742       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5743     }
5744     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
5745   }
5746   *pc = snes->npc;
5747   PetscFunctionReturn(PETSC_SUCCESS);
5748 }
5749 
5750 /*@
5751   SNESHasNPC - Returns whether a nonlinear preconditioner exists
5752 
5753   Not Collective
5754 
5755   Input Parameter:
5756 . snes - iterative context obtained from `SNESCreate()`
5757 
5758   Output Parameter:
5759 . has_npc - whether the `SNES` has a nonlinear preconditioner or not
5760 
5761   Level: developer
5762 
5763 .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
5764 @*/
5765 PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5766 {
5767   PetscFunctionBegin;
5768   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5769   PetscAssertPointer(has_npc, 2);
5770   *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE;
5771   PetscFunctionReturn(PETSC_SUCCESS);
5772 }
5773 
5774 /*@
5775   SNESSetNPCSide - Sets the nonlinear preconditioning side.
5776 
5777   Logically Collective
5778 
5779   Input Parameter:
5780 . snes - iterative context obtained from `SNESCreate()`
5781 
5782   Output Parameter:
5783 . side - the preconditioning side, where side is one of
5784 .vb
5785       PC_LEFT - left preconditioning
5786       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5787 .ve
5788 
5789   Options Database Key:
5790 . -snes_npc_side <right,left> - nonlinear preconditioner side
5791 
5792   Level: intermediate
5793 
5794   Note:
5795   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
5796 
5797 .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5798 @*/
5799 PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5800 {
5801   PetscFunctionBegin;
5802   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5803   PetscValidLogicalCollectiveEnum(snes, side, 2);
5804   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
5805   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5806   snes->npcside = side;
5807   PetscFunctionReturn(PETSC_SUCCESS);
5808 }
5809 
5810 /*@
5811   SNESGetNPCSide - Gets the preconditioning side.
5812 
5813   Not Collective
5814 
5815   Input Parameter:
5816 . snes - iterative context obtained from `SNESCreate()`
5817 
5818   Output Parameter:
5819 . side - the preconditioning side, where side is one of
5820 .vb
5821       `PC_LEFT` - left preconditioning
5822       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5823 .ve
5824 
5825   Level: intermediate
5826 
5827 .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5828 @*/
5829 PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5830 {
5831   PetscFunctionBegin;
5832   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5833   PetscAssertPointer(side, 2);
5834   *side = snes->npcside;
5835   PetscFunctionReturn(PETSC_SUCCESS);
5836 }
5837 
5838 /*@
5839   SNESSetLineSearch - Sets the linesearch to be used for `SNES`
5840 
5841   Collective
5842 
5843   Input Parameters:
5844 + snes       - iterative context obtained from `SNESCreate()`
5845 - linesearch - the linesearch object
5846 
5847   Level: developer
5848 
5849   Note:
5850   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
5851   to configure it using the API).
5852 
5853 .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
5854 @*/
5855 PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5856 {
5857   PetscFunctionBegin;
5858   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5859   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
5860   PetscCheckSameComm(snes, 1, linesearch, 2);
5861   PetscCall(PetscObjectReference((PetscObject)linesearch));
5862   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5863 
5864   snes->linesearch = linesearch;
5865   PetscFunctionReturn(PETSC_SUCCESS);
5866 }
5867 
5868 /*@
5869   SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()`
5870   or creates a default line search instance associated with the `SNES` and returns it.
5871 
5872   Not Collective
5873 
5874   Input Parameter:
5875 . snes - iterative context obtained from `SNESCreate()`
5876 
5877   Output Parameter:
5878 . linesearch - linesearch context
5879 
5880   Level: beginner
5881 
5882 .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
5883 @*/
5884 PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5885 {
5886   const char *optionsprefix;
5887 
5888   PetscFunctionBegin;
5889   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5890   PetscAssertPointer(linesearch, 2);
5891   if (!snes->linesearch) {
5892     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
5893     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
5894     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
5895     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
5896     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
5897   }
5898   *linesearch = snes->linesearch;
5899   PetscFunctionReturn(PETSC_SUCCESS);
5900 }
5901