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