xref: /petsc/src/snes/interface/snes.c (revision 3b9d9b6507112a6fc8ea0705b2a0df60b27b6bb4)
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()`, `SNESMonitorSet()`, `SNESMonitorGet()`
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   PetscInt  i;
4271   PetscBool identical;
4272 
4273   PetscFunctionBegin;
4274   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4275   for (i = 0; i < snes->numbermonitors; i++) {
4276     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
4277     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4278   }
4279   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
4280   snes->monitor[snes->numbermonitors]          = f;
4281   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4282   snes->monitorcontext[snes->numbermonitors++] = mctx;
4283   PetscFunctionReturn(PETSC_SUCCESS);
4284 }
4285 
4286 /*@
4287   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
4288 
4289   Logically Collective
4290 
4291   Input Parameter:
4292 . snes - the `SNES` context
4293 
4294   Options Database Key:
4295 . -snes_monitor_cancel - cancels all monitors that have been hardwired
4296                          into a code by calls to `SNESMonitorSet()`, but does not cancel those
4297                          set via the options database
4298 
4299   Level: intermediate
4300 
4301   Note:
4302   There is no way to clear one specific monitor from a `SNES` object.
4303 
4304 .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
4305 @*/
4306 PetscErrorCode SNESMonitorCancel(SNES snes)
4307 {
4308   PetscInt i;
4309 
4310   PetscFunctionBegin;
4311   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4312   for (i = 0; i < snes->numbermonitors; i++) {
4313     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4314   }
4315   snes->numbermonitors = 0;
4316   PetscFunctionReturn(PETSC_SUCCESS);
4317 }
4318 
4319 /*MC
4320     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4321 
4322      Synopsis:
4323      #include <petscsnes.h>
4324      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4325 
4326      Collective
4327 
4328     Input Parameters:
4329 +    snes - the `SNES` context
4330 .    it - current iteration (0 is the first and is before any Newton step)
4331 .    xnorm - 2-norm of current iterate
4332 .    gnorm - 2-norm of current step
4333 .    f - 2-norm of function
4334 -    cctx - [optional] convergence context
4335 
4336     Output Parameter:
4337 .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4338 
4339    Level: intermediate
4340 
4341 .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
4342 M*/
4343 
4344 /*@C
4345   SNESSetConvergenceTest - Sets the function that is to be used
4346   to test for convergence of the nonlinear iterative solution.
4347 
4348   Logically Collective
4349 
4350   Input Parameters:
4351 + snes                        - the `SNES` context
4352 . SNESConvergenceTestFunction - routine to test for convergence
4353 . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4354 - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
4355 
4356   Level: advanced
4357 
4358 .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
4359 @*/
4360 PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4361 {
4362   PetscFunctionBegin;
4363   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4364   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
4365   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4366   snes->ops->converged        = SNESConvergenceTestFunction;
4367   snes->ops->convergeddestroy = destroy;
4368   snes->cnvP                  = cctx;
4369   PetscFunctionReturn(PETSC_SUCCESS);
4370 }
4371 
4372 /*@
4373   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation
4374 
4375   Not Collective
4376 
4377   Input Parameter:
4378 . snes - the `SNES` context
4379 
4380   Output Parameter:
4381 . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4382 
4383   Options Database Key:
4384 . -snes_converged_reason - prints the reason to standard out
4385 
4386   Level: intermediate
4387 
4388   Note:
4389   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4390 
4391 .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4392 @*/
4393 PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4394 {
4395   PetscFunctionBegin;
4396   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4397   PetscAssertPointer(reason, 2);
4398   *reason = snes->reason;
4399   PetscFunctionReturn(PETSC_SUCCESS);
4400 }
4401 
4402 /*@C
4403   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4404 
4405   Not Collective
4406 
4407   Input Parameter:
4408 . snes - the `SNES` context
4409 
4410   Output Parameter:
4411 . strreason - a human readable string that describes `SNES` converged reason
4412 
4413   Level: beginner
4414 
4415 .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4416 @*/
4417 PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4418 {
4419   PetscFunctionBegin;
4420   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4421   PetscAssertPointer(strreason, 2);
4422   *strreason = SNESConvergedReasons[snes->reason];
4423   PetscFunctionReturn(PETSC_SUCCESS);
4424 }
4425 
4426 /*@
4427   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
4428 
4429   Not Collective
4430 
4431   Input Parameters:
4432 + snes   - the `SNES` context
4433 - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
4434             manual pages for the individual convergence tests for complete lists
4435 
4436   Level: developer
4437 
4438   Developer Note:
4439   Called inside the various `SNESSolve()` implementations
4440 
4441 .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
4442 @*/
4443 PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4444 {
4445   PetscFunctionBegin;
4446   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4447   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
4448   snes->reason = reason;
4449   PetscFunctionReturn(PETSC_SUCCESS);
4450 }
4451 
4452 /*@
4453   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4454 
4455   Logically Collective
4456 
4457   Input Parameters:
4458 + snes  - iterative context obtained from `SNESCreate()`
4459 . a     - array to hold history, this array will contain the function norms computed at each step
4460 . its   - integer array holds the number of linear iterations for each solve.
4461 . na    - size of `a` and `its`
4462 - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4463           else it continues storing new values for new nonlinear solves after the old ones
4464 
4465   Level: intermediate
4466 
4467   Notes:
4468   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` (or, deprecated, `PETSC_DEFAULT`) then a
4469   default array of length 1,000 is allocated.
4470 
4471   This routine is useful, e.g., when running a code for purposes
4472   of accurate performance monitoring, when no I/O should be done
4473   during the section of code that is being timed.
4474 
4475   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4476 
4477 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4478 @*/
4479 PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4480 {
4481   PetscFunctionBegin;
4482   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4483   if (a) PetscAssertPointer(a, 2);
4484   if (its) PetscAssertPointer(its, 3);
4485   if (!a) {
4486     if (na == PETSC_DECIDE) na = 1000;
4487     PetscCall(PetscCalloc2(na, &a, na, &its));
4488     snes->conv_hist_alloc = PETSC_TRUE;
4489   }
4490   snes->conv_hist       = a;
4491   snes->conv_hist_its   = its;
4492   snes->conv_hist_max   = (size_t)na;
4493   snes->conv_hist_len   = 0;
4494   snes->conv_hist_reset = reset;
4495   PetscFunctionReturn(PETSC_SUCCESS);
4496 }
4497 
4498 #if defined(PETSC_HAVE_MATLAB)
4499   #include <engine.h> /* MATLAB include file */
4500   #include <mex.h>    /* MATLAB include file */
4501 
4502 PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4503 {
4504   mxArray   *mat;
4505   PetscInt   i;
4506   PetscReal *ar;
4507 
4508   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4509   ar  = (PetscReal *)mxGetData(mat);
4510   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
4511   return mat;
4512 }
4513 #endif
4514 
4515 /*@C
4516   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4517 
4518   Not Collective
4519 
4520   Input Parameter:
4521 . snes - iterative context obtained from `SNESCreate()`
4522 
4523   Output Parameters:
4524 + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4525 . its - integer array holds the number of linear iterations (or
4526          negative if not converged) for each solve.
4527 - na  - size of `a` and `its`
4528 
4529   Level: intermediate
4530 
4531   Note:
4532   This routine is useful, e.g., when running a code for purposes
4533   of accurate performance monitoring, when no I/O should be done
4534   during the section of code that is being timed.
4535 
4536   Fortran Notes:
4537   Return the arrays with ``SNESRestoreConvergenceHistory()`
4538 
4539   Use the arguments
4540 .vb
4541   PetscReal, pointer :: a(:)
4542   PetscInt, pointer :: its(:)
4543 .ve
4544 
4545 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4546 @*/
4547 PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4548 {
4549   PetscFunctionBegin;
4550   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4551   if (a) *a = snes->conv_hist;
4552   if (its) *its = snes->conv_hist_its;
4553   if (na) *na = (PetscInt)snes->conv_hist_len;
4554   PetscFunctionReturn(PETSC_SUCCESS);
4555 }
4556 
4557 /*@C
4558   SNESSetUpdate - Sets the general-purpose update function called
4559   at the beginning of every iteration of the nonlinear solve. Specifically
4560   it is called just before the Jacobian is "evaluated" and after the function
4561   evaluation.
4562 
4563   Logically Collective
4564 
4565   Input Parameters:
4566 + snes - The nonlinear solver context
4567 - func - The update function; for calling sequence see `SNESUpdateFn`
4568 
4569   Level: advanced
4570 
4571   Notes:
4572   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
4573   to `SNESSetFunction()`, or `SNESSetPicard()`
4574   This is not used by most users, and it is intended to provide a general hook that is run
4575   right before the direction step is computed.
4576 
4577   Users are free to modify the current residual vector,
4578   the current linearization point, or any other vector associated to the specific solver used.
4579   If such modifications take place, it is the user responsibility to update all the relevant
4580   vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like
4581 .vb
4582   PetscErrorCode update(SNES snes, PetscInt iteration)
4583   {
4584     PetscFunctionBeginUser;
4585     if (iteration > 0) {
4586       // update the model parameters here
4587       Vec x,f;
4588       PetscCall(SNESGetSolution(snes,&x));
4589       PetcCall(SNESGetFunction(snes,&f,NULL,NULL));
4590       PetscCall(SNESComputeFunction(snes,x,f));
4591     }
4592     PetscFunctionReturn(PETSC_SUCCESS);
4593   }
4594 .ve
4595 
4596   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.
4597 
4598 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
4599          `SNESMonitorSet()`
4600 @*/
4601 PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4602 {
4603   PetscFunctionBegin;
4604   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4605   snes->ops->update = func;
4606   PetscFunctionReturn(PETSC_SUCCESS);
4607 }
4608 
4609 /*@
4610   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
4611 
4612   Collective
4613 
4614   Input Parameters:
4615 + snes   - iterative context obtained from `SNESCreate()`
4616 - viewer - the viewer to display the reason
4617 
4618   Options Database Keys:
4619 + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4620 - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4621 
4622   Level: beginner
4623 
4624   Note:
4625   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4626   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
4627 
4628 .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4629           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4630           `SNESConvergedReasonViewFromOptions()`,
4631           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
4632 @*/
4633 PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4634 {
4635   PetscViewerFormat format;
4636   PetscBool         isAscii;
4637 
4638   PetscFunctionBegin;
4639   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
4640   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
4641   if (isAscii) {
4642     PetscCall(PetscViewerGetFormat(viewer, &format));
4643     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
4644     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
4645       DM       dm;
4646       Vec      u;
4647       PetscDS  prob;
4648       PetscInt Nf, f;
4649       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
4650       void    **exactCtx;
4651       PetscReal error;
4652 
4653       PetscCall(SNESGetDM(snes, &dm));
4654       PetscCall(SNESGetSolution(snes, &u));
4655       PetscCall(DMGetDS(dm, &prob));
4656       PetscCall(PetscDSGetNumFields(prob, &Nf));
4657       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
4658       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
4659       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
4660       PetscCall(PetscFree2(exactSol, exactCtx));
4661       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
4662       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
4663     }
4664     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
4665       if (((PetscObject)snes)->prefix) {
4666         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
4667       } else {
4668         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
4669       }
4670     } else if (snes->reason <= 0) {
4671       if (((PetscObject)snes)->prefix) {
4672         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve did not converge due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
4673       } else {
4674         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
4675       }
4676     }
4677     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
4678   }
4679   PetscFunctionReturn(PETSC_SUCCESS);
4680 }
4681 
4682 /*@C
4683   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4684   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4685 
4686   Logically Collective
4687 
4688   Input Parameters:
4689 + snes              - the `SNES` context
4690 . f                 - the `SNESConvergedReason` view function
4691 . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
4692 - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
4693 
4694   Calling sequence of `f`:
4695 + snes - the `SNES` context
4696 - vctx - [optional] context for private data for the function
4697 
4698   Options Database Keys:
4699 + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4700 - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4701                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4702 
4703   Level: intermediate
4704 
4705   Note:
4706   Several different converged reason view routines may be set by calling
4707   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4708   order in which they were set.
4709 
4710 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`,
4711           `PetscCtxDestroyFn`
4712 @*/
4713 PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy)
4714 {
4715   PetscInt  i;
4716   PetscBool identical;
4717 
4718   PetscFunctionBegin;
4719   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4720   for (i = 0; i < snes->numberreasonviews; i++) {
4721     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
4722     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4723   }
4724   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4725   snes->reasonview[snes->numberreasonviews]          = f;
4726   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4727   snes->reasonviewcontext[snes->numberreasonviews++] = vctx;
4728   PetscFunctionReturn(PETSC_SUCCESS);
4729 }
4730 
4731 /*@
4732   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
4733   All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist.
4734 
4735   Collective
4736 
4737   Input Parameter:
4738 . snes - the `SNES` object
4739 
4740   Level: advanced
4741 
4742 .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4743           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
4744 @*/
4745 PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4746 {
4747   static PetscBool incall = PETSC_FALSE;
4748 
4749   PetscFunctionBegin;
4750   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
4751   incall = PETSC_TRUE;
4752 
4753   /* All user-provided viewers are called first, if they exist. */
4754   for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4755 
4756   /* Call PETSc default routine if users ask for it */
4757   if (snes->convergedreasonviewer) {
4758     PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
4759     PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
4760     PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
4761   }
4762   incall = PETSC_FALSE;
4763   PetscFunctionReturn(PETSC_SUCCESS);
4764 }
4765 
4766 /*@
4767   SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object
4768 
4769   Collective
4770 
4771   Input Parameters:
4772 + snes - the `SNES` context
4773 . b    - the constant part of the equation $F(x) = b$, or `NULL` to use zero.
4774 - x    - the solution vector.
4775 
4776   Level: beginner
4777 
4778   Note:
4779   The user should initialize the vector, `x`, with the initial guess
4780   for the nonlinear solve prior to calling `SNESSolve()` .
4781 
4782 .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4783           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4784           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
4785 @*/
4786 PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4787 {
4788   PetscBool flg;
4789   PetscInt  grid;
4790   Vec       xcreated = NULL;
4791   DM        dm;
4792 
4793   PetscFunctionBegin;
4794   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4795   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4796   if (x) PetscCheckSameComm(snes, 1, x, 3);
4797   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4798   if (b) PetscCheckSameComm(snes, 1, b, 2);
4799 
4800   /* High level operations using the nonlinear solver */
4801   {
4802     PetscViewer       viewer;
4803     PetscViewerFormat format;
4804     PetscInt          num;
4805     PetscBool         flg;
4806     static PetscBool  incall = PETSC_FALSE;
4807 
4808     if (!incall) {
4809       /* Estimate the convergence rate of the discretization */
4810       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
4811       if (flg) {
4812         PetscConvEst conv;
4813         DM           dm;
4814         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
4815         PetscInt     Nf;
4816 
4817         incall = PETSC_TRUE;
4818         PetscCall(SNESGetDM(snes, &dm));
4819         PetscCall(DMGetNumFields(dm, &Nf));
4820         PetscCall(PetscCalloc1(Nf, &alpha));
4821         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
4822         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
4823         PetscCall(PetscConvEstSetFromOptions(conv));
4824         PetscCall(PetscConvEstSetUp(conv));
4825         PetscCall(PetscConvEstGetConvRate(conv, alpha));
4826         PetscCall(PetscViewerPushFormat(viewer, format));
4827         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
4828         PetscCall(PetscViewerPopFormat(viewer));
4829         PetscCall(PetscViewerDestroy(&viewer));
4830         PetscCall(PetscConvEstDestroy(&conv));
4831         PetscCall(PetscFree(alpha));
4832         incall = PETSC_FALSE;
4833       }
4834       /* Adaptively refine the initial grid */
4835       num = 1;
4836       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
4837       if (flg) {
4838         DMAdaptor adaptor;
4839 
4840         incall = PETSC_TRUE;
4841         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4842         PetscCall(DMAdaptorSetSolver(adaptor, snes));
4843         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
4844         PetscCall(DMAdaptorSetFromOptions(adaptor));
4845         PetscCall(DMAdaptorSetUp(adaptor));
4846         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
4847         PetscCall(DMAdaptorDestroy(&adaptor));
4848         incall = PETSC_FALSE;
4849       }
4850       /* Use grid sequencing to adapt */
4851       num = 0;
4852       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
4853       if (num) {
4854         DMAdaptor   adaptor;
4855         const char *prefix;
4856 
4857         incall = PETSC_TRUE;
4858         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4859         PetscCall(SNESGetOptionsPrefix(snes, &prefix));
4860         PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix));
4861         PetscCall(DMAdaptorSetSolver(adaptor, snes));
4862         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
4863         PetscCall(DMAdaptorSetFromOptions(adaptor));
4864         PetscCall(DMAdaptorSetUp(adaptor));
4865         PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
4866         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
4867         PetscCall(DMAdaptorDestroy(&adaptor));
4868         incall = PETSC_FALSE;
4869       }
4870     }
4871   }
4872   if (!x) x = snes->vec_sol;
4873   if (!x) {
4874     PetscCall(SNESGetDM(snes, &dm));
4875     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4876     x = xcreated;
4877   }
4878   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4879 
4880   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4881   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
4882     /* set solution vector */
4883     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
4884     PetscCall(VecDestroy(&snes->vec_sol));
4885     snes->vec_sol = x;
4886     PetscCall(SNESGetDM(snes, &dm));
4887 
4888     /* set affine vector if provided */
4889     if (b) PetscCall(PetscObjectReference((PetscObject)b));
4890     PetscCall(VecDestroy(&snes->vec_rhs));
4891     snes->vec_rhs = b;
4892 
4893     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");
4894     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4895     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4896     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
4897     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
4898     PetscCall(SNESSetUp(snes));
4899 
4900     if (!grid) {
4901       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4902     }
4903 
4904     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
4905     PetscCall(SNESResetCounters(snes));
4906     snes->reason = SNES_CONVERGED_ITERATING;
4907     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4908     PetscUseTypeMethod(snes, solve);
4909     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
4910     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4911     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
4912 
4913     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
4914     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
4915 
4916     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
4917     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4918     /* Call converged reason views. This may involve user-provided viewers as well */
4919     PetscCall(SNESConvergedReasonViewFromOptions(snes));
4920 
4921     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
4922     if (snes->reason < 0) break;
4923     if (grid < snes->gridsequence) {
4924       DM  fine;
4925       Vec xnew;
4926       Mat interp;
4927 
4928       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
4929       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
4930       PetscCall(DMGetCoordinatesLocalSetUp(fine));
4931       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
4932       PetscCall(DMCreateGlobalVector(fine, &xnew));
4933       PetscCall(MatInterpolate(interp, x, xnew));
4934       PetscCall(DMInterpolate(snes->dm, interp, fine));
4935       PetscCall(MatDestroy(&interp));
4936       x = xnew;
4937 
4938       PetscCall(SNESReset(snes));
4939       PetscCall(SNESSetDM(snes, fine));
4940       PetscCall(SNESResetFromOptions(snes));
4941       PetscCall(DMDestroy(&fine));
4942       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4943     }
4944   }
4945   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
4946   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
4947   PetscCall(DMMonitor(snes->dm));
4948   PetscCall(SNESMonitorPauseFinal_Internal(snes));
4949 
4950   PetscCall(VecDestroy(&xcreated));
4951   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
4952   PetscFunctionReturn(PETSC_SUCCESS);
4953 }
4954 
4955 /* --------- Internal routines for SNES Package --------- */
4956 
4957 /*@
4958   SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES`
4959 
4960   Collective
4961 
4962   Input Parameters:
4963 + snes - the `SNES` context
4964 - type - a known method
4965 
4966   Options Database Key:
4967 . -snes_type <type> - Sets the method; use -help for a list
4968    of available methods (for instance, newtonls or newtontr)
4969 
4970   Level: intermediate
4971 
4972   Notes:
4973   See `SNESType` for available methods (for instance)
4974 +    `SNESNEWTONLS` - Newton's method with line search
4975   (systems of nonlinear equations)
4976 -    `SNESNEWTONTR` - Newton's method with trust region
4977   (systems of nonlinear equations)
4978 
4979   Normally, it is best to use the `SNESSetFromOptions()` command and then
4980   set the `SNES` solver type from the options database rather than by using
4981   this routine.  Using the options database provides the user with
4982   maximum flexibility in evaluating the many nonlinear solvers.
4983   The `SNESSetType()` routine is provided for those situations where it
4984   is necessary to set the nonlinear solver independently of the command
4985   line or options database.  This might be the case, for example, when
4986   the choice of solver changes during the execution of the program,
4987   and the user's application is taking responsibility for choosing the
4988   appropriate method.
4989 
4990   Developer Note:
4991   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4992   the constructor in that list and calls it to create the specific object.
4993 
4994 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
4995 @*/
4996 PetscErrorCode SNESSetType(SNES snes, SNESType type)
4997 {
4998   PetscBool match;
4999   PetscErrorCode (*r)(SNES);
5000 
5001   PetscFunctionBegin;
5002   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5003   PetscAssertPointer(type, 2);
5004 
5005   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
5006   if (match) PetscFunctionReturn(PETSC_SUCCESS);
5007 
5008   PetscCall(PetscFunctionListFind(SNESList, type, &r));
5009   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
5010   /* Destroy the previous private SNES context */
5011   PetscTryTypeMethod(snes, destroy);
5012   /* Reinitialize type-specific function pointers in SNESOps structure */
5013   snes->ops->reset          = NULL;
5014   snes->ops->setup          = NULL;
5015   snes->ops->solve          = NULL;
5016   snes->ops->view           = NULL;
5017   snes->ops->setfromoptions = NULL;
5018   snes->ops->destroy        = NULL;
5019 
5020   /* It may happen the user has customized the line search before calling SNESSetType */
5021   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5022 
5023   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
5024   snes->setupcalled = PETSC_FALSE;
5025 
5026   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
5027   PetscCall((*r)(snes));
5028   PetscFunctionReturn(PETSC_SUCCESS);
5029 }
5030 
5031 /*@
5032   SNESGetType - Gets the `SNES` method type and name (as a string).
5033 
5034   Not Collective
5035 
5036   Input Parameter:
5037 . snes - nonlinear solver context
5038 
5039   Output Parameter:
5040 . type - `SNES` method (a character string)
5041 
5042   Level: intermediate
5043 
5044 .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
5045 @*/
5046 PetscErrorCode SNESGetType(SNES snes, SNESType *type)
5047 {
5048   PetscFunctionBegin;
5049   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5050   PetscAssertPointer(type, 2);
5051   *type = ((PetscObject)snes)->type_name;
5052   PetscFunctionReturn(PETSC_SUCCESS);
5053 }
5054 
5055 /*@
5056   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
5057 
5058   Logically Collective
5059 
5060   Input Parameters:
5061 + snes - the `SNES` context obtained from `SNESCreate()`
5062 - u    - the solution vector
5063 
5064   Level: beginner
5065 
5066 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
5067 @*/
5068 PetscErrorCode SNESSetSolution(SNES snes, Vec u)
5069 {
5070   DM dm;
5071 
5072   PetscFunctionBegin;
5073   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5074   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
5075   PetscCall(PetscObjectReference((PetscObject)u));
5076   PetscCall(VecDestroy(&snes->vec_sol));
5077 
5078   snes->vec_sol = u;
5079 
5080   PetscCall(SNESGetDM(snes, &dm));
5081   PetscCall(DMShellSetGlobalVector(dm, u));
5082   PetscFunctionReturn(PETSC_SUCCESS);
5083 }
5084 
5085 /*@
5086   SNESGetSolution - Returns the vector where the approximate solution is
5087   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
5088 
5089   Not Collective, but `x` is parallel if `snes` is parallel
5090 
5091   Input Parameter:
5092 . snes - the `SNES` context
5093 
5094   Output Parameter:
5095 . x - the solution
5096 
5097   Level: intermediate
5098 
5099 .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
5100 @*/
5101 PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
5102 {
5103   PetscFunctionBegin;
5104   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5105   PetscAssertPointer(x, 2);
5106   *x = snes->vec_sol;
5107   PetscFunctionReturn(PETSC_SUCCESS);
5108 }
5109 
5110 /*@
5111   SNESGetSolutionUpdate - Returns the vector where the solution update is
5112   stored.
5113 
5114   Not Collective, but `x` is parallel if `snes` is parallel
5115 
5116   Input Parameter:
5117 . snes - the `SNES` context
5118 
5119   Output Parameter:
5120 . x - the solution update
5121 
5122   Level: advanced
5123 
5124 .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
5125 @*/
5126 PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
5127 {
5128   PetscFunctionBegin;
5129   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5130   PetscAssertPointer(x, 2);
5131   *x = snes->vec_sol_update;
5132   PetscFunctionReturn(PETSC_SUCCESS);
5133 }
5134 
5135 /*@C
5136   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
5137 
5138   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
5139 
5140   Input Parameter:
5141 . snes - the `SNES` context
5142 
5143   Output Parameters:
5144 + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
5145 . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
5146 - ctx - the function context (or `NULL` if you don't want it)
5147 
5148   Level: advanced
5149 
5150   Note:
5151   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
5152 
5153 .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
5154 @*/
5155 PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
5156 {
5157   DM dm;
5158 
5159   PetscFunctionBegin;
5160   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5161   if (r) {
5162     if (!snes->vec_func) {
5163       if (snes->vec_rhs) {
5164         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5165       } else if (snes->vec_sol) {
5166         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5167       } else if (snes->dm) {
5168         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5169       }
5170     }
5171     *r = snes->vec_func;
5172   }
5173   PetscCall(SNESGetDM(snes, &dm));
5174   PetscCall(DMSNESGetFunction(dm, f, ctx));
5175   PetscFunctionReturn(PETSC_SUCCESS);
5176 }
5177 
5178 /*@C
5179   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5180 
5181   Input Parameter:
5182 . snes - the `SNES` context
5183 
5184   Output Parameters:
5185 + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5186 - ctx - the function context (or `NULL`)
5187 
5188   Level: advanced
5189 
5190 .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5191 @*/
5192 PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5193 {
5194   DM dm;
5195 
5196   PetscFunctionBegin;
5197   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5198   PetscCall(SNESGetDM(snes, &dm));
5199   PetscCall(DMSNESGetNGS(dm, f, ctx));
5200   PetscFunctionReturn(PETSC_SUCCESS);
5201 }
5202 
5203 /*@
5204   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5205   `SNES` options in the database.
5206 
5207   Logically Collective
5208 
5209   Input Parameters:
5210 + snes   - the `SNES` context
5211 - prefix - the prefix to prepend to all option names
5212 
5213   Level: advanced
5214 
5215   Note:
5216   A hyphen (-) must NOT be given at the beginning of the prefix name.
5217   The first character of all runtime options is AUTOMATICALLY the hyphen.
5218 
5219 .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
5220 @*/
5221 PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5222 {
5223   PetscFunctionBegin;
5224   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5225   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
5226   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
5227   if (snes->linesearch) {
5228     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
5229     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
5230   }
5231   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
5232   PetscFunctionReturn(PETSC_SUCCESS);
5233 }
5234 
5235 /*@
5236   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5237   `SNES` options in the database.
5238 
5239   Logically Collective
5240 
5241   Input Parameters:
5242 + snes   - the `SNES` context
5243 - prefix - the prefix to prepend to all option names
5244 
5245   Level: advanced
5246 
5247   Note:
5248   A hyphen (-) must NOT be given at the beginning of the prefix name.
5249   The first character of all runtime options is AUTOMATICALLY the hyphen.
5250 
5251 .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
5252 @*/
5253 PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5254 {
5255   PetscFunctionBegin;
5256   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5257   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
5258   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
5259   if (snes->linesearch) {
5260     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
5261     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
5262   }
5263   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
5264   PetscFunctionReturn(PETSC_SUCCESS);
5265 }
5266 
5267 /*@
5268   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5269   `SNES` options in the database.
5270 
5271   Not Collective
5272 
5273   Input Parameter:
5274 . snes - the `SNES` context
5275 
5276   Output Parameter:
5277 . prefix - pointer to the prefix string used
5278 
5279   Level: advanced
5280 
5281 .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
5282 @*/
5283 PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5284 {
5285   PetscFunctionBegin;
5286   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5287   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
5288   PetscFunctionReturn(PETSC_SUCCESS);
5289 }
5290 
5291 /*@C
5292   SNESRegister - Adds a method to the nonlinear solver package.
5293 
5294   Not Collective
5295 
5296   Input Parameters:
5297 + sname    - name of a new user-defined solver
5298 - function - routine to create method context
5299 
5300   Level: advanced
5301 
5302   Note:
5303   `SNESRegister()` may be called multiple times to add several user-defined solvers.
5304 
5305   Example Usage:
5306 .vb
5307    SNESRegister("my_solver", MySolverCreate);
5308 .ve
5309 
5310   Then, your solver can be chosen with the procedural interface via
5311 .vb
5312   SNESSetType(snes, "my_solver")
5313 .ve
5314   or at runtime via the option
5315 .vb
5316   -snes_type my_solver
5317 .ve
5318 
5319 .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
5320 @*/
5321 PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5322 {
5323   PetscFunctionBegin;
5324   PetscCall(SNESInitializePackage());
5325   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
5326   PetscFunctionReturn(PETSC_SUCCESS);
5327 }
5328 
5329 PetscErrorCode SNESTestLocalMin(SNES snes)
5330 {
5331   PetscInt    N, i, j;
5332   Vec         u, uh, fh;
5333   PetscScalar value;
5334   PetscReal   norm;
5335 
5336   PetscFunctionBegin;
5337   PetscCall(SNESGetSolution(snes, &u));
5338   PetscCall(VecDuplicate(u, &uh));
5339   PetscCall(VecDuplicate(u, &fh));
5340 
5341   /* currently only works for sequential */
5342   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
5343   PetscCall(VecGetSize(u, &N));
5344   for (i = 0; i < N; i++) {
5345     PetscCall(VecCopy(u, uh));
5346     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5347     for (j = -10; j < 11; j++) {
5348       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
5349       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5350       PetscCall(SNESComputeFunction(snes, uh, fh));
5351       PetscCall(VecNorm(fh, NORM_2, &norm));
5352       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5353       value = -value;
5354       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5355     }
5356   }
5357   PetscCall(VecDestroy(&uh));
5358   PetscCall(VecDestroy(&fh));
5359   PetscFunctionReturn(PETSC_SUCCESS);
5360 }
5361 
5362 /*@
5363   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
5364   computing relative tolerance for linear solvers within an inexact
5365   Newton method.
5366 
5367   Logically Collective
5368 
5369   Input Parameters:
5370 + snes - `SNES` context
5371 - flag - `PETSC_TRUE` or `PETSC_FALSE`
5372 
5373   Options Database Keys:
5374 + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
5375 . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
5376 . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
5377 . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
5378 . -snes_ksp_ew_gamma <gamma>         - Sets gamma
5379 . -snes_ksp_ew_alpha <alpha>         - Sets alpha
5380 . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
5381 - -snes_ksp_ew_threshold <threshold> - Sets threshold
5382 
5383   Level: advanced
5384 
5385   Note:
5386   The default is to use a constant relative tolerance for
5387   the inner linear solvers.  Alternatively, one can use the
5388   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
5389   is reset at each Newton iteration according progress of the nonlinear
5390   solver.
5391 
5392 .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
5393 @*/
5394 PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5395 {
5396   PetscFunctionBegin;
5397   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5398   PetscValidLogicalCollectiveBool(snes, flag, 2);
5399   snes->ksp_ewconv = flag;
5400   PetscFunctionReturn(PETSC_SUCCESS);
5401 }
5402 
5403 /*@
5404   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
5405   for computing relative tolerance for linear solvers within an
5406   inexact Newton method.
5407 
5408   Not Collective
5409 
5410   Input Parameter:
5411 . snes - `SNES` context
5412 
5413   Output Parameter:
5414 . flag - `PETSC_TRUE` or `PETSC_FALSE`
5415 
5416   Level: advanced
5417 
5418 .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
5419 @*/
5420 PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5421 {
5422   PetscFunctionBegin;
5423   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5424   PetscAssertPointer(flag, 2);
5425   *flag = snes->ksp_ewconv;
5426   PetscFunctionReturn(PETSC_SUCCESS);
5427 }
5428 
5429 /*@
5430   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
5431   convergence criteria for the linear solvers within an inexact
5432   Newton method.
5433 
5434   Logically Collective
5435 
5436   Input Parameters:
5437 + snes      - `SNES` context
5438 . version   - version 1, 2 (default is 2), 3 or 4
5439 . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
5440 . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5441 . gamma     - multiplicative factor for version 2 rtol computation
5442              (0 <= gamma2 <= 1)
5443 . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
5444 . alpha2    - power for safeguard
5445 - threshold - threshold for imposing safeguard (0 < threshold < 1)
5446 
5447   Level: advanced
5448 
5449   Notes:
5450   Version 3 was contributed by Luis Chacon, June 2006.
5451 
5452   Use `PETSC_CURRENT` to retain the default for any of the parameters.
5453 
5454 .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
5455 @*/
5456 PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5457 {
5458   SNESKSPEW *kctx;
5459 
5460   PetscFunctionBegin;
5461   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5462   kctx = (SNESKSPEW *)snes->kspconvctx;
5463   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5464   PetscValidLogicalCollectiveInt(snes, version, 2);
5465   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5466   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5467   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5468   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5469   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5470   PetscValidLogicalCollectiveReal(snes, threshold, 8);
5471 
5472   if (version != PETSC_CURRENT) kctx->version = version;
5473   if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0;
5474   if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max;
5475   if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma;
5476   if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha;
5477   if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2;
5478   if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold;
5479 
5480   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);
5481   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);
5482   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);
5483   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);
5484   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);
5485   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);
5486   PetscFunctionReturn(PETSC_SUCCESS);
5487 }
5488 
5489 /*@
5490   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
5491   convergence criteria for the linear solvers within an inexact
5492   Newton method.
5493 
5494   Not Collective
5495 
5496   Input Parameter:
5497 . snes - `SNES` context
5498 
5499   Output Parameters:
5500 + version   - version 1, 2 (default is 2), 3 or 4
5501 . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
5502 . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5503 . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
5504 . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
5505 . alpha2    - power for safeguard
5506 - threshold - threshold for imposing safeguard (0 < threshold < 1)
5507 
5508   Level: advanced
5509 
5510 .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
5511 @*/
5512 PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5513 {
5514   SNESKSPEW *kctx;
5515 
5516   PetscFunctionBegin;
5517   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5518   kctx = (SNESKSPEW *)snes->kspconvctx;
5519   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5520   if (version) *version = kctx->version;
5521   if (rtol_0) *rtol_0 = kctx->rtol_0;
5522   if (rtol_max) *rtol_max = kctx->rtol_max;
5523   if (gamma) *gamma = kctx->gamma;
5524   if (alpha) *alpha = kctx->alpha;
5525   if (alpha2) *alpha2 = kctx->alpha2;
5526   if (threshold) *threshold = kctx->threshold;
5527   PetscFunctionReturn(PETSC_SUCCESS);
5528 }
5529 
5530 PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5531 {
5532   SNES       snes = (SNES)ctx;
5533   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
5534   PetscReal  rtol = PETSC_CURRENT, stol;
5535 
5536   PetscFunctionBegin;
5537   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
5538   if (!snes->iter) {
5539     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
5540     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
5541   } else {
5542     PetscCheck(kctx->version >= 1 && kctx->version <= 4, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only versions 1-4 are supported: %" PetscInt_FMT, kctx->version);
5543     if (kctx->version == 1) {
5544       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
5545       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
5546       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
5547     } else if (kctx->version == 2) {
5548       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
5549       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
5550       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
5551     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
5552       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
5553       /* safeguard: avoid sharp decrease of rtol */
5554       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
5555       stol = PetscMax(rtol, stol);
5556       rtol = PetscMin(kctx->rtol_0, stol);
5557       /* safeguard: avoid oversolving */
5558       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
5559       stol = PetscMax(rtol, stol);
5560       rtol = PetscMin(kctx->rtol_0, stol);
5561     } else /* if (kctx->version == 4) */ {
5562       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
5563       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
5564       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
5565       PetscReal rk   = ared / pred;
5566       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
5567       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
5568       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
5569       else rtol = kctx->v4_m2 * kctx->rtol_last;
5570 
5571       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;
5572       kctx->rtol_last_2 = kctx->rtol_last;
5573       kctx->rk_last_2   = kctx->rk_last;
5574       kctx->rk_last     = rk;
5575     }
5576   }
5577   /* safeguard: avoid rtol greater than rtol_max */
5578   rtol = PetscMin(rtol, kctx->rtol_max);
5579   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT));
5580   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
5581   PetscFunctionReturn(PETSC_SUCCESS);
5582 }
5583 
5584 PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5585 {
5586   SNES       snes = (SNES)ctx;
5587   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
5588   PCSide     pcside;
5589   Vec        lres;
5590 
5591   PetscFunctionBegin;
5592   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
5593   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
5594   kctx->norm_last = snes->norm;
5595   if (kctx->version == 1 || kctx->version == 4) {
5596     PC        pc;
5597     PetscBool getRes;
5598 
5599     PetscCall(KSPGetPC(ksp, &pc));
5600     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
5601     if (!getRes) {
5602       KSPNormType normtype;
5603 
5604       PetscCall(KSPGetNormType(ksp, &normtype));
5605       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
5606     }
5607     PetscCall(KSPGetPCSide(ksp, &pcside));
5608     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
5609       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
5610     } else {
5611       /* KSP residual is preconditioned residual */
5612       /* compute true linear residual norm */
5613       Mat J;
5614       PetscCall(KSPGetOperators(ksp, &J, NULL));
5615       PetscCall(VecDuplicate(b, &lres));
5616       PetscCall(MatMult(J, x, lres));
5617       PetscCall(VecAYPX(lres, -1.0, b));
5618       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
5619       PetscCall(VecDestroy(&lres));
5620     }
5621   }
5622   PetscFunctionReturn(PETSC_SUCCESS);
5623 }
5624 
5625 /*@
5626   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5627 
5628   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5629 
5630   Input Parameter:
5631 . snes - the `SNES` context
5632 
5633   Output Parameter:
5634 . ksp - the `KSP` context
5635 
5636   Level: beginner
5637 
5638   Notes:
5639   The user can then directly manipulate the `KSP` context to set various
5640   options, etc.  Likewise, the user can then extract and manipulate the
5641   `PC` contexts as well.
5642 
5643   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.
5644 
5645 .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5646 @*/
5647 PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5648 {
5649   PetscFunctionBegin;
5650   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5651   PetscAssertPointer(ksp, 2);
5652 
5653   if (!snes->ksp) {
5654     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
5655     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5656 
5657     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
5658     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5659 
5660     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
5661     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5662   }
5663   *ksp = snes->ksp;
5664   PetscFunctionReturn(PETSC_SUCCESS);
5665 }
5666 
5667 #include <petsc/private/dmimpl.h>
5668 /*@
5669   SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners
5670 
5671   Logically Collective
5672 
5673   Input Parameters:
5674 + snes - the nonlinear solver context
5675 - dm   - the `DM`, cannot be `NULL`
5676 
5677   Level: intermediate
5678 
5679   Note:
5680   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5681   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5682   problems using the same function space.
5683 
5684 .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
5685 @*/
5686 PetscErrorCode SNESSetDM(SNES snes, DM dm)
5687 {
5688   KSP    ksp;
5689   DMSNES sdm;
5690 
5691   PetscFunctionBegin;
5692   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5693   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
5694   PetscCall(PetscObjectReference((PetscObject)dm));
5695   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
5696     if (snes->dm->dmsnes && !dm->dmsnes) {
5697       PetscCall(DMCopyDMSNES(snes->dm, dm));
5698       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5699       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
5700     }
5701     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
5702     PetscCall(DMDestroy(&snes->dm));
5703   }
5704   snes->dm     = dm;
5705   snes->dmAuto = PETSC_FALSE;
5706 
5707   PetscCall(SNESGetKSP(snes, &ksp));
5708   PetscCall(KSPSetDM(ksp, dm));
5709   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5710   if (snes->npc) {
5711     PetscCall(SNESSetDM(snes->npc, snes->dm));
5712     PetscCall(SNESSetNPCSide(snes, snes->npcside));
5713   }
5714   PetscFunctionReturn(PETSC_SUCCESS);
5715 }
5716 
5717 /*@
5718   SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners
5719 
5720   Not Collective but `dm` obtained is parallel on `snes`
5721 
5722   Input Parameter:
5723 . snes - the `SNES` context
5724 
5725   Output Parameter:
5726 . dm - the `DM`
5727 
5728   Level: intermediate
5729 
5730 .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
5731 @*/
5732 PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5733 {
5734   PetscFunctionBegin;
5735   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5736   if (!snes->dm) {
5737     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5738     snes->dmAuto = PETSC_TRUE;
5739   }
5740   *dm = snes->dm;
5741   PetscFunctionReturn(PETSC_SUCCESS);
5742 }
5743 
5744 /*@
5745   SNESSetNPC - Sets the nonlinear preconditioner to be used.
5746 
5747   Collective
5748 
5749   Input Parameters:
5750 + snes - iterative context obtained from `SNESCreate()`
5751 - npc  - the `SNES` nonlinear preconditioner object
5752 
5753   Options Database Key:
5754 . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5755 
5756   Level: developer
5757 
5758   Notes:
5759   This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API.
5760 
5761   Only some `SNESType` can use a nonlinear preconditioner
5762 
5763 .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
5764 @*/
5765 PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5766 {
5767   PetscFunctionBegin;
5768   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5769   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5770   PetscCheckSameComm(snes, 1, npc, 2);
5771   PetscCall(PetscObjectReference((PetscObject)npc));
5772   PetscCall(SNESDestroy(&snes->npc));
5773   snes->npc = npc;
5774   PetscFunctionReturn(PETSC_SUCCESS);
5775 }
5776 
5777 /*@
5778   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
5779 
5780   Not Collective; but any changes to the obtained the `pc` object must be applied collectively
5781 
5782   Input Parameter:
5783 . snes - iterative context obtained from `SNESCreate()`
5784 
5785   Output Parameter:
5786 . pc - the `SNES` preconditioner context
5787 
5788   Options Database Key:
5789 . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5790 
5791   Level: advanced
5792 
5793   Notes:
5794   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will
5795   be used as the nonlinear preconditioner for the current `SNES`.
5796 
5797   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5798   `SNES`. These may be overwritten if needed.
5799 
5800   Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner
5801 
5802 .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
5803 @*/
5804 PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5805 {
5806   const char *optionsprefix;
5807 
5808   PetscFunctionBegin;
5809   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5810   PetscAssertPointer(pc, 2);
5811   if (!snes->npc) {
5812     void *ctx;
5813 
5814     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
5815     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
5816     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
5817     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
5818     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5819     if (snes->ops->usercompute) {
5820       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy));
5821     } else {
5822       PetscCall(SNESGetApplicationContext(snes, &ctx));
5823       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5824     }
5825     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
5826   }
5827   *pc = snes->npc;
5828   PetscFunctionReturn(PETSC_SUCCESS);
5829 }
5830 
5831 /*@
5832   SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES`
5833 
5834   Not Collective
5835 
5836   Input Parameter:
5837 . snes - iterative context obtained from `SNESCreate()`
5838 
5839   Output Parameter:
5840 . has_npc - whether the `SNES` has a nonlinear preconditioner or not
5841 
5842   Level: developer
5843 
5844 .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
5845 @*/
5846 PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5847 {
5848   PetscFunctionBegin;
5849   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5850   PetscAssertPointer(has_npc, 2);
5851   *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE;
5852   PetscFunctionReturn(PETSC_SUCCESS);
5853 }
5854 
5855 /*@
5856   SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`.
5857 
5858   Logically Collective
5859 
5860   Input Parameter:
5861 . snes - iterative context obtained from `SNESCreate()`
5862 
5863   Output Parameter:
5864 . side - the preconditioning side, where side is one of
5865 .vb
5866       PC_LEFT  - left preconditioning
5867       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5868 .ve
5869 
5870   Options Database Key:
5871 . -snes_npc_side <right,left> - nonlinear preconditioner side
5872 
5873   Level: intermediate
5874 
5875   Note:
5876   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
5877 
5878 .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5879 @*/
5880 PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5881 {
5882   PetscFunctionBegin;
5883   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5884   PetscValidLogicalCollectiveEnum(snes, side, 2);
5885   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
5886   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5887   snes->npcside = side;
5888   PetscFunctionReturn(PETSC_SUCCESS);
5889 }
5890 
5891 /*@
5892   SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`.
5893 
5894   Not Collective
5895 
5896   Input Parameter:
5897 . snes - iterative context obtained from `SNESCreate()`
5898 
5899   Output Parameter:
5900 . side - the preconditioning side, where side is one of
5901 .vb
5902       `PC_LEFT` - left preconditioning
5903       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5904 .ve
5905 
5906   Level: intermediate
5907 
5908 .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5909 @*/
5910 PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5911 {
5912   PetscFunctionBegin;
5913   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5914   PetscAssertPointer(side, 2);
5915   *side = snes->npcside;
5916   PetscFunctionReturn(PETSC_SUCCESS);
5917 }
5918 
5919 /*@
5920   SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES`
5921 
5922   Collective
5923 
5924   Input Parameters:
5925 + snes       - iterative context obtained from `SNESCreate()`
5926 - linesearch - the linesearch object
5927 
5928   Level: developer
5929 
5930   Note:
5931   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
5932   to configure it using the API).
5933 
5934 .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
5935 @*/
5936 PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5937 {
5938   PetscFunctionBegin;
5939   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5940   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
5941   PetscCheckSameComm(snes, 1, linesearch, 2);
5942   PetscCall(PetscObjectReference((PetscObject)linesearch));
5943   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5944 
5945   snes->linesearch = linesearch;
5946   PetscFunctionReturn(PETSC_SUCCESS);
5947 }
5948 
5949 /*@
5950   SNESGetLineSearch - Returns the line search associated with the `SNES`.
5951 
5952   Not Collective
5953 
5954   Input Parameter:
5955 . snes - iterative context obtained from `SNESCreate()`
5956 
5957   Output Parameter:
5958 . linesearch - linesearch context
5959 
5960   Level: beginner
5961 
5962   Notes:
5963   It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`.
5964 
5965   You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options.
5966 
5967 .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`
5968 @*/
5969 PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5970 {
5971   const char *optionsprefix;
5972 
5973   PetscFunctionBegin;
5974   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5975   PetscAssertPointer(linesearch, 2);
5976   if (!snes->linesearch) {
5977     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
5978     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
5979     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
5980     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
5981     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
5982   }
5983   *linesearch = snes->linesearch;
5984   PetscFunctionReturn(PETSC_SUCCESS);
5985 }
5986