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