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