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