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