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