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