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