xref: /petsc/src/snes/interface/snes.c (revision 76c6338944e4871467ad7a763eee41b62845c2b0)
1af0996ceSBarry Smith #include <petsc/private/snesimpl.h>       /*I "petscsnes.h"  I*/
2*76c63389SBarry Smith #include <petsc/private/linesearchimpl.h> /*I "petscsnes.h"  I*/
307475bc1SBarry Smith #include <petscdmshell.h>
4d96771aaSLisandro Dalcin #include <petscdraw.h>
5a01aa210SMatthew G. Knepley #include <petscds.h>
634b4d3a8SMatthew G. Knepley #include <petscdmadaptor.h>
706fc46c8SMatthew G. Knepley #include <petscconvest.h>
89b94acceSBarry Smith 
9ace3abfcSBarry Smith PetscBool         SNESRegisterAllCalled = PETSC_FALSE;
100298fd71SBarry Smith PetscFunctionList SNESList              = NULL;
118ba1e511SMatthew Knepley 
128ba1e511SMatthew Knepley /* Logging support */
1322c6f798SBarry Smith PetscClassId  SNES_CLASSID, DMSNES_CLASSID;
1497276fddSZach Atkins PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NewtonALEval, SNES_NPCSolve, SNES_ObjectiveEval;
15a09944afSBarry Smith 
16e113a28aSBarry Smith /*@
17dc4c0fb0SBarry Smith   SNESSetErrorIfNotConverged - Causes `SNESSolve()` to generate an error immediately if the solver has not converged.
18e113a28aSBarry Smith 
19c3339decSBarry Smith   Logically Collective
20e113a28aSBarry Smith 
21e113a28aSBarry Smith   Input Parameters:
22f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
23f6dfbefdSBarry Smith - flg  - `PETSC_TRUE` indicates you want the error generated
24e113a28aSBarry Smith 
2520f4b53cSBarry Smith   Options Database Key:
2667b8a455SSatish Balay . -snes_error_if_not_converged <true,false> - cause an immediate error condition and stop the program if the solver does not converge
27e113a28aSBarry Smith 
28e113a28aSBarry Smith   Level: intermediate
29e113a28aSBarry Smith 
30f6dfbefdSBarry Smith   Note:
31f6dfbefdSBarry Smith   Normally PETSc continues if a solver fails to converge, you can call `SNESGetConvergedReason()` after a `SNESSolve()`
32f6dfbefdSBarry Smith   to determine if it has converged. Otherwise the solution may be inaccurate or wrong
33e113a28aSBarry Smith 
341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()`
35e113a28aSBarry Smith @*/
36d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetErrorIfNotConverged(SNES snes, PetscBool flg)
37d71ae5a4SJacob Faibussowitsch {
38e113a28aSBarry Smith   PetscFunctionBegin;
39e113a28aSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
40acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flg, 2);
41e113a28aSBarry Smith   snes->errorifnotconverged = flg;
423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43e113a28aSBarry Smith }
44e113a28aSBarry Smith 
45e113a28aSBarry Smith /*@
46f6dfbefdSBarry Smith   SNESGetErrorIfNotConverged - Indicates if `SNESSolve()` will generate an error if the solver does not converge?
47e113a28aSBarry Smith 
48e113a28aSBarry Smith   Not Collective
49e113a28aSBarry Smith 
50e113a28aSBarry Smith   Input Parameter:
51f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
52e113a28aSBarry Smith 
53e113a28aSBarry Smith   Output Parameter:
54f6dfbefdSBarry Smith . flag - `PETSC_TRUE` if it will generate an error, else `PETSC_FALSE`
55e113a28aSBarry Smith 
56e113a28aSBarry Smith   Level: intermediate
57e113a28aSBarry Smith 
581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()`
59e113a28aSBarry Smith @*/
60d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetErrorIfNotConverged(SNES snes, PetscBool *flag)
61d71ae5a4SJacob Faibussowitsch {
62e113a28aSBarry Smith   PetscFunctionBegin;
63e113a28aSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
644f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
65e113a28aSBarry Smith   *flag = snes->errorifnotconverged;
663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
67e113a28aSBarry Smith }
68e113a28aSBarry Smith 
694fc747eaSLawrence Mitchell /*@
70dc4c0fb0SBarry Smith   SNESSetAlwaysComputesFinalResidual - tells the `SNES` to always compute the residual (nonlinear function value) at the final solution
714fc747eaSLawrence Mitchell 
72c3339decSBarry Smith   Logically Collective
734fc747eaSLawrence Mitchell 
744fc747eaSLawrence Mitchell   Input Parameters:
75f6dfbefdSBarry Smith + snes - the shell `SNES`
76f6dfbefdSBarry Smith - flg  - `PETSC_TRUE` to always compute the residual
774fc747eaSLawrence Mitchell 
784fc747eaSLawrence Mitchell   Level: advanced
794fc747eaSLawrence Mitchell 
80f6dfbefdSBarry Smith   Note:
81f6dfbefdSBarry Smith   Some solvers (such as smoothers in a `SNESFAS`) do not need the residual computed at the final solution so skip computing it
82f6dfbefdSBarry Smith   to save time.
83f6dfbefdSBarry Smith 
84420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESGetAlwaysComputesFinalResidual()`
854fc747eaSLawrence Mitchell @*/
86d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetAlwaysComputesFinalResidual(SNES snes, PetscBool flg)
87d71ae5a4SJacob Faibussowitsch {
884fc747eaSLawrence Mitchell   PetscFunctionBegin;
894fc747eaSLawrence Mitchell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
904fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = flg;
913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
924fc747eaSLawrence Mitchell }
934fc747eaSLawrence Mitchell 
944fc747eaSLawrence Mitchell /*@
95f6dfbefdSBarry Smith   SNESGetAlwaysComputesFinalResidual - checks if the `SNES` always computes the residual at the final solution
964fc747eaSLawrence Mitchell 
97c3339decSBarry Smith   Logically Collective
984fc747eaSLawrence Mitchell 
994fc747eaSLawrence Mitchell   Input Parameter:
100f6dfbefdSBarry Smith . snes - the `SNES` context
1014fc747eaSLawrence Mitchell 
1024fc747eaSLawrence Mitchell   Output Parameter:
103f6dfbefdSBarry Smith . flg - `PETSC_TRUE` if the residual is computed
1044fc747eaSLawrence Mitchell 
1054fc747eaSLawrence Mitchell   Level: advanced
1064fc747eaSLawrence Mitchell 
107420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESSetAlwaysComputesFinalResidual()`
1084fc747eaSLawrence Mitchell @*/
109d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg)
110d71ae5a4SJacob Faibussowitsch {
1114fc747eaSLawrence Mitchell   PetscFunctionBegin;
1124fc747eaSLawrence Mitchell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1134fc747eaSLawrence Mitchell   *flg = snes->alwayscomputesfinalresidual;
1143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1154fc747eaSLawrence Mitchell }
1164fc747eaSLawrence Mitchell 
117e725d27bSBarry Smith /*@
118f6dfbefdSBarry Smith   SNESSetFunctionDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetFunction()` is not
119*76c63389SBarry Smith   in the function's domain. For example, a step with negative pressure.
1204936397dSBarry Smith 
1216b1535e8SBarry Smith   Not Collective
1224936397dSBarry Smith 
1232fe279fdSBarry Smith   Input Parameter:
124f6dfbefdSBarry Smith . snes - the `SNES` context
1254936397dSBarry Smith 
12628529972SSatish Balay   Level: advanced
1274936397dSBarry Smith 
128ced0f3aeSBarry Smith   Notes:
1296b1535e8SBarry Smith   This does not need to be called by all processes in the `SNES` MPI communicator.
1306b1535e8SBarry Smith 
131*76c63389SBarry Smith   A few solvers will try to cut the step size to avoid the domain error but for other solvers `SNESSolve()` stops iterating and and
132*76c63389SBarry Smith   returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
133ced0f3aeSBarry Smith 
134f0b84518SBarry Smith   You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
135f0b84518SBarry Smith   `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
136f0b84518SBarry Smith 
137*76c63389SBarry Smith   You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
138*76c63389SBarry Smith 
1396b1535e8SBarry Smith   You can call `SNESSetJacobianDomainError()` during a Jacobian computation to indicate the proposed solution is not in the domain.
1406b1535e8SBarry Smith 
1416b1535e8SBarry Smith   Developer Note:
142*76c63389SBarry Smith   This value is used by `SNESCheckFunctionDomainError()` to determine if the `SNESConvergedReason` is set to `SNES_DIVERGED_FUNCTION_DOMAIN`
1436b1535e8SBarry Smith 
1448434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`,
1456b1535e8SBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`,
146*76c63389SBarry Smith           `SNES_DIVERGED_FUNCTION_DOMAIN`, `SNESSetObjectiveDomainError()`
1474936397dSBarry Smith @*/
148d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionDomainError(SNES snes)
149d71ae5a4SJacob Faibussowitsch {
1504936397dSBarry Smith   PetscFunctionBegin;
1510700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
152*76c63389SBarry Smith   snes->functiondomainerror = PETSC_TRUE;
153*76c63389SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
154*76c63389SBarry Smith }
155*76c63389SBarry Smith 
156*76c63389SBarry Smith /*@
157*76c63389SBarry Smith   SNESSetObjectiveDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetObjective()` is not
158*76c63389SBarry Smith   in the function's domain. For example, a step with negative pressure.
159*76c63389SBarry Smith 
160*76c63389SBarry Smith   Not Collective
161*76c63389SBarry Smith 
162*76c63389SBarry Smith   Input Parameter:
163*76c63389SBarry Smith . snes - the `SNES` context
164*76c63389SBarry Smith 
165*76c63389SBarry Smith   Level: advanced
166*76c63389SBarry Smith 
167*76c63389SBarry Smith   Notes:
168*76c63389SBarry Smith   This does not need to be called by all processes in the `SNES` MPI communicator.
169*76c63389SBarry Smith 
170*76c63389SBarry Smith   A few solvers will try to cut the step size to avoid the domain error but for other solvers `SNESSolve()` stops iterating and and
171*76c63389SBarry Smith   returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
172*76c63389SBarry Smith 
173*76c63389SBarry Smith   You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
174*76c63389SBarry Smith   `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
175*76c63389SBarry Smith 
176*76c63389SBarry Smith   You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
177*76c63389SBarry Smith 
178*76c63389SBarry Smith   You can call `SNESSetJacobianDomainError()` during a Jacobian computation to indicate the proposed solution is not in the domain.
179*76c63389SBarry Smith 
180*76c63389SBarry Smith   Developer Note:
181*76c63389SBarry Smith   This value is used by `SNESCheckFunctionDomainError()` to determine if the `SNESConvergedReason` is set to `SNES_DIVERGED_FUNCTION_DOMAIN`
182*76c63389SBarry Smith 
183*76c63389SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`,
184*76c63389SBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`,
185*76c63389SBarry Smith           `SNES_DIVERGED_FUNCTION_DOMAIN`, `SNESSetFunctionDomainError()`
186*76c63389SBarry Smith @*/
187*76c63389SBarry Smith PetscErrorCode SNESSetObjectiveDomainError(SNES snes)
188*76c63389SBarry Smith {
189*76c63389SBarry Smith   PetscFunctionBegin;
190*76c63389SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
191*76c63389SBarry Smith   snes->objectivedomainerror = PETSC_TRUE;
1923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1934936397dSBarry Smith }
1944936397dSBarry Smith 
1956a388c36SPeter Brune /*@
196f6dfbefdSBarry Smith   SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation.
19707b62357SFande Kong 
198c3339decSBarry Smith   Logically Collective
19907b62357SFande Kong 
2002fe279fdSBarry Smith   Input Parameter:
201f6dfbefdSBarry Smith . snes - the `SNES` context
20207b62357SFande Kong 
20307b62357SFande Kong   Level: advanced
20407b62357SFande Kong 
205ced0f3aeSBarry Smith   Notes:
206ced0f3aeSBarry Smith   If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
207ced0f3aeSBarry Smith 
208ced0f3aeSBarry Smith   You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
209ced0f3aeSBarry Smith 
210f0b84518SBarry Smith   You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
211f0b84518SBarry Smith   `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
212f0b84518SBarry Smith 
2138434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`,
214ced0f3aeSBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`
21507b62357SFande Kong @*/
216d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes)
217d71ae5a4SJacob Faibussowitsch {
21807b62357SFande Kong   PetscFunctionBegin;
21907b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2205f80ce2aSJacob Faibussowitsch   PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense");
22107b62357SFande Kong   snes->jacobiandomainerror = PETSC_TRUE;
2223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22307b62357SFande Kong }
22407b62357SFande Kong 
22507b62357SFande Kong /*@
226*76c63389SBarry Smith   SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` to indicate a Jacobian domain error after
227*76c63389SBarry Smith   each Jacobian evaluation.
228b351a90bSFande Kong 
229c3339decSBarry Smith   Logically Collective
230b351a90bSFande Kong 
231b351a90bSFande Kong   Input Parameters:
23220f4b53cSBarry Smith + snes - the `SNES` context
233f6dfbefdSBarry Smith - flg  - indicates if or not to check Jacobian domain error after each Jacobian evaluation
234b351a90bSFande Kong 
235b351a90bSFande Kong   Level: advanced
236b351a90bSFande Kong 
237*76c63389SBarry Smith   Notes:
238*76c63389SBarry Smith   By default, it checks for the Jacobian domain error in the debug mode, and does not check it in the optimized mode.
239*76c63389SBarry Smith 
240f6dfbefdSBarry Smith   Checks require one extra parallel synchronization for each Jacobian evaluation
241f6dfbefdSBarry Smith 
2428434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()`
243b351a90bSFande Kong @*/
244d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg)
245d71ae5a4SJacob Faibussowitsch {
246b351a90bSFande Kong   PetscFunctionBegin;
247b351a90bSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
248b351a90bSFande Kong   snes->checkjacdomainerror = flg;
2493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
250b351a90bSFande Kong }
251b351a90bSFande Kong 
252b351a90bSFande Kong /*@
253420bcc1bSBarry Smith   SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation.
2548383d7d7SFande Kong 
255c3339decSBarry Smith   Logically Collective
2568383d7d7SFande Kong 
2572fe279fdSBarry Smith   Input Parameter:
258f6dfbefdSBarry Smith . snes - the `SNES` context
2598383d7d7SFande Kong 
2602fe279fdSBarry Smith   Output Parameter:
261420bcc1bSBarry Smith . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation
2628383d7d7SFande Kong 
2638383d7d7SFande Kong   Level: advanced
2648383d7d7SFande Kong 
2658434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()`
2668383d7d7SFande Kong @*/
267d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg)
268d71ae5a4SJacob Faibussowitsch {
2698383d7d7SFande Kong   PetscFunctionBegin;
2708383d7d7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2714f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
2728383d7d7SFande Kong   *flg = snes->checkjacdomainerror;
2733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2748383d7d7SFande Kong }
2758383d7d7SFande Kong 
2768383d7d7SFande Kong /*@
277f6dfbefdSBarry Smith   SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`.
27855849f57SBarry Smith 
279c3339decSBarry Smith   Collective
28055849f57SBarry Smith 
28155849f57SBarry Smith   Input Parameters:
282e4094ef1SJacob Faibussowitsch + snes   - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or
283f6dfbefdSBarry Smith            some related function before a call to `SNESLoad()`.
284f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
28555849f57SBarry Smith 
28655849f57SBarry Smith   Level: intermediate
28755849f57SBarry Smith 
288f6dfbefdSBarry Smith   Note:
289420bcc1bSBarry Smith   The `SNESType` is determined by the data in the file, any type set into the `SNES` before this call is ignored.
29055849f57SBarry Smith 
2911cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()`
29255849f57SBarry Smith @*/
293d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer)
294d71ae5a4SJacob Faibussowitsch {
29555849f57SBarry Smith   PetscBool isbinary;
296060da220SMatthew G. Knepley   PetscInt  classid;
29755849f57SBarry Smith   char      type[256];
29855849f57SBarry Smith   KSP       ksp;
2992d53ad75SBarry Smith   DM        dm;
3002d53ad75SBarry Smith   DMSNES    dmsnes;
30155849f57SBarry Smith 
30255849f57SBarry Smith   PetscFunctionBegin;
3032d53ad75SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
30455849f57SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
3065f80ce2aSJacob Faibussowitsch   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");
30755849f57SBarry Smith 
3089566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
3095f80ce2aSJacob Faibussowitsch   PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file");
3109566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
3119566063dSJacob Faibussowitsch   PetscCall(SNESSetType(snes, type));
312dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, load, viewer);
3139566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3149566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &dmsnes));
3159566063dSJacob Faibussowitsch   PetscCall(DMSNESLoad(dmsnes, viewer));
3169566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
3179566063dSJacob Faibussowitsch   PetscCall(KSPLoad(ksp, viewer));
3183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31955849f57SBarry Smith }
3206a388c36SPeter Brune 
3219804daf3SBarry Smith #include <petscdraw.h>
322e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
323e04113cfSBarry Smith   #include <petscviewersaws.h>
324bfb97211SBarry Smith #endif
3258404b7f3SBarry Smith 
326ffeef943SBarry Smith /*@
327dc4c0fb0SBarry Smith   SNESViewFromOptions - View a `SNES` based on values in the options database
328fe2efc57SMark 
329c3339decSBarry Smith   Collective
330fe2efc57SMark 
331fe2efc57SMark   Input Parameters:
332f6dfbefdSBarry Smith + A    - the `SNES` context
333dc4c0fb0SBarry Smith . obj  - Optional object that provides the options prefix for the checks
334736c3998SJose E. Roman - name - command line option
335fe2efc57SMark 
336fe2efc57SMark   Level: intermediate
337f6dfbefdSBarry Smith 
3381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()`
339fe2efc57SMark @*/
340d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[])
341d71ae5a4SJacob Faibussowitsch {
342fe2efc57SMark   PetscFunctionBegin;
343fe2efc57SMark   PetscValidHeaderSpecific(A, SNES_CLASSID, 1);
3449566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
3453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
346fe2efc57SMark }
347fe2efc57SMark 
348789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *);
349789d8953SBarry Smith 
350ffeef943SBarry Smith /*@
351dc4c0fb0SBarry Smith   SNESView - Prints or visualizes the `SNES` data structure.
3529b94acceSBarry Smith 
353c3339decSBarry Smith   Collective
354fee21e36SBarry Smith 
355c7afd0dbSLois Curfman McInnes   Input Parameters:
356f6dfbefdSBarry Smith + snes   - the `SNES` context
357f6dfbefdSBarry Smith - viewer - the `PetscViewer`
358c7afd0dbSLois Curfman McInnes 
3599b94acceSBarry Smith   Options Database Key:
360f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()`
3619b94acceSBarry Smith 
362dc4c0fb0SBarry Smith   Level: beginner
363dc4c0fb0SBarry Smith 
3649b94acceSBarry Smith   Notes:
3659b94acceSBarry Smith   The available visualization contexts include
366f6dfbefdSBarry Smith +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
367f6dfbefdSBarry Smith -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
368c8a8ba5cSLois Curfman McInnes   output where only the first processor opens
369c8a8ba5cSLois Curfman McInnes   the file.  All other processors send their
370c8a8ba5cSLois Curfman McInnes   data to the first processor to print.
3719b94acceSBarry Smith 
372052bf0daSPierre Jolivet   The available formats include
373f6dfbefdSBarry Smith +     `PETSC_VIEWER_DEFAULT` - standard output (default)
374f6dfbefdSBarry Smith -     `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM`
375052bf0daSPierre Jolivet 
3763e081fefSLois Curfman McInnes   The user can open an alternative visualization context with
377f6dfbefdSBarry Smith   `PetscViewerASCIIOpen()` - output to a specified file.
3789b94acceSBarry Smith 
379f6dfbefdSBarry Smith   In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer).
380595c91d4SBarry Smith 
3811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()`
3829b94acceSBarry Smith @*/
383d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer)
384d71ae5a4SJacob Faibussowitsch {
385fa9f3622SBarry Smith   SNESKSPEW     *kctx;
38694b7f48cSBarry Smith   KSP            ksp;
3877f1410a3SPeter Brune   SNESLineSearch linesearch;
3889f196a02SMartin Diehl   PetscBool      isascii, isstring, isbinary, isdraw;
3892d53ad75SBarry Smith   DMSNES         dmsnes;
390e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
391536b137fSBarry Smith   PetscBool issaws;
392bfb97211SBarry Smith #endif
3939b94acceSBarry Smith 
3943a40ed3dSBarry Smith   PetscFunctionBegin;
3950700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
39648a46eb9SPierre Jolivet   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer));
3970700a824SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
398c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, viewer, 2);
39974679c65SBarry Smith 
4009f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
4019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
4029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
4039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
404e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
4059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
406bfb97211SBarry Smith #endif
4079f196a02SMartin Diehl   if (isascii) {
408dc0571f2SMatthew G. Knepley     SNESNormSchedule normschedule;
4098404b7f3SBarry Smith     DM               dm;
4108434afd1SBarry Smith     SNESJacobianFn  *cJ;
4118404b7f3SBarry Smith     void            *ctx;
412789d8953SBarry Smith     const char      *pre = "";
413dc0571f2SMatthew G. Knepley 
4149566063dSJacob Faibussowitsch     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer));
41548a46eb9SPierre Jolivet     if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  SNES has not been set up so information may be incomplete\n"));
416e7788613SBarry Smith     if (snes->ops->view) {
4179566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
418dbbe0bcdSBarry Smith       PetscUseTypeMethod(snes, view, viewer);
4199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
4200ef38995SBarry Smith     }
42177e5a1f9SBarry Smith     if (snes->max_funcs == PETSC_UNLIMITED) {
42277e5a1f9SBarry Smith       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=unlimited\n", snes->max_its));
42377e5a1f9SBarry Smith     } else {
42463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs));
42577e5a1f9SBarry Smith     }
4269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol));
42748a46eb9SPierre Jolivet     if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its));
42863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs));
4299566063dSJacob Faibussowitsch     PetscCall(SNESGetNormSchedule(snes, &normschedule));
4309566063dSJacob Faibussowitsch     if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "  norm schedule %s\n", SNESNormSchedules[normschedule]));
43148a46eb9SPierre Jolivet     if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence));
4329b94acceSBarry Smith     if (snes->ksp_ewconv) {
433fa9f3622SBarry Smith       kctx = (SNESKSPEW *)snes->kspconvctx;
4349b94acceSBarry Smith       if (kctx) {
43563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version));
4369566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold));
4379566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2));
4389b94acceSBarry Smith       }
4399b94acceSBarry Smith     }
440eb1f6c34SBarry Smith     if (snes->lagpreconditioner == -1) {
4419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is never rebuilt\n"));
442eb1f6c34SBarry Smith     } else if (snes->lagpreconditioner > 1) {
44363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner));
444eb1f6c34SBarry Smith     }
445eb1f6c34SBarry Smith     if (snes->lagjacobian == -1) {
4469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is never rebuilt\n"));
447eb1f6c34SBarry Smith     } else if (snes->lagjacobian > 1) {
44863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian));
449eb1f6c34SBarry Smith     }
4509566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4519566063dSJacob Faibussowitsch     PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx));
452789d8953SBarry Smith     if (snes->mf_operator) {
4539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing\n"));
454789d8953SBarry Smith       pre = "Preconditioning ";
455789d8953SBarry Smith     }
4568404b7f3SBarry Smith     if (cJ == SNESComputeJacobianDefault) {
4579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences one column at a time\n", pre));
4588404b7f3SBarry Smith     } else if (cJ == SNESComputeJacobianDefaultColor) {
4599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences with coloring\n", pre));
460789d8953SBarry Smith       /* it slightly breaks data encapsulation for access the DMDA information directly */
461789d8953SBarry Smith     } else if (cJ == SNESComputeJacobian_DMDA) {
462789d8953SBarry Smith       MatFDColoring fdcoloring;
4639566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring));
464789d8953SBarry Smith       if (fdcoloring) {
4659566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using colored finite differences on a DMDA\n", pre));
466789d8953SBarry Smith       } else {
4679566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using a DMDA local Jacobian\n", pre));
468789d8953SBarry Smith       }
469996e1cbcSBarry Smith     } else if (snes->mf && !snes->mf_operator) {
4709566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing, no explicit Jacobian\n"));
4718404b7f3SBarry Smith     }
4720f5bd95cSBarry Smith   } else if (isstring) {
473317d6ea6SBarry Smith     const char *type;
4749566063dSJacob Faibussowitsch     PetscCall(SNESGetType(snes, &type));
4759566063dSJacob Faibussowitsch     PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type));
476dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
47755849f57SBarry Smith   } else if (isbinary) {
47855849f57SBarry Smith     PetscInt    classid = SNES_FILE_CLASSID;
47955849f57SBarry Smith     MPI_Comm    comm;
48055849f57SBarry Smith     PetscMPIInt rank;
48155849f57SBarry Smith     char        type[256];
48255849f57SBarry Smith 
4839566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
4849566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
485dd400576SPatrick Sanan     if (rank == 0) {
4869566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
4879566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type)));
4889566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR));
48955849f57SBarry Smith     }
490dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
49172a02f06SBarry Smith   } else if (isdraw) {
49272a02f06SBarry Smith     PetscDraw draw;
49372a02f06SBarry Smith     char      str[36];
49489fd9fafSBarry Smith     PetscReal x, y, bottom, h;
49572a02f06SBarry Smith 
4969566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4979566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
4989566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str)));
4999566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str)));
5009566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h));
50189fd9fafSBarry Smith     bottom = y - h;
5029566063dSJacob Faibussowitsch     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
503dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
504e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
505536b137fSBarry Smith   } else if (issaws) {
506d45a07a7SBarry Smith     PetscMPIInt rank;
5072657e9d9SBarry Smith     const char *name;
508d45a07a7SBarry Smith 
5099566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)snes, &name));
5109566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
511dd400576SPatrick Sanan     if (!((PetscObject)snes)->amsmem && rank == 0) {
512d45a07a7SBarry Smith       char dir[1024];
513d45a07a7SBarry Smith 
5149566063dSJacob Faibussowitsch       PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer));
5159566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name));
516792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT));
51748a46eb9SPierre Jolivet       if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE));
5189566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name));
519792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE));
520f05ece33SBarry Smith     }
521bfb97211SBarry Smith #endif
52272a02f06SBarry Smith   }
52372a02f06SBarry Smith   if (snes->linesearch) {
5249566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &linesearch));
5259566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5269566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchView(linesearch, viewer));
5279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
52819bcc07fSBarry Smith   }
529efd4aadfSBarry Smith   if (snes->npc && snes->usesnpc) {
5309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5319566063dSJacob Faibussowitsch     PetscCall(SNESView(snes->npc, viewer));
5329566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5334a0c5b0cSMatthew G Knepley   }
5349566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
5359566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(snes->dm, &dmsnes));
5369566063dSJacob Faibussowitsch   PetscCall(DMSNESView(dmsnes, viewer));
5379566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
5382c155ee1SBarry Smith   if (snes->usesksp) {
5399566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
5409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5419566063dSJacob Faibussowitsch     PetscCall(KSPView(ksp, viewer));
5429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5432c155ee1SBarry Smith   }
54472a02f06SBarry Smith   if (isdraw) {
54572a02f06SBarry Smith     PetscDraw draw;
5469566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5479566063dSJacob Faibussowitsch     PetscCall(PetscDrawPopCurrentPoint(draw));
5487f1410a3SPeter Brune   }
5493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5509b94acceSBarry Smith }
5519b94acceSBarry Smith 
55276b2cf59SMatthew Knepley /*
55376b2cf59SMatthew Knepley   We retain a list of functions that also take SNES command
55476b2cf59SMatthew Knepley   line options. These are called at the end SNESSetFromOptions()
55576b2cf59SMatthew Knepley */
55676b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5
557a7cc72afSBarry Smith static PetscInt numberofsetfromoptions;
5586849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
55976b2cf59SMatthew Knepley 
560ac226902SBarry Smith /*@C
561f6dfbefdSBarry Smith   SNESAddOptionsChecker - Adds an additional function to check for `SNES` options.
56276b2cf59SMatthew Knepley 
56376b2cf59SMatthew Knepley   Not Collective
56476b2cf59SMatthew Knepley 
56576b2cf59SMatthew Knepley   Input Parameter:
56676b2cf59SMatthew Knepley . snescheck - function that checks for options
56776b2cf59SMatthew Knepley 
568420bcc1bSBarry Smith   Calling sequence of `snescheck`:
569420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options
570420bcc1bSBarry Smith 
57176b2cf59SMatthew Knepley   Level: developer
57276b2cf59SMatthew Knepley 
5731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`
57476b2cf59SMatthew Knepley @*/
575420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes))
576d71ae5a4SJacob Faibussowitsch {
57776b2cf59SMatthew Knepley   PetscFunctionBegin;
57863a3b9bcSJacob Faibussowitsch   PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS);
57976b2cf59SMatthew Knepley   othersetfromoptions[numberofsetfromoptions++] = snescheck;
5803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58176b2cf59SMatthew Knepley }
58276b2cf59SMatthew Knepley 
583d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
584d71ae5a4SJacob Faibussowitsch {
585aa3661deSLisandro Dalcin   Mat          J;
586895c21f2SBarry Smith   MatNullSpace nullsp;
587aa3661deSLisandro Dalcin 
588aa3661deSLisandro Dalcin   PetscFunctionBegin;
5890700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
590aa3661deSLisandro Dalcin 
59198613b67SLisandro Dalcin   if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
59298613b67SLisandro Dalcin     Mat A = snes->jacobian, B = snes->jacobian_pre;
5939566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func));
59498613b67SLisandro Dalcin   }
59598613b67SLisandro Dalcin 
5960fdf79fbSJacob Faibussowitsch   PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
597aa3661deSLisandro Dalcin   if (version == 1) {
5989566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
5999566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
6009566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
6011e2ae407SBarry Smith     /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
6020fdf79fbSJacob Faibussowitsch   } else /* if (version == 2) */ {
6035f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first");
604570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
605f6dfbefdSBarry Smith     PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J));
606aa3661deSLisandro Dalcin #else
6072479783cSJose E. Roman     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
608aa3661deSLisandro Dalcin #endif
6090fdf79fbSJacob Faibussowitsch   }
610aa3661deSLisandro Dalcin 
61101c1178eSBarry Smith   /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */
612895c21f2SBarry Smith   if (snes->jacobian) {
6139566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(snes->jacobian, &nullsp));
6141baa6e33SBarry Smith     if (nullsp) PetscCall(MatSetNullSpace(J, nullsp));
615895c21f2SBarry Smith   }
616895c21f2SBarry Smith 
61763a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version));
618d3462f78SMatthew Knepley   if (hasOperator) {
619aa3661deSLisandro Dalcin     /* This version replaces the user provided Jacobian matrix with a
6207addb90fSBarry Smith        matrix-free version but still employs the user-provided matrix used for computing the preconditioner. */
6219566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
622aa3661deSLisandro Dalcin   } else {
623aa3661deSLisandro Dalcin     /* This version replaces both the user-provided Jacobian and the user-
62401c1178eSBarry Smith      provided preconditioner Jacobian with the default matrix-free version. */
625b552625fSStefano Zampini     if (snes->npcside == PC_LEFT && snes->npc) {
6269566063dSJacob Faibussowitsch       if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
627172a4300SPeter Brune     } else {
628789d8953SBarry Smith       KSP       ksp;
629789d8953SBarry Smith       PC        pc;
630789d8953SBarry Smith       PetscBool match;
631789d8953SBarry Smith 
6329566063dSJacob Faibussowitsch       PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL));
633aa3661deSLisandro Dalcin       /* Force no preconditioner */
6349566063dSJacob Faibussowitsch       PetscCall(SNESGetKSP(snes, &ksp));
6359566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksp, &pc));
6362698c518SLisandro Dalcin       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, ""));
637aa3661deSLisandro Dalcin       if (!match) {
6389566063dSJacob Faibussowitsch         PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n"));
6399566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc, PCNONE));
640aa3661deSLisandro Dalcin       }
641aa3661deSLisandro Dalcin     }
642789d8953SBarry Smith   }
6439566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&J));
6443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
645aa3661deSLisandro Dalcin }
646aa3661deSLisandro Dalcin 
647d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx)
648d71ae5a4SJacob Faibussowitsch {
649dfe15315SJed Brown   SNES snes = (SNES)ctx;
6500298fd71SBarry Smith   Vec  Xfine, Xfine_named = NULL, Xcoarse;
651dfe15315SJed Brown 
652dfe15315SJed Brown   PetscFunctionBegin;
65316ebb321SJed Brown   if (PetscLogPrintInfo) {
65416ebb321SJed Brown     PetscInt finelevel, coarselevel, fineclevel, coarseclevel;
6559566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmfine, &finelevel));
6569566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel));
6579566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel));
6589566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel));
65963a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dmfine, "Restricting SNES solution vector from level %" PetscInt_FMT "-%" PetscInt_FMT " to level %" PetscInt_FMT "-%" PetscInt_FMT "\n", finelevel, fineclevel, coarselevel, coarseclevel));
66016ebb321SJed Brown   }
661dfe15315SJed Brown   if (dmfine == snes->dm) Xfine = snes->vec_sol;
662dfe15315SJed Brown   else {
6639566063dSJacob Faibussowitsch     PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
664dfe15315SJed Brown     Xfine = Xfine_named;
665dfe15315SJed Brown   }
6669566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
667907f5c5aSLawrence Mitchell   if (Inject) {
6689566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Inject, Xfine, Xcoarse));
669907f5c5aSLawrence Mitchell   } else {
6709566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Restrict, Xfine, Xcoarse));
6719566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale));
672907f5c5aSLawrence Mitchell   }
6739566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
6749566063dSJacob Faibussowitsch   if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
6753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
676dfe15315SJed Brown }
677dfe15315SJed Brown 
678d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx)
679d71ae5a4SJacob Faibussowitsch {
68016ebb321SJed Brown   PetscFunctionBegin;
6819566063dSJacob Faibussowitsch   PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx));
6823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68316ebb321SJed Brown }
68416ebb321SJed Brown 
685a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
686a6950cb2SJed Brown  * safely call SNESGetDM() in their residual evaluation routine. */
687d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx)
688d71ae5a4SJacob Faibussowitsch {
689caa4e7f2SJed Brown   SNES            snes = (SNES)ctx;
69097d931d1SStefano Zampini   DMSNES          sdm;
6910298fd71SBarry Smith   Vec             X, Xnamed = NULL;
692dfe15315SJed Brown   DM              dmsave;
6934e269d77SPeter Brune   void           *ctxsave;
6948434afd1SBarry Smith   SNESJacobianFn *jac = NULL;
695caa4e7f2SJed Brown 
696caa4e7f2SJed Brown   PetscFunctionBegin;
697dfe15315SJed Brown   dmsave = snes->dm;
6989566063dSJacob Faibussowitsch   PetscCall(KSPGetDM(ksp, &snes->dm));
699dfe15315SJed Brown   if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
70097d931d1SStefano Zampini   else {
701309d62e6SStefano Zampini     PetscBool has;
702309d62e6SStefano Zampini 
70397d931d1SStefano Zampini     /* We are on a coarser level, this vec was initialized using a DM restrict hook */
704309d62e6SStefano Zampini     PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has));
705309d62e6SStefano Zampini     PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol");
70697d931d1SStefano Zampini     PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
707dfe15315SJed Brown     X = Xnamed;
7089566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave));
7094e269d77SPeter Brune     /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
71048a46eb9SPierre Jolivet     if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL));
7114e269d77SPeter Brune   }
7124e269d77SPeter Brune 
7132b93b426SMatthew G. Knepley   /* Compute the operators */
71497d931d1SStefano Zampini   PetscCall(DMGetDMSNES(snes->dm, &sdm));
71597d931d1SStefano Zampini   if (Xnamed && sdm->ops->computefunction) {
71697d931d1SStefano Zampini     /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian.
71797d931d1SStefano Zampini        We make sure of this here. Disable affine shift since it is for the finest level */
71897d931d1SStefano Zampini     Vec F, saverhs = snes->vec_rhs;
71997d931d1SStefano Zampini 
72097d931d1SStefano Zampini     snes->vec_rhs = NULL;
72197d931d1SStefano Zampini     PetscCall(DMGetGlobalVector(snes->dm, &F));
72297d931d1SStefano Zampini     PetscCall(SNESComputeFunction(snes, X, F));
72397d931d1SStefano Zampini     PetscCall(DMRestoreGlobalVector(snes->dm, &F));
72497d931d1SStefano Zampini     snes->vec_rhs = saverhs;
72597d931d1SStefano Zampini     snes->nfuncs--; /* Do not log coarser level evaluations */
72697d931d1SStefano Zampini   }
72797d931d1SStefano Zampini   /* Make sure KSP DM has the Jacobian computation routine */
72897d931d1SStefano Zampini   if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm));
729*76c63389SBarry Smith   PetscCall(SNESComputeJacobian(snes, X, A, B)); /* cannot handle previous SNESSetJacobianDomainError() calls */
73097d931d1SStefano Zampini 
7312b93b426SMatthew G. Knepley   /* Put the previous context back */
73248a46eb9SPierre Jolivet   if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave));
7334e269d77SPeter Brune 
7349566063dSJacob Faibussowitsch   if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
735dfe15315SJed Brown   snes->dm = dmsave;
7363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
737caa4e7f2SJed Brown }
738caa4e7f2SJed Brown 
7396cab3a1bSJed Brown /*@
740dc4c0fb0SBarry Smith   SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()`
7416cab3a1bSJed Brown 
7426cab3a1bSJed Brown   Collective
7436cab3a1bSJed Brown 
7444165533cSJose E. Roman   Input Parameter:
74520f4b53cSBarry Smith . snes - `SNES` object to configure
7466cab3a1bSJed Brown 
7476cab3a1bSJed Brown   Level: developer
7486cab3a1bSJed Brown 
749dc4c0fb0SBarry Smith   Note:
750dc4c0fb0SBarry Smith   If the matrices do not yet exist it attempts to create them based on options previously set for the `SNES` such as `-snes_mf`
751dc4c0fb0SBarry Smith 
75273a84a35SBarry Smith   Developer Note:
75373a84a35SBarry Smith   The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by
75473a84a35SBarry Smith   `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the
75573a84a35SBarry Smith   logic that handles the matrix-free case is desirable.
75673a84a35SBarry Smith 
7571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()`
7586cab3a1bSJed Brown @*/
759d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
760d71ae5a4SJacob Faibussowitsch {
7616cab3a1bSJed Brown   DM     dm;
762942e3340SBarry Smith   DMSNES sdm;
7636cab3a1bSJed Brown 
7646cab3a1bSJed Brown   PetscFunctionBegin;
7659566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
7669566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
76773a84a35SBarry Smith   if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) {
7686cab3a1bSJed Brown     Mat   J;
7696cab3a1bSJed Brown     void *functx;
7709566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7719566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7729566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7739566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7749566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7759566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
776caa4e7f2SJed Brown   } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7776cab3a1bSJed Brown     Mat J, B;
7789566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7799566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7809566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7819566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
78206f20277SJed Brown     /* sdm->computejacobian was already set to reach here */
7839566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
7849566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7859566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
786caa4e7f2SJed Brown   } else if (!snes->jacobian_pre) {
7871ba9b98eSMatthew G. Knepley     PetscDS   prob;
7886cab3a1bSJed Brown     Mat       J, B;
7891ba9b98eSMatthew G. Knepley     PetscBool hasPrec = PETSC_FALSE;
7901ba9b98eSMatthew G. Knepley 
7916cab3a1bSJed Brown     J = snes->jacobian;
7929566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
7939566063dSJacob Faibussowitsch     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
7949566063dSJacob Faibussowitsch     if (J) PetscCall(PetscObjectReference((PetscObject)J));
7959566063dSJacob Faibussowitsch     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
7969566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
7979566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
7989566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7999566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
8006cab3a1bSJed Brown   }
801caa4e7f2SJed Brown   {
802caa4e7f2SJed Brown     KSP ksp;
8039566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
8049566063dSJacob Faibussowitsch     PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
8059566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
806caa4e7f2SJed Brown   }
8073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8086cab3a1bSJed Brown }
8096cab3a1bSJed Brown 
810d6acfc2dSPierre Jolivet PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscMonitorPauseFinal_Internal(PetscInt, void *);
811ce78bad3SBarry Smith 
812d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
813d71ae5a4SJacob Faibussowitsch {
8145e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
8153ba16761SJacob Faibussowitsch   if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
816ce78bad3SBarry Smith   PetscCall(PetscMonitorPauseFinal_Internal(snes->numbermonitors, snes->monitorcontext));
8173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8185e7c47f3SMatthew G. Knepley }
8195e7c47f3SMatthew G. Knepley 
820fde5950dSBarry Smith /*@C
821fde5950dSBarry Smith   SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
822fde5950dSBarry Smith 
823c3339decSBarry Smith   Collective
824fde5950dSBarry Smith 
825fde5950dSBarry Smith   Input Parameters:
826dc4c0fb0SBarry Smith + snes         - `SNES` object you wish to monitor
827fde5950dSBarry Smith . name         - the monitor type one is seeking
828fde5950dSBarry Smith . help         - message indicating what monitoring is done
829fde5950dSBarry Smith . manual       - manual page for the monitor
83049abdd8aSBarry Smith . monitor      - the monitor function, this must use a `PetscViewerFormat` as its context
831f6dfbefdSBarry Smith - 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
832fde5950dSBarry Smith 
833420bcc1bSBarry Smith   Calling sequence of `monitor`:
834420bcc1bSBarry Smith + snes - the nonlinear solver context
835420bcc1bSBarry Smith . it   - the current iteration
836420bcc1bSBarry Smith . r    - the current function norm
837420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
838420bcc1bSBarry Smith 
839420bcc1bSBarry Smith   Calling sequence of `monitorsetup`:
840420bcc1bSBarry Smith + snes - the nonlinear solver context
841420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
842420bcc1bSBarry Smith 
843f6dfbefdSBarry Smith   Options Database Key:
844f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()`
845f6dfbefdSBarry Smith 
846f6dfbefdSBarry Smith   Level: advanced
847fde5950dSBarry Smith 
848648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
849db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
850e4094ef1SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
851db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
852c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
853db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
854db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
855fde5950dSBarry Smith @*/
856420bcc1bSBarry Smith 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))
857d71ae5a4SJacob Faibussowitsch {
858fde5950dSBarry Smith   PetscViewer       viewer;
859fde5950dSBarry Smith   PetscViewerFormat format;
860fde5950dSBarry Smith   PetscBool         flg;
861fde5950dSBarry Smith 
862fde5950dSBarry Smith   PetscFunctionBegin;
863648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
864fde5950dSBarry Smith   if (flg) {
865d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8669566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
867648c30bcSBarry Smith     PetscCall(PetscViewerDestroy(&viewer));
8681baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
86949abdd8aSBarry Smith     PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
870fde5950dSBarry Smith   }
8713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
872fde5950dSBarry Smith }
873fde5950dSBarry Smith 
874a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
875d71ae5a4SJacob Faibussowitsch {
876a4598233SStefano Zampini   const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
877a4598233SStefano Zampini 
8780f0abf79SStefano Zampini   PetscFunctionBegin;
8790f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
880a4598233SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
881a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
882a4598233SStefano Zampini   kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
883a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
884a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
885a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
8860f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
887a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
8880f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
8890f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
8900f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
8910f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
8920f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
8930f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
8940f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
8950f0abf79SStefano Zampini   PetscOptionsEnd();
8963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8970f0abf79SStefano Zampini }
8980f0abf79SStefano Zampini 
8999b94acceSBarry Smith /*@
900f6dfbefdSBarry Smith   SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
9019b94acceSBarry Smith 
902c3339decSBarry Smith   Collective
903c7afd0dbSLois Curfman McInnes 
9049b94acceSBarry Smith   Input Parameter:
905f6dfbefdSBarry Smith . snes - the `SNES` context
9069b94acceSBarry Smith 
90736851e7fSLois Curfman McInnes   Options Database Keys:
908f6dfbefdSBarry Smith + -snes_type <type>                                                            - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
909b39c3a46SLois Curfman McInnes . -snes_rtol <rtol>                                                            - relative decrease in tolerance norm from initial
91077e5a1f9SBarry Smith . -snes_atol <abstol>                                                          - absolute tolerance of residual norm
91177e5a1f9SBarry Smith . -snes_stol <stol>                                                            - convergence tolerance in terms of the norm of the change in the solution between steps
912e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol>                                          - if the residual goes above divtol*rnorm0, exit with divergence
913b39c3a46SLois Curfman McInnes . -snes_max_it <max_it>                                                        - maximum number of iterations
914b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs>                                                  - maximum number of function evaluations
91577e5a1f9SBarry Smith . -snes_force_iteration <force>                                                - force `SNESSolve()` to take at least one iteration
9164839bfe8SBarry Smith . -snes_max_fail <max_fail>                                                    - maximum number of line search failures allowed before stopping, default is none
917ddf469c8SBarry Smith . -snes_max_linear_solve_fail                                                  - number of linear solver failures before SNESSolve() stops
918a8054027SBarry Smith . -snes_lag_preconditioner <lag>                                               - how often preconditioner is rebuilt (use -1 to never rebuild)
9193d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false>                               - retains the -snes_lag_preconditioner information across multiple SNESSolve()
920e35cf81dSBarry Smith . -snes_lag_jacobian <lag>                                                     - how often Jacobian is rebuilt (use -1 to never rebuild)
9213d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false>                                     - retains the -snes_lag_jacobian information across multiple SNESSolve()
922ceaaa498SBarry Smith . -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.
923fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format]                             - prints residual norm at each iteration. if no filename given prints to stdout
924fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format]        - plots solution at each iteration
925fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format]        - plots residual (not its norm) at each iteration
926fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9274619e776SBarry Smith . -snes_monitor_lg_residualnorm                                                - plots residual norm at each iteration
928459f5d12SBarry Smith . -snes_monitor_lg_range                                                       - plots residual norm at each iteration
9295e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final                                                    - Pauses all monitor drawing after the solver ends
930e24b481bSBarry Smith . -snes_fd                                                                     - use finite differences to compute Jacobian; very slow, only for testing
931e2e60de9SPeter Brune . -snes_fd_color                                                               - use finite differences with coloring to compute Jacobian
932ceaaa498SBarry Smith . -snes_mf_ksp_monitor                                                         - if using matrix-free multiply then print h at each `KSP` iteration
933b5badacbSBarry Smith . -snes_converged_reason                                                       - print the reason for convergence/divergence after each solve
934ceaaa498SBarry Smith . -npc_snes_type <type>                                                        - the `SNES` type to use as a nonlinear preconditioner
935e62ac41dSBarry Smith . -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.
936e62ac41dSBarry Smith - -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.
93782738288SBarry Smith 
938f6dfbefdSBarry Smith   Options Database Keys for Eisenstat-Walker method:
939fa9f3622SBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
9404b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
94136851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
94236851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
94336851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma>         - Sets gamma
94436851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha>         - Sets alpha
94536851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
94636851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
94782738288SBarry Smith 
948dc4c0fb0SBarry Smith   Level: beginner
949dc4c0fb0SBarry Smith 
95011ca99fdSLois Curfman McInnes   Notes:
951ec5066bdSBarry Smith   To see all options, run your program with the -help option or consult the users manual
952ec5066bdSBarry Smith 
953420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
954420bcc1bSBarry Smith   and computing explicitly with
955f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
95683e2fdc7SBarry Smith 
957420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring`
9589b94acceSBarry Smith @*/
959d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
960d71ae5a4SJacob Faibussowitsch {
9618afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
96277e5a1f9SBarry Smith   PetscInt    i, indx, lag, grids, max_its, max_funcs;
96304d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
964649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
96585385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9660f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
967c40d0f55SPeter Brune   PCSide      pcside;
968a64e098fSPeter Brune   const char *optionsprefix;
96977e5a1f9SBarry Smith   PetscReal   rtol, abstol, stol;
9709b94acceSBarry Smith 
9713a40ed3dSBarry Smith   PetscFunctionBegin;
9720700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9739566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
974d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
975639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
977d64ed03dSBarry Smith   if (flg) {
9789566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
9797adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
9809566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
981d64ed03dSBarry Smith   }
982186905e3SBarry Smith 
98377e5a1f9SBarry Smith   abstol    = snes->abstol;
98477e5a1f9SBarry Smith   rtol      = snes->rtol;
98577e5a1f9SBarry Smith   stol      = snes->stol;
98677e5a1f9SBarry Smith   max_its   = snes->max_its;
98777e5a1f9SBarry Smith   max_funcs = snes->max_funcs;
98877e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL));
98977e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL));
99077e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL));
99177e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL));
99277e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL));
99377e5a1f9SBarry Smith   PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs));
99477e5a1f9SBarry Smith 
99577e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg));
99677e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol));
99777e5a1f9SBarry Smith 
99877e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg));
99977e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures));
100077e5a1f9SBarry Smith 
100177e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg));
100277e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures));
100377e5a1f9SBarry Smith 
10049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
10059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
10069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
100785385478SLisandro Dalcin 
10089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
1009a8054027SBarry Smith   if (flg) {
10105f80ce2aSJacob Faibussowitsch     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");
10119566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
1012a8054027SBarry Smith   }
10139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
10141baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
10159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
1016e35cf81dSBarry Smith   if (flg) {
10175f80ce2aSJacob Faibussowitsch     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");
10189566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
1019e35cf81dSBarry Smith   }
10209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
10211baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
102237ec4e1aSPeter Brune 
10239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
10241baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
1025a8054027SBarry Smith 
1026400f6f02SBarry Smith   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg));
102785385478SLisandro Dalcin   if (flg) {
102885385478SLisandro Dalcin     switch (indx) {
1029d71ae5a4SJacob Faibussowitsch     case 0:
1030d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1031d71ae5a4SJacob Faibussowitsch       break;
1032d71ae5a4SJacob Faibussowitsch     case 1:
1033d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1034d71ae5a4SJacob Faibussowitsch       break;
1035d71ae5a4SJacob Faibussowitsch     case 2:
1036d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1037d71ae5a4SJacob Faibussowitsch       break;
103885385478SLisandro Dalcin     }
103985385478SLisandro Dalcin   }
104085385478SLisandro Dalcin 
10419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10429566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1043fdacfa88SPeter Brune 
10449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10459566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1046186905e3SBarry Smith 
104785385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
104885385478SLisandro Dalcin 
10499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1050186905e3SBarry Smith 
10510f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10520f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1053a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1054186905e3SBarry Smith 
105590d69ab7SBarry Smith   flg = PETSC_FALSE;
10569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10579566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1058eabae89aSBarry Smith 
10599566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10609566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10619566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1062eabae89aSBarry Smith 
10639566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10649566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10659566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10669566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10679566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10689566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10699566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10712db13446SMatthew G. Knepley 
10729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10739566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10745180491cSLisandro Dalcin 
107590d69ab7SBarry Smith   flg = PETSC_FALSE;
10769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1077459f5d12SBarry Smith   if (flg) {
1078459f5d12SBarry Smith     PetscViewer ctx;
1079e24b481bSBarry Smith 
10809566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
108149abdd8aSBarry Smith     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscCtxDestroyFn *)PetscViewerDestroy));
1082459f5d12SBarry Smith   }
10832e7541e6SPeter Brune 
1084648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
1085648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL));
108690d69ab7SBarry Smith   flg = PETSC_FALSE;
10879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
10889566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1089c4421ceaSFande Kong 
1090c4421ceaSFande Kong   flg = PETSC_FALSE;
10919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
10924b27c08aSLois Curfman McInnes   if (flg) {
10936cab3a1bSJed Brown     void *functx;
1094b1f624c7SBarry Smith     DM    dm;
10959566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1096800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10979566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
10989566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
10999566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
11009b94acceSBarry Smith   }
1101639f9d9dSBarry Smith 
110244848bc4SPeter Brune   flg = PETSC_FALSE;
11039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
11041baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
110597584545SPeter Brune 
110697584545SPeter Brune   flg = PETSC_FALSE;
11079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
110844848bc4SPeter Brune   if (flg) {
1109c52e227fSPeter Brune     DM dm;
11109566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1111800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11129566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
11139566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
111444848bc4SPeter Brune   }
111544848bc4SPeter Brune 
1116aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11177addb90fSBarry Smith   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1118d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1119a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1120d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1121a8248277SBarry Smith   }
1122aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11237addb90fSBarry Smith   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1124d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
11259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1126d28543b3SPeter Brune 
11271dfd7622SMatthew Knepley   PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference functions", "None", &snes->testFunc));
11281dfd7622SMatthew Knepley   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &snes->testJac));
11291dfd7622SMatthew Knepley 
1130c40d0f55SPeter Brune   flg = PETSC_FALSE;
11319566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11339566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1134c40d0f55SPeter Brune 
1135e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11368a70d858SHong Zhang   /*
11378a70d858SHong Zhang     Publish convergence information using SAWs
11388a70d858SHong Zhang   */
11398a70d858SHong Zhang   flg = PETSC_FALSE;
11409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11418a70d858SHong Zhang   if (flg) {
11428a70d858SHong Zhang     void *ctx;
11439566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11449566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11458a70d858SHong Zhang   }
11468a70d858SHong Zhang #endif
11478a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1148b90c6cbeSBarry Smith   {
1149b90c6cbeSBarry Smith     PetscBool set;
1150b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11519566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11521baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1153b90c6cbeSBarry Smith   }
1154b90c6cbeSBarry Smith #endif
1155b90c6cbeSBarry Smith 
115648a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
115776b2cf59SMatthew Knepley 
1158dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11595d973c19SBarry Smith 
11605d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1161dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1162d0609cedSBarry Smith   PetscOptionsEnd();
11634bbc92c1SBarry Smith 
1164d8d34be6SBarry Smith   if (snes->linesearch) {
11659566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11669566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1167d8d34be6SBarry Smith   }
11689e764e56SPeter Brune 
11696aa5e7e9SBarry Smith   if (snes->usesksp) {
11709566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11719566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11729566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11736aa5e7e9SBarry Smith   }
11746991f827SBarry Smith 
1175b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11769566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
117848a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11791baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1180b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1182b3cd9a81SMatthew G. Knepley }
1183b3cd9a81SMatthew G. Knepley 
1184b3cd9a81SMatthew G. Knepley /*@
1185420bcc1bSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1186b3cd9a81SMatthew G. Knepley 
1187c3339decSBarry Smith   Collective
1188b3cd9a81SMatthew G. Knepley 
1189b3cd9a81SMatthew G. Knepley   Input Parameter:
1190f6dfbefdSBarry Smith . snes - the `SNES` context
1191b3cd9a81SMatthew G. Knepley 
1192420bcc1bSBarry Smith   Level: advanced
1193b3cd9a81SMatthew G. Knepley 
11941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1195b3cd9a81SMatthew G. Knepley @*/
1196d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1197d71ae5a4SJacob Faibussowitsch {
1198b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
11999566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
12003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12019b94acceSBarry Smith }
12029b94acceSBarry Smith 
1203bb9467b5SJed Brown /*@C
1204d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1205d25893d9SBarry Smith   the nonlinear solvers.
1206d25893d9SBarry Smith 
1207dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1208d25893d9SBarry Smith 
1209d25893d9SBarry Smith   Input Parameters:
1210f6dfbefdSBarry Smith + snes    - the `SNES` context
1211d25893d9SBarry Smith . compute - function to compute the context
121249abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence
1213d25893d9SBarry Smith 
1214420bcc1bSBarry Smith   Calling sequence of `compute`:
1215420bcc1bSBarry Smith + snes - the `SNES` context
1216420bcc1bSBarry Smith - ctx  - context to be computed
1217420bcc1bSBarry Smith 
1218d25893d9SBarry Smith   Level: intermediate
1219d25893d9SBarry Smith 
1220f6dfbefdSBarry Smith   Note:
1221f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1222f6dfbefdSBarry Smith 
1223f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1224f6dfbefdSBarry Smith 
122549abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn`
1226d25893d9SBarry Smith @*/
122749abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy)
1228d71ae5a4SJacob Faibussowitsch {
1229d25893d9SBarry Smith   PetscFunctionBegin;
1230d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1231d25893d9SBarry Smith   snes->ops->usercompute = compute;
123249abdd8aSBarry Smith   snes->ops->ctxdestroy  = destroy;
12333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1234d25893d9SBarry Smith }
1235a847f771SSatish Balay 
1236b07ff414SBarry Smith /*@
1237f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12389b94acceSBarry Smith 
1239c3339decSBarry Smith   Logically Collective
1240fee21e36SBarry Smith 
1241c7afd0dbSLois Curfman McInnes   Input Parameters:
1242f6dfbefdSBarry Smith + snes - the `SNES` context
1243ce78bad3SBarry Smith - ctx  - the user context
1244c7afd0dbSLois Curfman McInnes 
124536851e7fSLois Curfman McInnes   Level: intermediate
124636851e7fSLois Curfman McInnes 
1247f6dfbefdSBarry Smith   Notes:
1248ce78bad3SBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function
1249f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1250f6dfbefdSBarry Smith 
1251f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1252f6dfbefdSBarry Smith 
1253420bcc1bSBarry Smith   Fortran Note:
1254ce78bad3SBarry Smith   This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this
1255ce78bad3SBarry Smith   function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for
1256ce78bad3SBarry Smith   an example.
1257daf670e6SBarry Smith 
12581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12599b94acceSBarry Smith @*/
126049abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx)
1261d71ae5a4SJacob Faibussowitsch {
1262b07ff414SBarry Smith   KSP ksp;
12631b2093e4SBarry Smith 
12643a40ed3dSBarry Smith   PetscFunctionBegin;
12650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12669566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
126749abdd8aSBarry Smith   PetscCall(KSPSetApplicationContext(ksp, ctx));
126849abdd8aSBarry Smith   snes->ctx = ctx;
12693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12709b94acceSBarry Smith }
127174679c65SBarry Smith 
1272b07ff414SBarry Smith /*@
12739b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1274420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12759b94acceSBarry Smith 
1276c7afd0dbSLois Curfman McInnes   Not Collective
1277c7afd0dbSLois Curfman McInnes 
12789b94acceSBarry Smith   Input Parameter:
1279f6dfbefdSBarry Smith . snes - `SNES` context
12809b94acceSBarry Smith 
12819b94acceSBarry Smith   Output Parameter:
128249abdd8aSBarry Smith . ctx - user context
12839b94acceSBarry Smith 
128436851e7fSLois Curfman McInnes   Level: intermediate
128536851e7fSLois Curfman McInnes 
1286ce78bad3SBarry Smith   Fortran Notes:
1287ce78bad3SBarry Smith   This only works when the context is a Fortran derived type (it cannot be a `PetscObject`) and you **must** write a Fortran interface definition for this
1288ce78bad3SBarry Smith   function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example,
1289ce78bad3SBarry Smith .vb
1290ce78bad3SBarry Smith   Interface SNESGetApplicationContext
1291ce78bad3SBarry Smith     Subroutine SNESGetApplicationContext(snes,ctx,ierr)
1292ce78bad3SBarry Smith   #include <petsc/finclude/petscsnes.h>
1293ce78bad3SBarry Smith       use petscsnes
1294ce78bad3SBarry Smith       SNES snes
1295ce78bad3SBarry Smith       type(tUsertype), pointer :: ctx
1296ce78bad3SBarry Smith       PetscErrorCode ierr
1297ce78bad3SBarry Smith     End Subroutine
1298ce78bad3SBarry Smith   End Interface SNESGetApplicationContext
1299ce78bad3SBarry Smith .ve
1300ce78bad3SBarry Smith 
1301bfe80ac4SPierre Jolivet   The prototype for `ctx` must be
1302ce78bad3SBarry Smith .vb
1303ce78bad3SBarry Smith   type(tUsertype), pointer :: ctx
1304ce78bad3SBarry Smith .ve
1305dc4c0fb0SBarry Smith 
1306420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
13079b94acceSBarry Smith @*/
1308ce78bad3SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PeCtx ctx)
1309d71ae5a4SJacob Faibussowitsch {
13103a40ed3dSBarry Smith   PetscFunctionBegin;
13110700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
131249abdd8aSBarry Smith   *(void **)ctx = snes->ctx;
13133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13149b94acceSBarry Smith }
131574679c65SBarry Smith 
13169b94acceSBarry Smith /*@
1317420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
13183565c898SBarry Smith 
1319dc4c0fb0SBarry Smith   Logically Collective
13203565c898SBarry Smith 
13213565c898SBarry Smith   Input Parameters:
1322f6dfbefdSBarry Smith + snes        - `SNES` context
1323f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1324f6dfbefdSBarry Smith - 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
1325420bcc1bSBarry Smith                 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
13263565c898SBarry Smith 
1327f6dfbefdSBarry Smith   Options Database Keys:
132801c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1329f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1330ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1331ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
13323565c898SBarry Smith 
13333565c898SBarry Smith   Level: intermediate
13343565c898SBarry Smith 
1335f6dfbefdSBarry Smith   Note:
1336420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1337420bcc1bSBarry Smith   and computing explicitly with
1338f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1339ec5066bdSBarry Smith 
1340420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13413565c898SBarry Smith @*/
1342d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1343d71ae5a4SJacob Faibussowitsch {
13443565c898SBarry Smith   PetscFunctionBegin;
13453565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
134688b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
134788b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13484ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13493565c898SBarry Smith   snes->mf_operator = mf_operator;
13503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13513565c898SBarry Smith }
13523565c898SBarry Smith 
13533565c898SBarry Smith /*@
1354dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13553565c898SBarry Smith 
1356420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13573565c898SBarry Smith 
13583565c898SBarry Smith   Input Parameter:
1359f6dfbefdSBarry Smith . snes - `SNES` context
13603565c898SBarry Smith 
13613565c898SBarry Smith   Output Parameters:
1362f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1363f6dfbefdSBarry Smith - mf          - use matrix-free for both the Amat and Pmat used by `SNESSetJacobian()`, both the Amat and Pmat set in `SNESSetJacobian()` will be ignored
13643565c898SBarry Smith 
13653565c898SBarry Smith   Level: intermediate
13663565c898SBarry Smith 
13671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13683565c898SBarry Smith @*/
1369d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1370d71ae5a4SJacob Faibussowitsch {
13713565c898SBarry Smith   PetscFunctionBegin;
13723565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13733565c898SBarry Smith   if (mf) *mf = snes->mf;
13743565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13763565c898SBarry Smith }
13773565c898SBarry Smith 
13783565c898SBarry Smith /*@
1379420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13809b94acceSBarry Smith 
1381c7afd0dbSLois Curfman McInnes   Not Collective
1382c7afd0dbSLois Curfman McInnes 
13839b94acceSBarry Smith   Input Parameter:
1384f6dfbefdSBarry Smith . snes - `SNES` context
13859b94acceSBarry Smith 
13869b94acceSBarry Smith   Output Parameter:
13879b94acceSBarry Smith . iter - iteration number
13889b94acceSBarry Smith 
1389dc4c0fb0SBarry Smith   Level: intermediate
1390dc4c0fb0SBarry Smith 
1391c8228a4eSBarry Smith   Notes:
1392c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1393c8228a4eSBarry Smith 
1394c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1395f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
139608405cd6SLois Curfman McInnes .vb
139708405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
139808405cd6SLois Curfman McInnes       if (!(it % 2)) {
139908405cd6SLois Curfman McInnes         [compute Jacobian here]
140008405cd6SLois Curfman McInnes       }
140108405cd6SLois Curfman McInnes .ve
1402f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1403f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1404c8228a4eSBarry Smith 
1405f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1406c04deec6SBarry Smith 
1407420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
14089b94acceSBarry Smith @*/
1409d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1410d71ae5a4SJacob Faibussowitsch {
14113a40ed3dSBarry Smith   PetscFunctionBegin;
14120700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14134f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
14149b94acceSBarry Smith   *iter = snes->iter;
14153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14169b94acceSBarry Smith }
141774679c65SBarry Smith 
1418360c497dSPeter Brune /*@
1419360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1420360c497dSPeter Brune 
1421360c497dSPeter Brune   Not Collective
1422360c497dSPeter Brune 
1423d8d19677SJose E. Roman   Input Parameters:
1424f6dfbefdSBarry Smith + snes - `SNES` context
1425a2b725a8SWilliam Gropp - iter - iteration number
1426360c497dSPeter Brune 
1427360c497dSPeter Brune   Level: developer
1428360c497dSPeter Brune 
1429420bcc1bSBarry Smith   Note:
1430420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1431420bcc1bSBarry Smith 
14321cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1433360c497dSPeter Brune @*/
1434d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1435d71ae5a4SJacob Faibussowitsch {
1436360c497dSPeter Brune   PetscFunctionBegin;
1437360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14389566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1439360c497dSPeter Brune   snes->iter = iter;
14409566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1442360c497dSPeter Brune }
1443360c497dSPeter Brune 
14449b94acceSBarry Smith /*@
1445b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1446*76c63389SBarry Smith   taken by the nonlinear solver in the current or most recent `SNESSolve()` .
14479b94acceSBarry Smith 
1448c7afd0dbSLois Curfman McInnes   Not Collective
1449c7afd0dbSLois Curfman McInnes 
14509b94acceSBarry Smith   Input Parameter:
1451f6dfbefdSBarry Smith . snes - `SNES` context
14529b94acceSBarry Smith 
14539b94acceSBarry Smith   Output Parameter:
14549b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14559b94acceSBarry Smith 
1456dc4c0fb0SBarry Smith   Level: intermediate
1457dc4c0fb0SBarry Smith 
1458*76c63389SBarry Smith   Notes:
1459*76c63389SBarry Smith   A failed step is a step that was generated and taken but did not satisfy the requested step criteria. For example,
1460*76c63389SBarry Smith   the `SNESLineSearchApply()` could not generate a sufficient decrease in the function norm (in fact it may have produced an increase).
1461*76c63389SBarry Smith 
1462*76c63389SBarry Smith   Taken steps that produce a infinity or NaN in the function evaluation or generate a `SNESSetFunctionDomainError()`
1463*76c63389SBarry Smith   will always immediately terminate the `SNESSolve()` regardless of the value of `maxFails`.
1464*76c63389SBarry Smith 
1465*76c63389SBarry Smith   `SNESSetMaxNonlinearStepFailures()` determines how many unsuccessful steps are allowed before the `SNESSolve()` terminates
1466*76c63389SBarry Smith 
1467f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1468c96a6f78SLois Curfman McInnes 
14691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1470db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14719b94acceSBarry Smith @*/
1472d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1473d71ae5a4SJacob Faibussowitsch {
14743a40ed3dSBarry Smith   PetscFunctionBegin;
14750700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14764f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
147750ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
147950ffb88aSMatthew Knepley }
148050ffb88aSMatthew Knepley 
148150ffb88aSMatthew Knepley /*@
1482b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1483420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
148450ffb88aSMatthew Knepley 
148550ffb88aSMatthew Knepley   Not Collective
148650ffb88aSMatthew Knepley 
148750ffb88aSMatthew Knepley   Input Parameters:
1488f6dfbefdSBarry Smith + snes     - `SNES` context
148977e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures
149050ffb88aSMatthew Knepley 
1491420bcc1bSBarry Smith   Options Database Key:
1492420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1493420bcc1bSBarry Smith 
149450ffb88aSMatthew Knepley   Level: intermediate
149550ffb88aSMatthew Knepley 
1496*76c63389SBarry Smith   Note:
1497*76c63389SBarry Smith   A failed step is a step that was generated and taken but did not satisfy the requested criteria. For example,
1498*76c63389SBarry Smith   the `SNESLineSearchApply()` could not generate a sufficient decrease in the function norm (in fact it may have produced an increase).
1499*76c63389SBarry Smith 
1500*76c63389SBarry Smith   Taken steps that produce a infinity or NaN in the function evaluation or generate a `SNESSetFunctionDomainError()`
1501*76c63389SBarry Smith   will always immediately terminate the `SNESSolve()` regardless of the value of `maxFails`.
1502*76c63389SBarry Smith 
1503420bcc1bSBarry Smith   Developer Note:
1504420bcc1bSBarry Smith   The options database key is wrong for this function name
1505420bcc1bSBarry Smith 
1506*76c63389SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
1507*76c63389SBarry Smith           `SNESGetLinearSolveFailures()`, `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`, `SNESCheckLineSearchFailure()`
150850ffb88aSMatthew Knepley @*/
1509d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1510d71ae5a4SJacob Faibussowitsch {
151150ffb88aSMatthew Knepley   PetscFunctionBegin;
15120700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
151377e5a1f9SBarry Smith 
151477e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
15151690c2aeSBarry Smith     snes->maxFailures = PETSC_INT_MAX;
151677e5a1f9SBarry Smith   } else {
151777e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
151850ffb88aSMatthew Knepley     snes->maxFailures = maxFails;
151977e5a1f9SBarry Smith   }
15203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
152150ffb88aSMatthew Knepley }
152250ffb88aSMatthew Knepley 
152350ffb88aSMatthew Knepley /*@
1524b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1525420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
152650ffb88aSMatthew Knepley 
152750ffb88aSMatthew Knepley   Not Collective
152850ffb88aSMatthew Knepley 
152950ffb88aSMatthew Knepley   Input Parameter:
153020f4b53cSBarry Smith . snes - `SNES` context
153150ffb88aSMatthew Knepley 
153250ffb88aSMatthew Knepley   Output Parameter:
153350ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
153450ffb88aSMatthew Knepley 
153550ffb88aSMatthew Knepley   Level: intermediate
153650ffb88aSMatthew Knepley 
15371cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1538db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
153950ffb88aSMatthew Knepley @*/
1540d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1541d71ae5a4SJacob Faibussowitsch {
154250ffb88aSMatthew Knepley   PetscFunctionBegin;
15430700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15444f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
154550ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
15463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15479b94acceSBarry Smith }
1548a847f771SSatish Balay 
15492541af92SBarry Smith /*@
15502541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1551420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
15522541af92SBarry Smith 
15532541af92SBarry Smith   Not Collective
15542541af92SBarry Smith 
15552541af92SBarry Smith   Input Parameter:
1556f6dfbefdSBarry Smith . snes - `SNES` context
15572541af92SBarry Smith 
15582541af92SBarry Smith   Output Parameter:
15592541af92SBarry Smith . nfuncs - number of evaluations
15602541af92SBarry Smith 
15612541af92SBarry Smith   Level: intermediate
15622541af92SBarry Smith 
1563f6dfbefdSBarry Smith   Note:
1564f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1565971e163fSPeter Brune 
15661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15672541af92SBarry Smith @*/
1568d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1569d71ae5a4SJacob Faibussowitsch {
15702541af92SBarry Smith   PetscFunctionBegin;
15710700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15724f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15732541af92SBarry Smith   *nfuncs = snes->nfuncs;
15743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15752541af92SBarry Smith }
15762541af92SBarry Smith 
15773d4c4710SBarry Smith /*@
15783d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1579420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15803d4c4710SBarry Smith 
15813d4c4710SBarry Smith   Not Collective
15823d4c4710SBarry Smith 
15833d4c4710SBarry Smith   Input Parameter:
1584f6dfbefdSBarry Smith . snes - `SNES` context
15853d4c4710SBarry Smith 
15863d4c4710SBarry Smith   Output Parameter:
15873d4c4710SBarry Smith . nfails - number of failed solves
15883d4c4710SBarry Smith 
1589f6dfbefdSBarry Smith   Options Database Key:
15909d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15919d85da0cSMatthew G. Knepley 
1592f6dfbefdSBarry Smith   Level: intermediate
1593f6dfbefdSBarry Smith 
1594f6dfbefdSBarry Smith   Note:
1595f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15963d4c4710SBarry Smith 
15971cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15983d4c4710SBarry Smith @*/
1599d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1600d71ae5a4SJacob Faibussowitsch {
16013d4c4710SBarry Smith   PetscFunctionBegin;
16020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16034f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
16043d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
16053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16063d4c4710SBarry Smith }
16073d4c4710SBarry Smith 
16083d4c4710SBarry Smith /*@
16093d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1610f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
16113d4c4710SBarry Smith 
1612c3339decSBarry Smith   Logically Collective
16133d4c4710SBarry Smith 
16143d4c4710SBarry Smith   Input Parameters:
1615f6dfbefdSBarry Smith + snes     - `SNES` context
161677e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures
16173d4c4710SBarry Smith 
1618f6dfbefdSBarry Smith   Options Database Key:
16199d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
16209d85da0cSMatthew G. Knepley 
1621dc4c0fb0SBarry Smith   Level: intermediate
1622dc4c0fb0SBarry Smith 
1623f6dfbefdSBarry Smith   Note:
1624f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
16253d4c4710SBarry Smith 
1626420bcc1bSBarry Smith   Developer Note:
1627420bcc1bSBarry Smith   The options database key is wrong for this function name
1628420bcc1bSBarry Smith 
16291cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
16303d4c4710SBarry Smith @*/
1631d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1632d71ae5a4SJacob Faibussowitsch {
16333d4c4710SBarry Smith   PetscFunctionBegin;
16340700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1635c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
163677e5a1f9SBarry Smith 
163777e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
16381690c2aeSBarry Smith     snes->maxLinearSolveFailures = PETSC_INT_MAX;
163977e5a1f9SBarry Smith   } else {
164077e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
16413d4c4710SBarry Smith     snes->maxLinearSolveFailures = maxFails;
164277e5a1f9SBarry Smith   }
16433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16443d4c4710SBarry Smith }
16453d4c4710SBarry Smith 
16463d4c4710SBarry Smith /*@
16473d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1648f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
16493d4c4710SBarry Smith 
16503d4c4710SBarry Smith   Not Collective
16513d4c4710SBarry Smith 
16523d4c4710SBarry Smith   Input Parameter:
1653f6dfbefdSBarry Smith . snes - `SNES` context
16543d4c4710SBarry Smith 
16553d4c4710SBarry Smith   Output Parameter:
16563d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16573d4c4710SBarry Smith 
16583d4c4710SBarry Smith   Level: intermediate
16593d4c4710SBarry Smith 
1660f6dfbefdSBarry Smith   Note:
1661f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16623d4c4710SBarry Smith 
16631cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16643d4c4710SBarry Smith @*/
1665d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1666d71ae5a4SJacob Faibussowitsch {
16673d4c4710SBarry Smith   PetscFunctionBegin;
16680700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16694f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16703d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16723d4c4710SBarry Smith }
16733d4c4710SBarry Smith 
1674c96a6f78SLois Curfman McInnes /*@
1675b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1676420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1677c96a6f78SLois Curfman McInnes 
1678c7afd0dbSLois Curfman McInnes   Not Collective
1679c7afd0dbSLois Curfman McInnes 
1680c96a6f78SLois Curfman McInnes   Input Parameter:
1681f6dfbefdSBarry Smith . snes - `SNES` context
1682c96a6f78SLois Curfman McInnes 
1683c96a6f78SLois Curfman McInnes   Output Parameter:
1684c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1685c96a6f78SLois Curfman McInnes 
1686dc4c0fb0SBarry Smith   Level: intermediate
1687dc4c0fb0SBarry Smith 
1688c96a6f78SLois Curfman McInnes   Notes:
1689f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1690c96a6f78SLois Curfman McInnes 
1691f6dfbefdSBarry Smith   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
1692f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1693010be392SBarry Smith 
16941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1695c96a6f78SLois Curfman McInnes @*/
1696d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1697d71ae5a4SJacob Faibussowitsch {
16983a40ed3dSBarry Smith   PetscFunctionBegin;
16990700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17004f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1701c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
17023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1703c96a6f78SLois Curfman McInnes }
1704c96a6f78SLois Curfman McInnes 
1705971e163fSPeter Brune /*@
1706971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1707f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1708971e163fSPeter Brune 
1709c3339decSBarry Smith   Logically Collective
1710971e163fSPeter Brune 
1711d8d19677SJose E. Roman   Input Parameters:
1712f6dfbefdSBarry Smith + snes  - `SNES` context
1713f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1714971e163fSPeter Brune 
1715971e163fSPeter Brune   Level: developer
1716971e163fSPeter Brune 
17171cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1718971e163fSPeter Brune @*/
1719d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1720d71ae5a4SJacob Faibussowitsch {
1721971e163fSPeter Brune   PetscFunctionBegin;
1722971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1723971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1724971e163fSPeter Brune   snes->counters_reset = reset;
17253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1726971e163fSPeter Brune }
1727971e163fSPeter Brune 
17282999313aSBarry Smith /*@
172912b1dd1aSStefano Zampini   SNESResetCounters - Reset counters for linear iterations and function evaluations.
173012b1dd1aSStefano Zampini 
173112b1dd1aSStefano Zampini   Logically Collective
173212b1dd1aSStefano Zampini 
173312b1dd1aSStefano Zampini   Input Parameters:
173412b1dd1aSStefano Zampini . snes - `SNES` context
173512b1dd1aSStefano Zampini 
173612b1dd1aSStefano Zampini   Level: developer
173712b1dd1aSStefano Zampini 
173812b1dd1aSStefano Zampini   Note:
173912b1dd1aSStefano Zampini   It honors the flag set with `SNESSetCountersReset()`
174012b1dd1aSStefano Zampini 
174112b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
174212b1dd1aSStefano Zampini @*/
174312b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes)
174412b1dd1aSStefano Zampini {
174512b1dd1aSStefano Zampini   PetscFunctionBegin;
174612b1dd1aSStefano Zampini   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
174712b1dd1aSStefano Zampini   if (snes->counters_reset) {
174812b1dd1aSStefano Zampini     snes->nfuncs      = 0;
174912b1dd1aSStefano Zampini     snes->linear_its  = 0;
175012b1dd1aSStefano Zampini     snes->numFailures = 0;
175112b1dd1aSStefano Zampini   }
175212b1dd1aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
175312b1dd1aSStefano Zampini }
175412b1dd1aSStefano Zampini 
175512b1dd1aSStefano Zampini /*@
1756f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
17572999313aSBarry Smith 
1758420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
17592999313aSBarry Smith 
17602999313aSBarry Smith   Input Parameters:
1761f6dfbefdSBarry Smith + snes - the `SNES` context
1762f6dfbefdSBarry Smith - ksp  - the `KSP` context
17632999313aSBarry Smith 
1764dc4c0fb0SBarry Smith   Level: developer
1765dc4c0fb0SBarry Smith 
17662999313aSBarry Smith   Notes:
1767f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
17682999313aSBarry Smith   so this routine is rarely needed.
17692999313aSBarry Smith 
1770f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1771420bcc1bSBarry Smith   decreased by one when this is called.
17722999313aSBarry Smith 
177342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
17742999313aSBarry Smith @*/
1775d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1776d71ae5a4SJacob Faibussowitsch {
17772999313aSBarry Smith   PetscFunctionBegin;
17780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17790700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
17802999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
17819566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
17829566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17832999313aSBarry Smith   snes->ksp = ksp;
17843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17852999313aSBarry Smith }
17862999313aSBarry Smith 
178752baeb72SSatish Balay /*@
178877e5a1f9SBarry Smith   SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they
178977e5a1f9SBarry Smith   currently contain default values
179077e5a1f9SBarry Smith 
179177e5a1f9SBarry Smith   Collective
179277e5a1f9SBarry Smith 
179377e5a1f9SBarry Smith   Input Parameter:
179477e5a1f9SBarry Smith . snes - the `SNES` object
179577e5a1f9SBarry Smith 
179677e5a1f9SBarry Smith   Level: developer
179777e5a1f9SBarry Smith 
179877e5a1f9SBarry Smith   Developer Note:
179977e5a1f9SBarry Smith   This is called by all the `SNESCreate_XXX()` routines.
180077e5a1f9SBarry Smith 
180177e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`,
180277e5a1f9SBarry Smith           `PetscObjectParameterSetDefault()`
180377e5a1f9SBarry Smith @*/
180477e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes)
180577e5a1f9SBarry Smith {
180677e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_its, 50);
180777e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_funcs, 10000);
180877e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
180977e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50);
181077e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
181177e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, divtol, 1.e4);
181277e5a1f9SBarry Smith   return PETSC_SUCCESS;
181377e5a1f9SBarry Smith }
181477e5a1f9SBarry Smith 
181577e5a1f9SBarry Smith /*@
1816dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
18179b94acceSBarry Smith 
1818d083f849SBarry Smith   Collective
1819c7afd0dbSLois Curfman McInnes 
1820f6dfbefdSBarry Smith   Input Parameter:
1821906ed7ccSBarry Smith . comm - MPI communicator
18229b94acceSBarry Smith 
18239b94acceSBarry Smith   Output Parameter:
182420f4b53cSBarry Smith . outsnes - the new `SNES` context
18259b94acceSBarry Smith 
1826c7afd0dbSLois Curfman McInnes   Options Database Keys:
18277addb90fSBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner
18287addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()`
1829dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1830c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1831c1f60f51SBarry Smith 
183236851e7fSLois Curfman McInnes   Level: beginner
183336851e7fSLois Curfman McInnes 
183495452b02SPatrick Sanan   Developer Notes:
1835f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1836efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1837f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1838f6dfbefdSBarry Smith   in `SNESView()`.
1839efd4aadfSBarry Smith 
1840f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1841f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1842f6dfbefdSBarry Smith 
18437addb90fSBarry Smith   `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed.
1844efd4aadfSBarry Smith 
1845e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
18469b94acceSBarry Smith @*/
1847d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1848d71ae5a4SJacob Faibussowitsch {
18499b94acceSBarry Smith   SNES       snes;
1850fa9f3622SBarry Smith   SNESKSPEW *kctx;
185137fcc0dbSBarry Smith 
18523a40ed3dSBarry Smith   PetscFunctionBegin;
18534f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
18549566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
18558ba1e511SMatthew Knepley 
18569566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
18578d359177SBarry Smith   snes->ops->converged = SNESConvergedDefault;
18582c155ee1SBarry Smith   snes->usesksp        = PETSC_TRUE;
18599b94acceSBarry Smith   snes->norm           = 0.0;
1860c1e67a49SFande Kong   snes->xnorm          = 0.0;
1861c1e67a49SFande Kong   snes->ynorm          = 0.0;
1862365a6726SPeter Brune   snes->normschedule   = SNES_NORM_ALWAYS;
18636c67d002SPeter Brune   snes->functype       = SNES_FUNCTION_DEFAULT;
1864b4874afaSBarry Smith   snes->ttol           = 0.0;
186577e5a1f9SBarry Smith 
1866e37c518bSBarry Smith   snes->rnorm0               = 0;
18679b94acceSBarry Smith   snes->nfuncs               = 0;
186850ffb88aSMatthew Knepley   snes->numFailures          = 0;
186950ffb88aSMatthew Knepley   snes->maxFailures          = 1;
18707a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1871e35cf81dSBarry Smith   snes->lagjacobian          = 1;
187237ec4e1aSPeter Brune   snes->jac_iter             = 0;
187337ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1874a8054027SBarry Smith   snes->lagpreconditioner    = 1;
187537ec4e1aSPeter Brune   snes->pre_iter             = 0;
187637ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1877639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1878c4421ceaSFande Kong   snes->numberreasonviews    = 0;
18799e5d0892SLisandro Dalcin   snes->data                 = NULL;
18804dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1881186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
18826f24a144SLois Curfman McInnes   snes->nwork                = 0;
18839e5d0892SLisandro Dalcin   snes->work                 = NULL;
188458c9b817SLisandro Dalcin   snes->nvwork               = 0;
18859e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1886758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1887758f92a0SBarry Smith   snes->conv_hist_max        = 0;
18880298fd71SBarry Smith   snes->conv_hist            = NULL;
18890298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1890758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1891971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1892e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1893184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1894efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1895b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1896c40d0f55SPeter Brune 
1897d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1898d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1899d8f46077SPeter Brune   snes->mf_version  = 1;
1900d8f46077SPeter Brune 
19013d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
19023d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
19033d4c4710SBarry Smith 
1904349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
190576bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1906349187a7SBarry Smith 
19074fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
19084fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
19094fc747eaSLawrence Mitchell 
19109b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
19114dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1912f5af7f23SKarl Rupp 
1913835f2295SStefano Zampini   snes->kspconvctx  = kctx;
19149b94acceSBarry Smith   kctx->version     = 2;
19150f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
19169b94acceSBarry Smith                              this was too large for some test cases */
191775567043SBarry Smith   kctx->rtol_last   = 0.0;
19180f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
19199b94acceSBarry Smith   kctx->gamma       = 1.0;
19200f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
192171f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
19220f0abf79SStefano Zampini   kctx->threshold   = 0.1;
192375567043SBarry Smith   kctx->lresid_last = 0.0;
192475567043SBarry Smith   kctx->norm_last   = 0.0;
19259b94acceSBarry Smith 
19260f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
19270f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
19280f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
19290f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
19300f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
19310f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
19320f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
19330f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
19340f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
19350f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
19360f0abf79SStefano Zampini 
1937b50c806fSBarry Smith   PetscCall(SNESParametersInitialize(snes));
19389b94acceSBarry Smith   *outsnes = snes;
19393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19409b94acceSBarry Smith }
19419b94acceSBarry Smith 
19429b94acceSBarry Smith /*@C
19439b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1944f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
19459b94acceSBarry Smith   equations.
19469b94acceSBarry Smith 
1947c3339decSBarry Smith   Logically Collective
1948fee21e36SBarry Smith 
1949c7afd0dbSLois Curfman McInnes   Input Parameters:
1950f6dfbefdSBarry Smith + snes - the `SNES` context
1951dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
19528434afd1SBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunctionFn`
1953c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1954dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
19559b94acceSBarry Smith 
195636851e7fSLois Curfman McInnes   Level: beginner
195736851e7fSLois Curfman McInnes 
19588434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
19599b94acceSBarry Smith @*/
19608434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx)
1961d71ae5a4SJacob Faibussowitsch {
19626cab3a1bSJed Brown   DM dm;
19636cab3a1bSJed Brown 
19643a40ed3dSBarry Smith   PetscFunctionBegin;
19650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1966d2a683ecSLisandro Dalcin   if (r) {
1967d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1968d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
19699566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
19709566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
197185385478SLisandro Dalcin     snes->vec_func = r;
1972d2a683ecSLisandro Dalcin   }
19739566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
19749566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
197548a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
19763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19779b94acceSBarry Smith }
19789b94acceSBarry Smith 
1979e4ed7901SPeter Brune /*@C
19800b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1981e4ed7901SPeter Brune 
1982c3339decSBarry Smith   Logically Collective
1983e4ed7901SPeter Brune 
1984e4ed7901SPeter Brune   Input Parameters:
1985f6dfbefdSBarry Smith + snes - the `SNES` context
1986e4ed7901SPeter Brune - f    - vector to store function value
1987e4ed7901SPeter Brune 
1988dc4c0fb0SBarry Smith   Level: developer
1989dc4c0fb0SBarry Smith 
1990e4ed7901SPeter Brune   Notes:
1991e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1992e4ed7901SPeter Brune 
1993f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1994e4ed7901SPeter Brune 
19951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1996e4ed7901SPeter Brune @*/
1997d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1998d71ae5a4SJacob Faibussowitsch {
1999e4ed7901SPeter Brune   Vec vec_func;
2000e4ed7901SPeter Brune 
2001e4ed7901SPeter Brune   PetscFunctionBegin;
2002e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2003e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
2004e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
2005efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
2006902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
20073ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2008902f982fSPeter Brune   }
20099566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
20109566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
2011f5af7f23SKarl Rupp 
2012217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
20133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2014e4ed7901SPeter Brune }
2015e4ed7901SPeter Brune 
2016534ebe21SPeter Brune /*@
2017f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
2018f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
2019534ebe21SPeter Brune 
2020c3339decSBarry Smith   Logically Collective
2021534ebe21SPeter Brune 
2022534ebe21SPeter Brune   Input Parameters:
2023f6dfbefdSBarry Smith + snes         - the `SNES` context
2024365a6726SPeter Brune - normschedule - the frequency of norm computation
2025534ebe21SPeter Brune 
2026517f1916SMatthew G. Knepley   Options Database Key:
202767b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
2028517f1916SMatthew G. Knepley 
2029dc4c0fb0SBarry Smith   Level: advanced
2030dc4c0fb0SBarry Smith 
2031534ebe21SPeter Brune   Notes:
2032f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
2033534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
2034534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
2035f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
2036534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
2037534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
2038534ebe21SPeter Brune   their solution.
2039534ebe21SPeter Brune 
2040e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
2041534ebe21SPeter Brune @*/
2042d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
2043d71ae5a4SJacob Faibussowitsch {
2044534ebe21SPeter Brune   PetscFunctionBegin;
2045534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2046365a6726SPeter Brune   snes->normschedule = normschedule;
20473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2048534ebe21SPeter Brune }
2049534ebe21SPeter Brune 
2050534ebe21SPeter Brune /*@
2051f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
2052f6dfbefdSBarry Smith   of the `SNES` method.
2053534ebe21SPeter Brune 
2054c3339decSBarry Smith   Logically Collective
2055534ebe21SPeter Brune 
2056534ebe21SPeter Brune   Input Parameters:
2057f6dfbefdSBarry Smith + snes         - the `SNES` context
2058365a6726SPeter Brune - normschedule - the type of the norm used
2059534ebe21SPeter Brune 
2060534ebe21SPeter Brune   Level: advanced
2061534ebe21SPeter Brune 
20621cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2063534ebe21SPeter Brune @*/
2064d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
2065d71ae5a4SJacob Faibussowitsch {
2066534ebe21SPeter Brune   PetscFunctionBegin;
2067534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2068365a6726SPeter Brune   *normschedule = snes->normschedule;
20693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2070534ebe21SPeter Brune }
2071534ebe21SPeter Brune 
2072c5ce4427SMatthew G. Knepley /*@
2073c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
2074c5ce4427SMatthew G. Knepley 
2075c3339decSBarry Smith   Logically Collective
2076c5ce4427SMatthew G. Knepley 
2077c5ce4427SMatthew G. Knepley   Input Parameters:
2078f6dfbefdSBarry Smith + snes - the `SNES` context
2079f6dfbefdSBarry Smith - norm - the value of the norm
2080c5ce4427SMatthew G. Knepley 
2081c5ce4427SMatthew G. Knepley   Level: developer
2082c5ce4427SMatthew G. Knepley 
20831cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2084c5ce4427SMatthew G. Knepley @*/
2085d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
2086d71ae5a4SJacob Faibussowitsch {
2087c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2088c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2089c5ce4427SMatthew G. Knepley   snes->norm = norm;
20903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2091c5ce4427SMatthew G. Knepley }
2092c5ce4427SMatthew G. Knepley 
2093c5ce4427SMatthew G. Knepley /*@
2094c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
2095c5ce4427SMatthew G. Knepley 
2096c5ce4427SMatthew G. Knepley   Not Collective
2097c5ce4427SMatthew G. Knepley 
2098c5ce4427SMatthew G. Knepley   Input Parameter:
2099f6dfbefdSBarry Smith . snes - the `SNES` context
2100c5ce4427SMatthew G. Knepley 
2101c5ce4427SMatthew G. Knepley   Output Parameter:
2102c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2103c5ce4427SMatthew G. Knepley 
2104c5ce4427SMatthew G. Knepley   Level: developer
2105c5ce4427SMatthew G. Knepley 
21061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2107c5ce4427SMatthew G. Knepley @*/
2108d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2109d71ae5a4SJacob Faibussowitsch {
2110c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2111c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21124f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2113c5ce4427SMatthew G. Knepley   *norm = snes->norm;
21143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2115c5ce4427SMatthew G. Knepley }
2116c5ce4427SMatthew G. Knepley 
2117c1e67a49SFande Kong /*@
2118f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2119c1e67a49SFande Kong 
2120c1e67a49SFande Kong   Not Collective
2121c1e67a49SFande Kong 
2122c1e67a49SFande Kong   Input Parameter:
2123f6dfbefdSBarry Smith . snes - the `SNES` context
2124c1e67a49SFande Kong 
2125c1e67a49SFande Kong   Output Parameter:
2126c1e67a49SFande Kong . ynorm - the last computed update norm
2127c1e67a49SFande Kong 
2128c1e67a49SFande Kong   Level: developer
2129c1e67a49SFande Kong 
2130f6dfbefdSBarry Smith   Note:
2131f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2132f6dfbefdSBarry Smith 
21331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2134c1e67a49SFande Kong @*/
2135d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2136d71ae5a4SJacob Faibussowitsch {
2137c1e67a49SFande Kong   PetscFunctionBegin;
2138c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21394f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2140c1e67a49SFande Kong   *ynorm = snes->ynorm;
21413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2142c1e67a49SFande Kong }
2143c1e67a49SFande Kong 
2144c1e67a49SFande Kong /*@
21454591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2146c1e67a49SFande Kong 
2147c1e67a49SFande Kong   Not Collective
2148c1e67a49SFande Kong 
2149c1e67a49SFande Kong   Input Parameter:
2150f6dfbefdSBarry Smith . snes - the `SNES` context
2151c1e67a49SFande Kong 
2152c1e67a49SFande Kong   Output Parameter:
2153c1e67a49SFande Kong . xnorm - the last computed solution norm
2154c1e67a49SFande Kong 
2155c1e67a49SFande Kong   Level: developer
2156c1e67a49SFande Kong 
21571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2158c1e67a49SFande Kong @*/
2159d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2160d71ae5a4SJacob Faibussowitsch {
2161c1e67a49SFande Kong   PetscFunctionBegin;
2162c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21634f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2164c1e67a49SFande Kong   *xnorm = snes->xnorm;
21653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2166c1e67a49SFande Kong }
2167c1e67a49SFande Kong 
2168cc4c1da9SBarry Smith /*@
2169f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2170f6dfbefdSBarry Smith   of the `SNES` method.
217147073ea2SPeter Brune 
2172c3339decSBarry Smith   Logically Collective
217347073ea2SPeter Brune 
217447073ea2SPeter Brune   Input Parameters:
2175f6dfbefdSBarry Smith + snes - the `SNES` context
2176f6dfbefdSBarry Smith - type - the function type
217747073ea2SPeter Brune 
217847073ea2SPeter Brune   Level: developer
217947073ea2SPeter Brune 
2180420bcc1bSBarry Smith   Values of the function type\:
2181f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT`          - the default for the given `SNESType`
2182f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2183f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED`   - a transformation of the function provided with `SNESSetFunction()`
2184f6dfbefdSBarry Smith 
2185420bcc1bSBarry Smith   Note:
2186f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2187f6dfbefdSBarry Smith 
21881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
218947073ea2SPeter Brune @*/
2190d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2191d71ae5a4SJacob Faibussowitsch {
219247073ea2SPeter Brune   PetscFunctionBegin;
219347073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
219447073ea2SPeter Brune   snes->functype = type;
21953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
219647073ea2SPeter Brune }
219747073ea2SPeter Brune 
2198cc4c1da9SBarry Smith /*@
2199f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
220047073ea2SPeter Brune   of the SNES method.
220147073ea2SPeter Brune 
2202c3339decSBarry Smith   Logically Collective
220347073ea2SPeter Brune 
220447073ea2SPeter Brune   Input Parameters:
2205f6dfbefdSBarry Smith + snes - the `SNES` context
2206f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
220747073ea2SPeter Brune 
220847073ea2SPeter Brune   Level: advanced
220947073ea2SPeter Brune 
22101cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
221147073ea2SPeter Brune @*/
2212d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2213d71ae5a4SJacob Faibussowitsch {
221447073ea2SPeter Brune   PetscFunctionBegin;
221547073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
221647073ea2SPeter Brune   *type = snes->functype;
22173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2218534ebe21SPeter Brune }
2219534ebe21SPeter Brune 
2220c79ef259SPeter Brune /*@C
2221be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2222c79ef259SPeter Brune   use with composed nonlinear solvers.
2223c79ef259SPeter Brune 
2224c79ef259SPeter Brune   Input Parameters:
22259bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
22268434afd1SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
222777e5a1f9SBarry Smith - ctx  - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`)
2228c79ef259SPeter Brune 
2229dc4c0fb0SBarry Smith   Level: intermediate
2230dc4c0fb0SBarry Smith 
2231f6dfbefdSBarry Smith   Note:
2232f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2233f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2234c79ef259SPeter Brune 
22358434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2236c79ef259SPeter Brune @*/
22378434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx)
2238d71ae5a4SJacob Faibussowitsch {
22396cab3a1bSJed Brown   DM dm;
22406cab3a1bSJed Brown 
2241646217ecSPeter Brune   PetscFunctionBegin;
22426cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22439566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22449566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
22453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2246646217ecSPeter Brune }
2247646217ecSPeter Brune 
2248bbc1464cSBarry Smith /*
2249bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2250bbc1464cSBarry Smith    changed during the KSPSolve()
2251bbc1464cSBarry Smith */
2252d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2253d71ae5a4SJacob Faibussowitsch {
2254bbc1464cSBarry Smith   DM     dm;
2255bbc1464cSBarry Smith   DMSNES sdm;
2256bbc1464cSBarry Smith 
2257bbc1464cSBarry Smith   PetscFunctionBegin;
22589566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22599566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2260bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2261bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2262792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22639566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
22640df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2265ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2266792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22679566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2268bbc1464cSBarry Smith   } else {
2269792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22709566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2271bbc1464cSBarry Smith   }
22723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2273bbc1464cSBarry Smith }
2274bbc1464cSBarry Smith 
2275d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2276d71ae5a4SJacob Faibussowitsch {
2277e03ab78fSPeter Brune   DM     dm;
2278942e3340SBarry Smith   DMSNES sdm;
22796cab3a1bSJed Brown 
22808b0a5094SBarry Smith   PetscFunctionBegin;
22819566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22829566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22838b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2284bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2285792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22869566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2287792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22889566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2289bbc1464cSBarry Smith   } else {
2290792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22919566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2292bbc1464cSBarry Smith   }
22933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22948b0a5094SBarry Smith }
22958b0a5094SBarry Smith 
2296d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2297d71ae5a4SJacob Faibussowitsch {
22988b0a5094SBarry Smith   PetscFunctionBegin;
2299e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2300bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
23019566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
23029566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
23033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23048b0a5094SBarry Smith }
23058b0a5094SBarry Smith 
23068b0a5094SBarry Smith /*@C
23071d27aa22SBarry Smith   SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
23088b0a5094SBarry Smith 
2309c3339decSBarry Smith   Logically Collective
23108b0a5094SBarry Smith 
23118b0a5094SBarry Smith   Input Parameters:
2312f6dfbefdSBarry Smith + snes - the `SNES` context
2313dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
23148434afd1SBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
231526a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed
2316dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
23178434afd1SBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2318dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2319dc4c0fb0SBarry Smith 
2320dc4c0fb0SBarry Smith   Level: intermediate
23218b0a5094SBarry Smith 
23228b0a5094SBarry Smith   Notes:
232326a11704SBarry Smith   It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use
2324f450aa47SBarry Smith   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.
2325f450aa47SBarry Smith 
2326f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
23278b0a5094SBarry Smith 
23281d27aa22SBarry Smith   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}$.
23291d27aa22SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
23308b0a5094SBarry Smith 
233126a11704SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner.
23328b0a5094SBarry Smith 
23330d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
23341d27aa22SBarry Smith   the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
23358b0a5094SBarry Smith 
23368b0a5094SBarry Smith   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
23371d27aa22SBarry Smith   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
23381d27aa22SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
23398b0a5094SBarry Smith 
23401d27aa22SBarry Smith   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
234126a11704SBarry Smith   $A(x^{n})$ is used to build the preconditioner
23426b7fb656SBarry Smith 
234315229ffcSPierre Jolivet   When used with `-snes_fd` this will compute the true Jacobian (very slowly one column at a time) and thus represent Newton's method.
23446b7fb656SBarry Smith 
2345dc4c0fb0SBarry Smith   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
234626a11704SBarry Smith   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
234726a11704SBarry Smith   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`.
2348aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2349bbc1464cSBarry Smith 
23509bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
23518434afd1SBarry Smith           `SNESFunctionFn`, `SNESJacobianFn`
23528b0a5094SBarry Smith @*/
23538434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
2354d71ae5a4SJacob Faibussowitsch {
2355e03ab78fSPeter Brune   DM dm;
2356e03ab78fSPeter Brune 
23578b0a5094SBarry Smith   PetscFunctionBegin;
23588b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23599566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23609566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
23619566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
23629566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
23639566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
23643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23658b0a5094SBarry Smith }
23668b0a5094SBarry Smith 
23677971a8bfSPeter Brune /*@C
23687971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
23697971a8bfSPeter Brune 
2370f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
23717971a8bfSPeter Brune 
23727971a8bfSPeter Brune   Input Parameter:
2373f6dfbefdSBarry Smith . snes - the `SNES` context
23747971a8bfSPeter Brune 
2375d8d19677SJose E. Roman   Output Parameters:
2376dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
23778434afd1SBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunctionFn`
2378dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2379dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
23808434afd1SBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFn`
2381dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
23827971a8bfSPeter Brune 
23837971a8bfSPeter Brune   Level: advanced
23847971a8bfSPeter Brune 
23858434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
23867971a8bfSPeter Brune @*/
23878434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
2388d71ae5a4SJacob Faibussowitsch {
23897971a8bfSPeter Brune   DM dm;
23907971a8bfSPeter Brune 
23917971a8bfSPeter Brune   PetscFunctionBegin;
23927971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23939566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23949566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23959566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23969566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23987971a8bfSPeter Brune }
23997971a8bfSPeter Brune 
2400d25893d9SBarry Smith /*@C
2401dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2402d25893d9SBarry Smith 
2403c3339decSBarry Smith   Logically Collective
2404d25893d9SBarry Smith 
2405d25893d9SBarry Smith   Input Parameters:
2406f6dfbefdSBarry Smith + snes - the `SNES` context
24078434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2408d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2409dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2410d25893d9SBarry Smith 
2411d25893d9SBarry Smith   Level: intermediate
2412d25893d9SBarry Smith 
24138434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2414d25893d9SBarry Smith @*/
24158434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx)
2416d71ae5a4SJacob Faibussowitsch {
2417d25893d9SBarry Smith   PetscFunctionBegin;
2418d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2419d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2420d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
24213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2422d25893d9SBarry Smith }
2423d25893d9SBarry Smith 
24241096aae1SMatthew Knepley /*@C
2425dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2426dd8e379bSPierre Jolivet   it assumes a zero right-hand side.
24271096aae1SMatthew Knepley 
2428c3339decSBarry Smith   Logically Collective
24291096aae1SMatthew Knepley 
24301096aae1SMatthew Knepley   Input Parameter:
2431f6dfbefdSBarry Smith . snes - the `SNES` context
24321096aae1SMatthew Knepley 
24331096aae1SMatthew Knepley   Output Parameter:
2434dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
24351096aae1SMatthew Knepley 
24361096aae1SMatthew Knepley   Level: intermediate
24371096aae1SMatthew Knepley 
24381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
24391096aae1SMatthew Knepley @*/
2440d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2441d71ae5a4SJacob Faibussowitsch {
24421096aae1SMatthew Knepley   PetscFunctionBegin;
24430700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24444f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
244585385478SLisandro Dalcin   *rhs = snes->vec_rhs;
24463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24471096aae1SMatthew Knepley }
24481096aae1SMatthew Knepley 
24499b94acceSBarry Smith /*@
2450f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
24519b94acceSBarry Smith 
2452c3339decSBarry Smith   Collective
2453c7afd0dbSLois Curfman McInnes 
24549b94acceSBarry Smith   Input Parameters:
2455f6dfbefdSBarry Smith + snes - the `SNES` context
2456c7afd0dbSLois Curfman McInnes - x    - input vector
24579b94acceSBarry Smith 
24589b94acceSBarry Smith   Output Parameter:
2459*76c63389SBarry Smith . f - function vector, as set by `SNESSetFunction()`
24609b94acceSBarry Smith 
2461dc4c0fb0SBarry Smith   Level: developer
2462dc4c0fb0SBarry Smith 
246300677de2SStefano Zampini   Notes:
2464f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2465bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
246636851e7fSLois Curfman McInnes 
2467*76c63389SBarry Smith   When solving for $F(x) = b$, this routine computes $f = F(x) - b$.
246800677de2SStefano Zampini 
2469*76c63389SBarry Smith   This function usually appears in the pattern.
2470*76c63389SBarry Smith .vb
2471*76c63389SBarry Smith   SNESComputeFunction(snes, x, f);
2472*76c63389SBarry Smith   VecNorm(f, &fnorm);
2473*76c63389SBarry Smith   SNESCheckFunctionDomainError(snes, fnorm); or SNESLineSearchCheckFunctionDomainError(ls, fnorm);
2474*76c63389SBarry Smith .ve
2475*76c63389SBarry Smith   to collectively handle the use of `SNESSetFunctionDomainError()` in the provided callback function.
2476*76c63389SBarry Smith 
2477*76c63389SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`, `SNESSetFunctionDomainError()`
24789b94acceSBarry Smith @*/
2479*76c63389SBarry Smith PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec f)
2480d71ae5a4SJacob Faibussowitsch {
24816cab3a1bSJed Brown   DM     dm;
2482942e3340SBarry Smith   DMSNES sdm;
24839b94acceSBarry Smith 
24843a40ed3dSBarry Smith   PetscFunctionBegin;
24850700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24860700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2487*76c63389SBarry Smith   PetscValidHeaderSpecific(f, VEC_CLASSID, 3);
2488c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2489*76c63389SBarry Smith   PetscCheckSameComm(snes, 1, f, 3);
2490e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2491184914b5SBarry Smith 
24929566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24939566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24940fdf79fbSJacob Faibussowitsch   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().");
249532f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
2496*76c63389SBarry Smith     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, f, 0));
24979566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24988ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2499*76c63389SBarry Smith     snes->functiondomainerror = PETSC_FALSE;
2500800f99ffSJeremy L Thompson     {
2501800f99ffSJeremy L Thompson       void           *ctx;
25028434afd1SBarry Smith       SNESFunctionFn *computefunction;
2503800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2504*76c63389SBarry Smith       PetscCallBack("SNES callback function", (*computefunction)(snes, x, f, ctx));
2505800f99ffSJeremy L Thompson     }
25069566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
2507*76c63389SBarry Smith     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, f, 0));
25080fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
2509*76c63389SBarry Smith     PetscCall(MatMult(snes->jacobian, x, f));
25100fdf79fbSJacob Faibussowitsch   }
2511*76c63389SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(f, -1.0, snes->vec_rhs));
2512ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2513422a814eSBarry Smith   /*
2514*76c63389SBarry Smith      domainerror might not be set on all processes; so we tag vector locally with infinity and the next inner product or norm will
2515422a814eSBarry Smith      propagate the value to all processes
2516422a814eSBarry Smith   */
2517*76c63389SBarry Smith   PetscCall(VecFlag(f, snes->functiondomainerror));
25183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25199b94acceSBarry Smith }
25209b94acceSBarry Smith 
2521c79ef259SPeter Brune /*@
25220b4b7b1cSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`.
2523bbc1464cSBarry Smith 
2524c3339decSBarry Smith   Collective
2525bbc1464cSBarry Smith 
2526bbc1464cSBarry Smith   Input Parameters:
2527f6dfbefdSBarry Smith + snes - the `SNES` context
2528bbc1464cSBarry Smith - x    - input vector
2529bbc1464cSBarry Smith 
2530bbc1464cSBarry Smith   Output Parameter:
25310b4b7b1cSBarry Smith . y - output vector
2532bbc1464cSBarry Smith 
2533dc4c0fb0SBarry Smith   Level: developer
2534dc4c0fb0SBarry Smith 
2535bbc1464cSBarry Smith   Notes:
2536420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2537bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2538bbc1464cSBarry Smith 
2539dd8e379bSPierre Jolivet   Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2540f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2541dd8e379bSPierre Jolivet   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.
2542bbc1464cSBarry Smith 
25430b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()`
2544bbc1464cSBarry Smith @*/
2545d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2546d71ae5a4SJacob Faibussowitsch {
2547bbc1464cSBarry Smith   DM     dm;
2548bbc1464cSBarry Smith   DMSNES sdm;
2549bbc1464cSBarry Smith 
2550bbc1464cSBarry Smith   PetscFunctionBegin;
2551bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2552bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2553bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2554bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2555bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2556e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2557bbc1464cSBarry Smith 
25589566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25599566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25609566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
25619566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2562bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2563*76c63389SBarry Smith   snes->functiondomainerror = PETSC_FALSE;
2564792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
25659566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
25669566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2567bbc1464cSBarry Smith   snes->nfuncs++;
2568bbc1464cSBarry Smith   /*
2569*76c63389SBarry Smith      domainerror might not be set on all processes; so we tag vector locally with infinity and the next inner product or norm will
2570bbc1464cSBarry Smith      propagate the value to all processes
2571bbc1464cSBarry Smith   */
2572*76c63389SBarry Smith   PetscCall(VecFlag(y, snes->functiondomainerror));
25733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2574bbc1464cSBarry Smith }
2575bbc1464cSBarry Smith 
2576bbc1464cSBarry Smith /*@
2577f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2578c79ef259SPeter Brune 
2579c3339decSBarry Smith   Collective
2580c79ef259SPeter Brune 
2581c79ef259SPeter Brune   Input Parameters:
2582f6dfbefdSBarry Smith + snes - the `SNES` context
2583c79ef259SPeter Brune . x    - input vector
2584c79ef259SPeter Brune - b    - rhs vector
2585c79ef259SPeter Brune 
2586c79ef259SPeter Brune   Output Parameter:
2587c79ef259SPeter Brune . x - new solution vector
2588c79ef259SPeter Brune 
2589dc4c0fb0SBarry Smith   Level: developer
2590dc4c0fb0SBarry Smith 
2591f6dfbefdSBarry Smith   Note:
2592f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2593c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2594c79ef259SPeter Brune   themselves.
2595c79ef259SPeter Brune 
25968434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2597c79ef259SPeter Brune @*/
2598d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2599d71ae5a4SJacob Faibussowitsch {
26006cab3a1bSJed Brown   DM     dm;
2601942e3340SBarry Smith   DMSNES sdm;
2602646217ecSPeter Brune 
2603646217ecSPeter Brune   PetscFunctionBegin;
2604646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2605064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2606064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2607064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2608064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2609e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
26109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
26119566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
26129566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
26130fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
26149566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2615792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
26169566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
26179566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
26183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2619646217ecSPeter Brune }
2620646217ecSPeter Brune 
2621494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2622494a190aSStefano Zampini {
2623494a190aSStefano Zampini   Vec          X;
2624494a190aSStefano Zampini   PetscScalar *g;
2625494a190aSStefano Zampini   PetscReal    f, f2;
2626494a190aSStefano Zampini   PetscInt     low, high, N, i;
2627494a190aSStefano Zampini   PetscBool    flg;
2628494a190aSStefano Zampini   PetscReal    h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2629494a190aSStefano Zampini 
2630494a190aSStefano Zampini   PetscFunctionBegin;
2631494a190aSStefano Zampini   PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2632494a190aSStefano Zampini   PetscCall(VecDuplicate(Xin, &X));
2633494a190aSStefano Zampini   PetscCall(VecCopy(Xin, X));
2634494a190aSStefano Zampini   PetscCall(VecGetSize(X, &N));
2635494a190aSStefano Zampini   PetscCall(VecGetOwnershipRange(X, &low, &high));
2636494a190aSStefano Zampini   PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2637494a190aSStefano Zampini   PetscCall(VecGetArray(G, &g));
2638494a190aSStefano Zampini   for (i = 0; i < N; i++) {
2639494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2640494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2641494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2642494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f));
2643494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2644494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2645494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2646494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f2));
2647494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2648494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2649494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2650494a190aSStefano Zampini     if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2651494a190aSStefano Zampini   }
2652494a190aSStefano Zampini   PetscCall(VecRestoreArray(G, &g));
2653494a190aSStefano Zampini   PetscCall(VecDestroy(&X));
2654494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2655494a190aSStefano Zampini }
2656494a190aSStefano Zampini 
26571dfd7622SMatthew Knepley /*@
26581dfd7622SMatthew Knepley   SNESTestFunction - Computes the difference between the computed and finite-difference functions
26591dfd7622SMatthew Knepley 
26601dfd7622SMatthew Knepley   Collective
26611dfd7622SMatthew Knepley 
2662d5bfe6baSJose E. Roman   Input Parameter:
26631dfd7622SMatthew Knepley . snes - the `SNES` context
26641dfd7622SMatthew Knepley 
26651dfd7622SMatthew Knepley   Options Database Keys:
26661dfd7622SMatthew Knepley + -snes_test_function      - compare the user provided function with one compute via finite differences to check for errors.
26671dfd7622SMatthew Knepley - -snes_test_function_view - display the user provided function, the finite difference function and the difference
26681dfd7622SMatthew Knepley 
26691dfd7622SMatthew Knepley   Level: developer
26701dfd7622SMatthew Knepley 
26711dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestJacobian()`, `SNESSetFunction()`, `SNESComputeFunction()`
26721dfd7622SMatthew Knepley @*/
2673494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2674494a190aSStefano Zampini {
2675494a190aSStefano Zampini   Vec               x, g1, g2, g3;
26761dfd7622SMatthew Knepley   PetscBool         complete_print = PETSC_FALSE;
2677494a190aSStefano Zampini   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2678494a190aSStefano Zampini   PetscScalar       dot;
2679494a190aSStefano Zampini   MPI_Comm          comm;
2680494a190aSStefano Zampini   PetscViewer       viewer, mviewer;
2681494a190aSStefano Zampini   PetscViewerFormat format;
2682494a190aSStefano Zampini   PetscInt          tabs;
2683494a190aSStefano Zampini   static PetscBool  directionsprinted = PETSC_FALSE;
26848434afd1SBarry Smith   SNESObjectiveFn  *objective;
2685494a190aSStefano Zampini 
2686494a190aSStefano Zampini   PetscFunctionBegin;
2687494a190aSStefano Zampini   PetscCall(SNESGetObjective(snes, &objective, NULL));
2688494a190aSStefano Zampini   if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2689494a190aSStefano Zampini 
2690494a190aSStefano Zampini   PetscObjectOptionsBegin((PetscObject)snes);
2691494a190aSStefano Zampini   PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2692494a190aSStefano Zampini   PetscOptionsEnd();
2693494a190aSStefano Zampini 
2694494a190aSStefano Zampini   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2695494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2696494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2697494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2698494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Function -------------\n"));
2699494a190aSStefano Zampini   if (!complete_print && !directionsprinted) {
2700494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2701494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference function entries greater than <threshold>.\n"));
2702494a190aSStefano Zampini   }
2703494a190aSStefano Zampini   if (!directionsprinted) {
2704494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2705494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Function is probably correct.\n"));
2706494a190aSStefano Zampini     directionsprinted = PETSC_TRUE;
2707494a190aSStefano Zampini   }
2708494a190aSStefano Zampini   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2709494a190aSStefano Zampini 
2710494a190aSStefano Zampini   PetscCall(SNESGetSolution(snes, &x));
2711494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g1));
2712494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g2));
2713494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g3));
2714*76c63389SBarry Smith   PetscCall(SNESComputeFunction(snes, x, g1)); /* does not handle use of SNESSetFunctionDomainError() corrrectly */
2715494a190aSStefano Zampini   PetscCall(SNESComputeFunction_FD(snes, x, g2));
2716494a190aSStefano Zampini 
2717494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2718494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2719494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2720494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2721494a190aSStefano Zampini   PetscCall(VecDot(g1, g2, &dot));
2722494a190aSStefano Zampini   PetscCall(VecCopy(g1, g3));
2723494a190aSStefano Zampini   PetscCall(VecAXPY(g3, -1.0, g2));
2724494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2725494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2726494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ||Ffd|| %g, ||F|| = %g, angle cosine = (Ffd'F)/||Ffd||||F|| = %g\n", (double)fdnorm, (double)hcnorm, (double)(PetscRealPart(dot) / (fdnorm * hcnorm))));
2727494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2728494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2729494a190aSStefano Zampini 
2730494a190aSStefano Zampini   if (complete_print) {
2731494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded function ----------\n"));
2732494a190aSStefano Zampini     PetscCall(VecView(g1, mviewer));
2733494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference function ----------\n"));
2734494a190aSStefano Zampini     PetscCall(VecView(g2, mviewer));
2735494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference function ----------\n"));
2736494a190aSStefano Zampini     PetscCall(VecView(g3, mviewer));
2737494a190aSStefano Zampini   }
2738494a190aSStefano Zampini   PetscCall(VecDestroy(&g1));
2739494a190aSStefano Zampini   PetscCall(VecDestroy(&g2));
2740494a190aSStefano Zampini   PetscCall(VecDestroy(&g3));
2741494a190aSStefano Zampini 
2742494a190aSStefano Zampini   if (complete_print) {
2743494a190aSStefano Zampini     PetscCall(PetscViewerPopFormat(mviewer));
2744494a190aSStefano Zampini     PetscCall(PetscViewerDestroy(&mviewer));
2745494a190aSStefano Zampini   }
2746494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2747494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2748494a190aSStefano Zampini }
2749494a190aSStefano Zampini 
2750cbf8f02cSMatthew G. Knepley /*@
2751cbf8f02cSMatthew G. Knepley   SNESTestJacobian - Computes the difference between the computed and finite-difference Jacobians
2752cbf8f02cSMatthew G. Knepley 
2753cbf8f02cSMatthew G. Knepley   Collective
2754cbf8f02cSMatthew G. Knepley 
2755d5bfe6baSJose E. Roman   Input Parameter:
2756cbf8f02cSMatthew G. Knepley . snes - the `SNES` context
2757cbf8f02cSMatthew G. Knepley 
2758cbf8f02cSMatthew G. Knepley   Output Parameters:
27591dfd7622SMatthew Knepley + Jnorm    - the Frobenius norm of the computed Jacobian, or `NULL`
27601dfd7622SMatthew Knepley - diffNorm - the Frobenius norm of the difference of the computed and finite-difference Jacobians, or `NULL`
2761cbf8f02cSMatthew G. Knepley 
2762cbf8f02cSMatthew G. Knepley   Options Database Keys:
2763cbf8f02cSMatthew G. Knepley + -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.
2764cbf8f02cSMatthew G. Knepley - -snes_test_jacobian_view                 - display the user provided Jacobian, the finite difference Jacobian and the difference
2765cbf8f02cSMatthew G. Knepley 
2766cbf8f02cSMatthew G. Knepley   Level: developer
2767cbf8f02cSMatthew G. Knepley 
27681dfd7622SMatthew Knepley   Note:
27691dfd7622SMatthew Knepley   Directions and norms are printed to stdout if `diffNorm` is `NULL`.
27701dfd7622SMatthew Knepley 
27711dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestFunction()`, `SNESSetJacobian()`, `SNESComputeJacobian()`
2772cbf8f02cSMatthew G. Knepley @*/
2773cbf8f02cSMatthew G. Knepley PetscErrorCode SNESTestJacobian(SNES snes, PetscReal *Jnorm, PetscReal *diffNorm)
2774d71ae5a4SJacob Faibussowitsch {
277512837594SBarry Smith   Mat               A, B, C, D, jacobian;
27764df93895SStefano Zampini   Vec               x = snes->vec_sol, f;
2777e885f1abSBarry Smith   PetscReal         nrm, gnorm;
277881e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
27790e276705SLisandro Dalcin   MatType           mattype;
2780e885f1abSBarry Smith   PetscInt          m, n, M, N;
2781e885f1abSBarry Smith   void             *functx;
27821dfd7622SMatthew Knepley   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, flg, istranspose;
27831dfd7622SMatthew Knepley   PetscBool         silent = diffNorm != PETSC_NULLPTR ? PETSC_TRUE : PETSC_FALSE;
27843325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2785e885f1abSBarry Smith   MPI_Comm          comm;
2786e885f1abSBarry Smith   PetscInt          tabs;
278712837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
27883325ff46SBarry Smith   PetscViewerFormat format;
2789e885f1abSBarry Smith 
2790e885f1abSBarry Smith   PetscFunctionBegin;
2791d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
27929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
27939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
27944ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
27959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
27969566063dSJacob Faibussowitsch   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));
2797d0609cedSBarry Smith   PetscOptionsEnd();
2798e885f1abSBarry Smith 
27999566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
28009566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
28019566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
28029566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
28031dfd7622SMatthew Knepley   if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
28041dfd7622SMatthew Knepley   if (!complete_print && !silent && !directionsprinted) {
28059566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
28069566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
280712837594SBarry Smith   }
28081dfd7622SMatthew Knepley   if (!directionsprinted && !silent) {
28099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
28109566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
281112837594SBarry Smith     directionsprinted = PETSC_TRUE;
2812e885f1abSBarry Smith   }
28131baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2814e885f1abSBarry Smith 
28159566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
281612837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
281712837594SBarry Smith   else jacobian = snes->jacobian_pre;
281812837594SBarry Smith 
28194df93895SStefano Zampini   if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
28204df93895SStefano Zampini   else PetscCall(PetscObjectReference((PetscObject)x));
28219566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &f));
28224df93895SStefano Zampini 
2823a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
28249566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
28259566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
28269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
282712837594SBarry Smith   while (jacobian) {
28282cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
28292cd624f9SStefano Zampini 
28302cd624f9SStefano Zampini     if (istranspose) {
28319566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
28322cd624f9SStefano Zampini       Jsave    = jacobian;
28332cd624f9SStefano Zampini       jacobian = JT;
28342cd624f9SStefano Zampini     }
28359566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
283612837594SBarry Smith     if (flg) {
283712837594SBarry Smith       A = jacobian;
28389566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
283912837594SBarry Smith     } else {
28409566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
284112837594SBarry Smith     }
2842e885f1abSBarry Smith 
28439566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
28449566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
28459566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
28469566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
28479566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
28489566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
28499566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
28509566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
28519566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2852e885f1abSBarry Smith 
28539566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
28549566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
285512837594SBarry Smith 
28569566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
28579566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28589566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
28599566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
28609566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
286112837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
28621dfd7622SMatthew Knepley     if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
2863e885f1abSBarry Smith     if (complete_print) {
28649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
28659566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
28669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
28679566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2868e885f1abSBarry Smith     }
2869e885f1abSBarry Smith 
2870df10fb39SFande Kong     if (threshold_print || complete_print) {
2871e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2872e885f1abSBarry Smith       PetscScalar       *cvals;
2873e885f1abSBarry Smith       const PetscInt    *bcols;
2874e885f1abSBarry Smith       const PetscScalar *bvals;
2875e885f1abSBarry Smith 
28769566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
28779566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
28789566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
28799566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
28809566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
28819566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
28820e276705SLisandro Dalcin 
28839566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28849566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2885e885f1abSBarry Smith 
2886e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
28879566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
28889566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2889e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
289023a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2891e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2892e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2893e885f1abSBarry Smith             cncols += 1;
2894e885f1abSBarry Smith           }
2895e885f1abSBarry Smith         }
289648a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
28979566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
28989566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2899e885f1abSBarry Smith       }
29009566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
29019566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
29029566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
29039566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
29049566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2905e885f1abSBarry Smith     }
29069566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
29079566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
29089566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
29092cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
291012837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
291112837594SBarry Smith       jacobian = snes->jacobian_pre;
29121dfd7622SMatthew Knepley       if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
29139371c9d4SSatish Balay     } else jacobian = NULL;
291412837594SBarry Smith   }
29159566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
29161baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2917648c30bcSBarry Smith   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
29189566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2919cbf8f02cSMatthew G. Knepley 
2920cbf8f02cSMatthew G. Knepley   if (Jnorm) *Jnorm = gnorm;
2921cbf8f02cSMatthew G. Knepley   if (diffNorm) *diffNorm = nrm;
29223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2923e885f1abSBarry Smith }
2924e885f1abSBarry Smith 
292562fef451SLois Curfman McInnes /*@
2926f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
292762fef451SLois Curfman McInnes 
2928c3339decSBarry Smith   Collective
2929c7afd0dbSLois Curfman McInnes 
293062fef451SLois Curfman McInnes   Input Parameters:
2931f6dfbefdSBarry Smith + snes - the `SNES` context
2932e4094ef1SJacob Faibussowitsch - X    - input vector
293362fef451SLois Curfman McInnes 
293462fef451SLois Curfman McInnes   Output Parameters:
2935c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2936420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2937fee21e36SBarry Smith 
2938e35cf81dSBarry Smith   Options Database Keys:
293967b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
294067b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2941455a5933SJed Brown . -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.
2942455a5933SJed Brown . -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
2943693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2944693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2945693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
29467addb90fSBarry Smith . -snes_compare_operator                   - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner
294794d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2948a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2949c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2950dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2951dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2952a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2953a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2954c01495d3SJed Brown 
2955dc4c0fb0SBarry Smith   Level: developer
2956dc4c0fb0SBarry Smith 
2957f6dfbefdSBarry Smith   Note:
295862fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
295962fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
296062fef451SLois Curfman McInnes 
2961420bcc1bSBarry Smith   Developer Note:
2962dc4c0fb0SBarry Smith   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
2963420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2964e885f1abSBarry Smith 
2965*76c63389SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`,
2966*76c63389SBarry Smith           `SNESSetJacobianDomainError()`, `SNESCheckJacobianDomainError()`, `SNESSetCheckJacobianDomainError()`
296762fef451SLois Curfman McInnes @*/
2968d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2969d71ae5a4SJacob Faibussowitsch {
2970ace3abfcSBarry Smith   PetscBool flag;
29716cab3a1bSJed Brown   DM        dm;
2972942e3340SBarry Smith   DMSNES    sdm;
2973e0e3a89bSBarry Smith   KSP       ksp;
29743a40ed3dSBarry Smith 
29753a40ed3dSBarry Smith   PetscFunctionBegin;
29760700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
29770700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2978c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2979e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
29809566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
29819566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
29823232da50SPeter Brune 
298301c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2984fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2985fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2986f5af7f23SKarl Rupp 
29879566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2988fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
29899566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
29909566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2991ebd3b9afSBarry Smith     if (flag) {
29929566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29939566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2994ebd3b9afSBarry Smith     }
29953ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
299637ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
299763a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
29989566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2999ebd3b9afSBarry Smith     if (flag) {
30009566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
30019566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
3002ebd3b9afSBarry Smith     }
30033ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3004e35cf81dSBarry Smith   }
3005efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
30069566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
30079566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
30083ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3009d728fb7dSPeter Brune   }
3010e35cf81dSBarry Smith 
30119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
30129566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
3013800f99ffSJeremy L Thompson   {
3014800f99ffSJeremy L Thompson     void           *ctx;
30158434afd1SBarry Smith     SNESJacobianFn *J;
3016800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
3017800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
3018800f99ffSJeremy L Thompson   }
30199566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
30209566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
302128d58a37SPierre Jolivet 
30227addb90fSBarry Smith   /* attach latest linearization point to the matrix used to construct the preconditioner */
30239566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
3024a8054027SBarry Smith 
3025e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
30269566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
30273b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
30289566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
30299566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
30303b4f5425SBarry Smith     snes->lagpreconditioner = -1;
30313b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
30329566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
30339566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
303437ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
303563a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
30369566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
3037d1e9a80fSBarry Smith   } else {
30389566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
30399566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
3040a8054027SBarry Smith   }
3041a8054027SBarry Smith 
30424df93895SStefano Zampini   /* monkey business to allow testing Jacobians in multilevel solvers.
30434df93895SStefano Zampini      This is needed because the SNESTestXXX interface does not accept vectors and matrices */
30444df93895SStefano Zampini   {
30454df93895SStefano Zampini     Vec xsave            = snes->vec_sol;
30464df93895SStefano Zampini     Mat jacobiansave     = snes->jacobian;
30474df93895SStefano Zampini     Mat jacobian_presave = snes->jacobian_pre;
30484df93895SStefano Zampini 
30494df93895SStefano Zampini     snes->vec_sol      = X;
30504df93895SStefano Zampini     snes->jacobian     = A;
30514df93895SStefano Zampini     snes->jacobian_pre = B;
30521dfd7622SMatthew Knepley     if (snes->testFunc) PetscCall(SNESTestFunction(snes));
30531dfd7622SMatthew Knepley     if (snes->testJac) PetscCall(SNESTestJacobian(snes, NULL, NULL));
3054494a190aSStefano Zampini 
30554df93895SStefano Zampini     snes->vec_sol      = xsave;
30564df93895SStefano Zampini     snes->jacobian     = jacobiansave;
30574df93895SStefano Zampini     snes->jacobian_pre = jacobian_presave;
30584df93895SStefano Zampini   }
30594df93895SStefano Zampini 
3060693365a8SJed Brown   {
3061693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
3062648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
3063648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
3064648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
3065648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
3066693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
30670298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
3068693365a8SJed Brown       PetscViewer vdraw, vstdout;
30696b3a5b13SJed Brown       PetscBool   flg;
3070693365a8SJed Brown       if (flag_operator) {
30719566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
3072693365a8SJed Brown         Bexp = Bexp_mine;
3073693365a8SJed Brown       } else {
30747addb90fSBarry Smith         /* See if the matrix used to construct the preconditioner can be viewed and added directly */
30752b2f8cc6SPierre Jolivet         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
307694ab13aaSBarry Smith         if (flg) Bexp = B;
3077693365a8SJed Brown         else {
3078693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
30799566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
3080693365a8SJed Brown           Bexp = Bexp_mine;
3081693365a8SJed Brown         }
3082693365a8SJed Brown       }
30839566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
30849566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
30859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
3086693365a8SJed Brown       if (flag_draw || flag_contour) {
30879566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30889566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30890298fd71SBarry Smith       } else vdraw = NULL;
30909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
30919566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
30929566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
30939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
30949566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
30959566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
30969566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
30979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
30989566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
3099693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
31009566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31019566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
31029566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
3103693365a8SJed Brown       }
31049566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
31059566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
31069566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
31079566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
3108693365a8SJed Brown     }
3109693365a8SJed Brown   }
31104c30e9fbSJed Brown   {
31116719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
31126719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
3113648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
3114648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
3115648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
3116648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
3117648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
311827b0f280SBarry Smith     if (flag_threshold) {
31199566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
31209566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
312127b0f280SBarry Smith     }
31226719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
31234c30e9fbSJed Brown       Mat             Bfd;
31244c30e9fbSJed Brown       PetscViewer     vdraw, vstdout;
3125335efc43SPeter Brune       MatColoring     coloring;
31264c30e9fbSJed Brown       ISColoring      iscoloring;
31274c30e9fbSJed Brown       MatFDColoring   matfdcoloring;
31288434afd1SBarry Smith       SNESFunctionFn *func;
31294c30e9fbSJed Brown       void           *funcctx;
31306719d8e4SJed Brown       PetscReal       norm1, norm2, normmax;
31314c30e9fbSJed Brown 
31329566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
31339566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
31349566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
31359566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
31369566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
31379566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
31389566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
31399566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
31409566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
31419566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
31424c30e9fbSJed Brown 
31434c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
31449566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
31452ba42892SBarry Smith       PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)func, funcctx));
31469566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
31479566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
31489566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
31499566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
31509566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
31514c30e9fbSJed Brown 
31529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
31534c30e9fbSJed Brown       if (flag_draw || flag_contour) {
31549566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
31559566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31560298fd71SBarry Smith       } else vdraw = NULL;
31579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
31589566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
31599566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
31609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
31619566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31629566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
31639566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
31649566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
31659566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
31669566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
31679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
31689566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31694c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
31709566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31719566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
31729566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
31734c30e9fbSJed Brown       }
31749566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
31756719d8e4SJed Brown 
31766719d8e4SJed Brown       if (flag_threshold) {
31776719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
31789566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
31799566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
31806719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
31816719d8e4SJed Brown           const PetscScalar *ba, *ca;
31826719d8e4SJed Brown           const PetscInt    *bj, *cj;
31836719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
31846719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
31859566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
31869566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
31875f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
31886719d8e4SJed Brown           for (j = 0; j < bn; j++) {
31896719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
31906719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
31916719d8e4SJed Brown               maxentrycol = bj[j];
31926719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
31936719d8e4SJed Brown             }
31946719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
31956719d8e4SJed Brown               maxdiffcol = bj[j];
31966719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
31976719d8e4SJed Brown             }
31986719d8e4SJed Brown             if (rdiff > maxrdiff) {
31996719d8e4SJed Brown               maxrdiffcol = bj[j];
32006719d8e4SJed Brown               maxrdiff    = rdiff;
32016719d8e4SJed Brown             }
32026719d8e4SJed Brown           }
32036719d8e4SJed Brown           if (maxrdiff > 1) {
320463a3b9bcSJacob Faibussowitsch             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));
32056719d8e4SJed Brown             for (j = 0; j < bn; j++) {
32066719d8e4SJed Brown               PetscReal rdiff;
32076719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
320848a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
32096719d8e4SJed Brown             }
321063a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
32116719d8e4SJed Brown           }
32129566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
32139566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
32146719d8e4SJed Brown         }
32156719d8e4SJed Brown       }
32169566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
32179566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
32184c30e9fbSJed Brown     }
32194c30e9fbSJed Brown   }
32203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32219b94acceSBarry Smith }
32229b94acceSBarry Smith 
32239b94acceSBarry Smith /*@C
32249b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3225044dda88SLois Curfman McInnes   location to store the matrix.
32269b94acceSBarry Smith 
3227c3339decSBarry Smith   Logically Collective
3228c7afd0dbSLois Curfman McInnes 
32299b94acceSBarry Smith   Input Parameters:
3230f6dfbefdSBarry Smith + snes - the `SNES` context
3231e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3232dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
32338434afd1SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3234c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3235dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3236dc4c0fb0SBarry Smith 
3237dc4c0fb0SBarry Smith   Level: beginner
32389b94acceSBarry Smith 
32399b94acceSBarry Smith   Notes:
3240dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
324116913363SBarry Smith   each matrix.
324216913363SBarry Smith 
3243dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3244dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3245895c21f2SBarry Smith 
3246dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3247f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3248a8a26c1eSJed Brown 
3249c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3250f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3251c3cc8fd1SJed Brown 
32521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
32538434afd1SBarry Smith           `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
32549b94acceSBarry Smith @*/
32558434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
3256d71ae5a4SJacob Faibussowitsch {
32576cab3a1bSJed Brown   DM dm;
32583a7fca6bSBarry Smith 
32593a40ed3dSBarry Smith   PetscFunctionBegin;
32600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3261e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3262e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3263e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3264e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
32659566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32669566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3267e5d3d808SBarry Smith   if (Amat) {
32689566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
32699566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3270f5af7f23SKarl Rupp 
3271e5d3d808SBarry Smith     snes->jacobian = Amat;
32723a7fca6bSBarry Smith   }
3273e5d3d808SBarry Smith   if (Pmat) {
32749566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
32759566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3276f5af7f23SKarl Rupp 
3277e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
32783a7fca6bSBarry Smith   }
32793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32809b94acceSBarry Smith }
328162fef451SLois Curfman McInnes 
3282c2aafc4cSSatish Balay /*@C
3283b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3284b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3285b4fd4287SBarry Smith 
3286420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3287c7afd0dbSLois Curfman McInnes 
3288b4fd4287SBarry Smith   Input Parameter:
3289b4fd4287SBarry Smith . snes - the nonlinear solver context
3290b4fd4287SBarry Smith 
3291b4fd4287SBarry Smith   Output Parameters:
3292dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3293dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
32948434afd1SBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3295dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3296fee21e36SBarry Smith 
329736851e7fSLois Curfman McInnes   Level: advanced
329836851e7fSLois Curfman McInnes 
32998434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3300b4fd4287SBarry Smith @*/
33018434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
3302d71ae5a4SJacob Faibussowitsch {
33036cab3a1bSJed Brown   DM dm;
33046cab3a1bSJed Brown 
33053a40ed3dSBarry Smith   PetscFunctionBegin;
33060700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3307e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3308e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
33099566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3310800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
33113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3312b4fd4287SBarry Smith }
3313b4fd4287SBarry Smith 
3314d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3315d71ae5a4SJacob Faibussowitsch {
331658b371f3SBarry Smith   DM     dm;
331758b371f3SBarry Smith   DMSNES sdm;
331858b371f3SBarry Smith 
331958b371f3SBarry Smith   PetscFunctionBegin;
33209566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
33219566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
332258b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
332358b371f3SBarry Smith     DM        dm;
332458b371f3SBarry Smith     PetscBool isdense, ismf;
332558b371f3SBarry Smith 
33269566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
33279566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
33289566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
332958b371f3SBarry Smith     if (isdense) {
33309566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
333158b371f3SBarry Smith     } else if (!ismf) {
33329566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
333358b371f3SBarry Smith     }
333458b371f3SBarry Smith   }
33353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
333658b371f3SBarry Smith }
333758b371f3SBarry Smith 
33389b94acceSBarry Smith /*@
33399b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
33400b4b7b1cSBarry Smith   of a nonlinear solver `SNESSolve()`.
33419b94acceSBarry Smith 
3342c3339decSBarry Smith   Collective
3343fee21e36SBarry Smith 
33442fe279fdSBarry Smith   Input Parameter:
3345f6dfbefdSBarry Smith . snes - the `SNES` context
3346c7afd0dbSLois Curfman McInnes 
3347dc4c0fb0SBarry Smith   Level: advanced
3348dc4c0fb0SBarry Smith 
3349f6dfbefdSBarry Smith   Note:
33500b4b7b1cSBarry Smith   For basic use of the `SNES` solvers the user does not need to explicitly call
3351f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3352f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3353f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3354f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3355272ac6f2SLois Curfman McInnes 
33560b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()`
33579b94acceSBarry Smith @*/
3358d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3359d71ae5a4SJacob Faibussowitsch {
33606cab3a1bSJed Brown   DM             dm;
3361942e3340SBarry Smith   DMSNES         sdm;
3362c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
33636e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
33649b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
33659b5c1c08SStefano Zampini   Vec            f, fpc;
33669b5c1c08SStefano Zampini   void          *funcctx;
33679b5c1c08SStefano Zampini   void          *jacctx, *appctx;
33689b5c1c08SStefano Zampini   Mat            j, jpre;
33696b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
33706b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
33718434afd1SBarry Smith   SNESFunctionFn *func;
33728434afd1SBarry Smith   SNESJacobianFn *jac;
33733a40ed3dSBarry Smith 
33743a40ed3dSBarry Smith   PetscFunctionBegin;
33750700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33763ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3377fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
33789b94acceSBarry Smith 
337948a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
338085385478SLisandro Dalcin 
33819566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
338258c9b817SLisandro Dalcin 
33839566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
33849566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
33859566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
338658b371f3SBarry Smith 
338748a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3388efd51863SBarry Smith 
338948a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3390b710008aSBarry Smith 
3391d8d34be6SBarry Smith   if (snes->linesearch) {
33929566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
33939566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3394d8d34be6SBarry Smith   }
33959e764e56SPeter Brune 
33969b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3397b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3398172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3399172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3400172a4300SPeter Brune   }
3401d8f46077SPeter Brune 
3402efd4aadfSBarry Smith   if (snes->npc) {
34036e2a1849SPeter Brune     /* copy the DM over */
34049566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
34059566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
34066e2a1849SPeter Brune 
34079566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
34089566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
34099566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
34109566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
34119566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
34129566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
34139566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
34149b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
34159566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
34166e2a1849SPeter Brune 
34176e2a1849SPeter Brune     /* copy the function pointers over */
34189566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
34196e2a1849SPeter Brune 
34206e2a1849SPeter Brune     /* default to 1 iteration */
34219566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3422efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
34239566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3424a9936a0cSPeter Brune     } else {
34259566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3426a9936a0cSPeter Brune     }
34279566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
34286e2a1849SPeter Brune 
34296e2a1849SPeter Brune     /* copy the line search context over */
3430d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
34319566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
34329566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
34339566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
34349566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
34359566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
34369566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
34379566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
34386e2a1849SPeter Brune     }
3439d8d34be6SBarry Smith   }
34401baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
3441835f2295SStefano Zampini   if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx));
34426e2a1849SPeter Brune 
344337ec4e1aSPeter Brune   snes->jac_iter = 0;
344437ec4e1aSPeter Brune   snes->pre_iter = 0;
344537ec4e1aSPeter Brune 
3446dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
344758c9b817SLisandro Dalcin 
34489566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
344958b371f3SBarry Smith 
3450b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
34516c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3452d8d34be6SBarry Smith       if (snes->linesearch) {
34539566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
34549566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
34556c67d002SPeter Brune       }
34566c67d002SPeter Brune     }
3457d8d34be6SBarry Smith   }
3458fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
34597aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
34603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34619b94acceSBarry Smith }
34629b94acceSBarry Smith 
346337596af1SLisandro Dalcin /*@
34640b4b7b1cSBarry Smith   SNESReset - Resets a `SNES` context to the state it was in before `SNESSetUp()` was called and removes any allocated `Vec` and `Mat` from its data structures
346537596af1SLisandro Dalcin 
3466c3339decSBarry Smith   Collective
346737596af1SLisandro Dalcin 
346837596af1SLisandro Dalcin   Input Parameter:
34690b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
347037596af1SLisandro Dalcin 
3471d25893d9SBarry Smith   Level: intermediate
3472d25893d9SBarry Smith 
347395452b02SPatrick Sanan   Notes:
34740b4b7b1cSBarry Smith   Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain.
34750b4b7b1cSBarry Smith 
3476f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
347737596af1SLisandro Dalcin 
3478f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3479f6dfbefdSBarry Smith 
34801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
348137596af1SLisandro Dalcin @*/
3482d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3483d71ae5a4SJacob Faibussowitsch {
348437596af1SLisandro Dalcin   PetscFunctionBegin;
348537596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
348649abdd8aSBarry Smith   if (snes->ops->ctxdestroy && snes->ctx) {
3487835f2295SStefano Zampini     PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx));
348849abdd8aSBarry Smith     snes->ctx = NULL;
3489d25893d9SBarry Smith   }
34901baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
34918a23116dSBarry Smith 
3492dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
34931baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
34949e764e56SPeter Brune 
34951baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
34969e764e56SPeter Brune 
34979566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
34989566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
34999566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
35009566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
35019566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
35029566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
35039566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
35049566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
35059566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3506f5af7f23SKarl Rupp 
350740fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
350840fdac6aSLawrence Mitchell 
350937596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
351037596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
35113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
351237596af1SLisandro Dalcin }
351337596af1SLisandro Dalcin 
351452baeb72SSatish Balay /*@
351536d43d94SBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also
351636d43d94SBarry Smith   removes the default viewer.
3517c4421ceaSFande Kong 
3518c3339decSBarry Smith   Collective
3519c4421ceaSFande Kong 
3520c4421ceaSFande Kong   Input Parameter:
35210b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
3522c4421ceaSFande Kong 
3523c4421ceaSFande Kong   Level: intermediate
3524c4421ceaSFande Kong 
3525420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3526c4421ceaSFande Kong @*/
3527d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3528d71ae5a4SJacob Faibussowitsch {
3529c4421ceaSFande Kong   PetscInt i;
3530c4421ceaSFande Kong 
3531c4421ceaSFande Kong   PetscFunctionBegin;
3532c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3533c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
353448a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3535c4421ceaSFande Kong   }
3536c4421ceaSFande Kong   snes->numberreasonviews = 0;
3537648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
35383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3539c4421ceaSFande Kong }
3540c4421ceaSFande Kong 
35410764c050SBarry Smith /*@
35429b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3543f6dfbefdSBarry Smith   with `SNESCreate()`.
35449b94acceSBarry Smith 
3545c3339decSBarry Smith   Collective
3546c7afd0dbSLois Curfman McInnes 
35479b94acceSBarry Smith   Input Parameter:
3548f6dfbefdSBarry Smith . snes - the `SNES` context
35499b94acceSBarry Smith 
355036851e7fSLois Curfman McInnes   Level: beginner
355136851e7fSLois Curfman McInnes 
35521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
35539b94acceSBarry Smith @*/
3554d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3555d71ae5a4SJacob Faibussowitsch {
355692e852f7SPablo Brubeck   DM dm;
355792e852f7SPablo Brubeck 
35583a40ed3dSBarry Smith   PetscFunctionBegin;
35593ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3560f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3561f4f49eeaSPierre Jolivet   if (--((PetscObject)*snes)->refct > 0) {
35629371c9d4SSatish Balay     *snes = NULL;
35633ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
35649371c9d4SSatish Balay   }
3565d4bb536fSBarry Smith 
3566f4f49eeaSPierre Jolivet   PetscCall(SNESReset(*snes));
35679566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
35686b8b9a38SLisandro Dalcin 
3569e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
35709566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3571f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*snes, destroy);
35726d4c513bSLisandro Dalcin 
357392e852f7SPablo Brubeck   dm = (*snes)->dm;
357492e852f7SPablo Brubeck   while (dm) {
357592e852f7SPablo Brubeck     PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
357692e852f7SPablo Brubeck     PetscCall(DMGetCoarseDM(dm, &dm));
357792e852f7SPablo Brubeck   }
357892e852f7SPablo Brubeck 
35799566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
35809566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
35819566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
35826b8b9a38SLisandro Dalcin 
35839566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
358412651944SBarry Smith   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)(&(*snes)->cnvP));
358548a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3586f4f49eeaSPierre Jolivet   PetscCall(SNESMonitorCancel(*snes));
3587f4f49eeaSPierre Jolivet   PetscCall(SNESConvergedReasonViewCancel(*snes));
35889566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
35893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35909b94acceSBarry Smith }
35919b94acceSBarry Smith 
35929b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
35939b94acceSBarry Smith 
3594a8054027SBarry Smith /*@
35950b4b7b1cSBarry Smith   SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`.
3596a8054027SBarry Smith 
3597c3339decSBarry Smith   Logically Collective
3598a8054027SBarry Smith 
3599a8054027SBarry Smith   Input Parameters:
3600f6dfbefdSBarry Smith + snes - the `SNES` context
3601d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
36023b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3603a8054027SBarry Smith 
3604a8054027SBarry Smith   Options Database Keys:
3605420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
36063d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3607420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
36083d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3609a8054027SBarry Smith 
3610dc4c0fb0SBarry Smith   Level: intermediate
3611dc4c0fb0SBarry Smith 
3612420bcc1bSBarry Smith   Notes:
3613a8054027SBarry Smith   The default is 1
3614420bcc1bSBarry Smith 
3615f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3616d8e291bfSBarry Smith 
3617f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3618a8054027SBarry Smith 
36193201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3620f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3621a8054027SBarry Smith @*/
3622d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3623d71ae5a4SJacob Faibussowitsch {
3624a8054027SBarry Smith   PetscFunctionBegin;
36250700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
36265f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
36275f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3628c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3629a8054027SBarry Smith   snes->lagpreconditioner = lag;
36303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3631a8054027SBarry Smith }
3632a8054027SBarry Smith 
3633efd51863SBarry Smith /*@
3634f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3635efd51863SBarry Smith 
3636c3339decSBarry Smith   Logically Collective
3637efd51863SBarry Smith 
3638efd51863SBarry Smith   Input Parameters:
3639f6dfbefdSBarry Smith + snes  - the `SNES` context
3640efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3641efd51863SBarry Smith 
3642f6dfbefdSBarry Smith   Options Database Key:
364367b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3644efd51863SBarry Smith 
3645efd51863SBarry Smith   Level: intermediate
3646efd51863SBarry Smith 
36470b4b7b1cSBarry Smith   Notes:
36480b4b7b1cSBarry Smith   Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement.
36490b4b7b1cSBarry Smith 
3650f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3651c0df2a02SJed Brown 
36523201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
365354c05997SPierre Jolivet           `SNESSetDM()`, `SNESSolve()`
3654efd51863SBarry Smith @*/
3655d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3656d71ae5a4SJacob Faibussowitsch {
3657efd51863SBarry Smith   PetscFunctionBegin;
3658efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3659efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3660efd51863SBarry Smith   snes->gridsequence = steps;
36613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3662efd51863SBarry Smith }
3663efd51863SBarry Smith 
3664fa19ca70SBarry Smith /*@
3665f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3666fa19ca70SBarry Smith 
3667c3339decSBarry Smith   Logically Collective
3668fa19ca70SBarry Smith 
3669fa19ca70SBarry Smith   Input Parameter:
3670f6dfbefdSBarry Smith . snes - the `SNES` context
3671fa19ca70SBarry Smith 
3672fa19ca70SBarry Smith   Output Parameter:
3673fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3674fa19ca70SBarry Smith 
3675fa19ca70SBarry Smith   Level: intermediate
3676fa19ca70SBarry Smith 
36773201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3678fa19ca70SBarry Smith @*/
3679d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3680d71ae5a4SJacob Faibussowitsch {
3681fa19ca70SBarry Smith   PetscFunctionBegin;
3682fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3683fa19ca70SBarry Smith   *steps = snes->gridsequence;
36843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3685fa19ca70SBarry Smith }
3686fa19ca70SBarry Smith 
3687a8054027SBarry Smith /*@
3688f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3689a8054027SBarry Smith 
36903f9fe445SBarry Smith   Not Collective
3691a8054027SBarry Smith 
3692a8054027SBarry Smith   Input Parameter:
3693f6dfbefdSBarry Smith . snes - the `SNES` context
3694a8054027SBarry Smith 
3695a8054027SBarry Smith   Output Parameter:
3696a8054027SBarry Smith . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
36973b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3698a8054027SBarry Smith 
3699dc4c0fb0SBarry Smith   Level: intermediate
3700dc4c0fb0SBarry Smith 
3701a8054027SBarry Smith   Notes:
3702a8054027SBarry Smith   The default is 1
3703f6dfbefdSBarry Smith 
3704a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3705a8054027SBarry Smith 
37063201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3707a8054027SBarry Smith @*/
3708d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3709d71ae5a4SJacob Faibussowitsch {
3710a8054027SBarry Smith   PetscFunctionBegin;
37110700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3712a8054027SBarry Smith   *lag = snes->lagpreconditioner;
37133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3714a8054027SBarry Smith }
3715a8054027SBarry Smith 
3716e35cf81dSBarry Smith /*@
3717f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3718e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3719e35cf81dSBarry Smith 
3720c3339decSBarry Smith   Logically Collective
3721e35cf81dSBarry Smith 
3722e35cf81dSBarry Smith   Input Parameters:
3723f6dfbefdSBarry Smith + snes - the `SNES` context
3724e35cf81dSBarry Smith - lag  - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
3725fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3726e35cf81dSBarry Smith 
3727e35cf81dSBarry Smith   Options Database Keys:
372879a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37293d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
373079a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37313d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3732e35cf81dSBarry Smith 
3733dc4c0fb0SBarry Smith   Level: intermediate
3734dc4c0fb0SBarry Smith 
3735e35cf81dSBarry Smith   Notes:
3736e35cf81dSBarry Smith   The default is 1
3737f6dfbefdSBarry Smith 
3738e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3739f6dfbefdSBarry Smith 
3740fe3ffe1eSBarry Smith   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
3741fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3742e35cf81dSBarry Smith 
37433201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3744e35cf81dSBarry Smith @*/
3745d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3746d71ae5a4SJacob Faibussowitsch {
3747e35cf81dSBarry Smith   PetscFunctionBegin;
37480700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
37495f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
37505f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3751c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3752e35cf81dSBarry Smith   snes->lagjacobian = lag;
37533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3754e35cf81dSBarry Smith }
3755e35cf81dSBarry Smith 
3756e35cf81dSBarry Smith /*@
3757f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3758e35cf81dSBarry Smith 
37593f9fe445SBarry Smith   Not Collective
3760e35cf81dSBarry Smith 
3761e35cf81dSBarry Smith   Input Parameter:
3762f6dfbefdSBarry Smith . snes - the `SNES` context
3763e35cf81dSBarry Smith 
3764e35cf81dSBarry Smith   Output Parameter:
3765e35cf81dSBarry Smith . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
3766e35cf81dSBarry Smith          the Jacobian is built etc.
3767e35cf81dSBarry Smith 
3768dc4c0fb0SBarry Smith   Level: intermediate
3769dc4c0fb0SBarry Smith 
3770e35cf81dSBarry Smith   Notes:
3771e35cf81dSBarry Smith   The default is 1
3772f6dfbefdSBarry Smith 
3773f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3774e35cf81dSBarry Smith 
37753201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3776e35cf81dSBarry Smith 
3777e35cf81dSBarry Smith @*/
3778d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3779d71ae5a4SJacob Faibussowitsch {
3780e35cf81dSBarry Smith   PetscFunctionBegin;
37810700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3782e35cf81dSBarry Smith   *lag = snes->lagjacobian;
37833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3784e35cf81dSBarry Smith }
3785e35cf81dSBarry Smith 
378637ec4e1aSPeter Brune /*@
3787f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
378837ec4e1aSPeter Brune 
3789c3339decSBarry Smith   Logically collective
379037ec4e1aSPeter Brune 
3791d8d19677SJose E. Roman   Input Parameters:
3792f6dfbefdSBarry Smith + snes - the `SNES` context
37939d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
379437ec4e1aSPeter Brune 
379537ec4e1aSPeter Brune   Options Database Keys:
379679a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37973d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
379879a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37993d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
38003d5a8a6aSBarry Smith 
3801dc4c0fb0SBarry Smith   Level: advanced
3802dc4c0fb0SBarry Smith 
380395452b02SPatrick Sanan   Notes:
3804420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3805f6dfbefdSBarry Smith 
380695452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
380737ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
380837ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
380937ec4e1aSPeter Brune 
381042747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
381137ec4e1aSPeter Brune @*/
3812d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3813d71ae5a4SJacob Faibussowitsch {
381437ec4e1aSPeter Brune   PetscFunctionBegin;
381537ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
381637ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
381737ec4e1aSPeter Brune   snes->lagjac_persist = flg;
38183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
381937ec4e1aSPeter Brune }
382037ec4e1aSPeter Brune 
382137ec4e1aSPeter Brune /*@
3822d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
382337ec4e1aSPeter Brune 
3824c3339decSBarry Smith   Logically Collective
382537ec4e1aSPeter Brune 
3826d8d19677SJose E. Roman   Input Parameters:
3827f6dfbefdSBarry Smith + snes - the `SNES` context
38289d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
382937ec4e1aSPeter Brune 
383037ec4e1aSPeter Brune   Options Database Keys:
383179a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
38323d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
383379a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
38343d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
383537ec4e1aSPeter Brune 
3836dc4c0fb0SBarry Smith   Level: developer
3837dc4c0fb0SBarry Smith 
383895452b02SPatrick Sanan   Notes:
3839420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3840f6dfbefdSBarry Smith 
384195452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
384237ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
384337ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
384437ec4e1aSPeter Brune 
38451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
384637ec4e1aSPeter Brune @*/
3847d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3848d71ae5a4SJacob Faibussowitsch {
384937ec4e1aSPeter Brune   PetscFunctionBegin;
385037ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
385137ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
385237ec4e1aSPeter Brune   snes->lagpre_persist = flg;
38533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
385437ec4e1aSPeter Brune }
385537ec4e1aSPeter Brune 
38569b94acceSBarry Smith /*@
3857f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3858be5caee7SBarry Smith 
3859c3339decSBarry Smith   Logically Collective
3860be5caee7SBarry Smith 
3861be5caee7SBarry Smith   Input Parameters:
3862f6dfbefdSBarry Smith + snes  - the `SNES` context
3863f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3864be5caee7SBarry Smith 
3865f6dfbefdSBarry Smith   Options Database Key:
3866be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3867be5caee7SBarry Smith 
3868dc4c0fb0SBarry Smith   Level: intermediate
3869dc4c0fb0SBarry Smith 
3870f6dfbefdSBarry Smith   Note:
3871f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3872be5caee7SBarry Smith 
38733201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()`
3874be5caee7SBarry Smith @*/
3875d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3876d71ae5a4SJacob Faibussowitsch {
3877be5caee7SBarry Smith   PetscFunctionBegin;
3878be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3879be5caee7SBarry Smith   snes->forceiteration = force;
38803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3881be5caee7SBarry Smith }
3882be5caee7SBarry Smith 
388385216dc7SFande Kong /*@
3884f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
388585216dc7SFande Kong 
3886c3339decSBarry Smith   Logically Collective
388785216dc7SFande Kong 
38882fe279fdSBarry Smith   Input Parameter:
3889f6dfbefdSBarry Smith . snes - the `SNES` context
389085216dc7SFande Kong 
389185216dc7SFande Kong   Output Parameter:
3892dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
389385216dc7SFande Kong 
389406dd6b0eSSatish Balay   Level: intermediate
389506dd6b0eSSatish Balay 
38963201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()`
389785216dc7SFande Kong @*/
3898d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3899d71ae5a4SJacob Faibussowitsch {
390085216dc7SFande Kong   PetscFunctionBegin;
390185216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
390285216dc7SFande Kong   *force = snes->forceiteration;
39033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
390485216dc7SFande Kong }
3905be5caee7SBarry Smith 
3906be5caee7SBarry Smith /*@
39070b4b7b1cSBarry Smith   SNESSetTolerances - Sets various parameters used in `SNES` convergence tests.
39089b94acceSBarry Smith 
3909c3339decSBarry Smith   Logically Collective
3910c7afd0dbSLois Curfman McInnes 
39119b94acceSBarry Smith   Input Parameters:
3912f6dfbefdSBarry Smith + snes   - the `SNES` context
39130b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $
39140b4b7b1cSBarry Smith . rtol   - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $
39155358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
39160b4b7b1cSBarry Smith . maxit  - the maximum number of iterations allowed in the solver, default 50.
39170b4b7b1cSBarry Smith - maxf   - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000
3918fee21e36SBarry Smith 
391933174efeSLois Curfman McInnes   Options Database Keys:
392077e5a1f9SBarry Smith + -snes_atol <abstol>    - Sets `abstol`
392177e5a1f9SBarry Smith . -snes_rtol <rtol>      - Sets `rtol`
392277e5a1f9SBarry Smith . -snes_stol <stol>      - Sets `stol`
392377e5a1f9SBarry Smith . -snes_max_it <maxit>   - Sets `maxit`
392477e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum)
39259b94acceSBarry Smith 
392636851e7fSLois Curfman McInnes   Level: intermediate
392736851e7fSLois Curfman McInnes 
392877e5a1f9SBarry Smith   Note:
392977e5a1f9SBarry Smith   All parameters must be non-negative
393077e5a1f9SBarry Smith 
393177e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`.
393277e5a1f9SBarry Smith   The default value is the value in the object when its type is set.
393377e5a1f9SBarry Smith 
393477e5a1f9SBarry Smith   Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations.
393577e5a1f9SBarry Smith 
393677e5a1f9SBarry Smith   Fortran Note:
393777e5a1f9SBarry Smith   Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL`
393877e5a1f9SBarry Smith 
39393201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
39409b94acceSBarry Smith @*/
3941d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3942d71ae5a4SJacob Faibussowitsch {
39433a40ed3dSBarry Smith   PetscFunctionBegin;
39440700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3945c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3946c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3947c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3948c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3949c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3950c5eb9154SBarry Smith 
395177e5a1f9SBarry Smith   if (abstol == (PetscReal)PETSC_DETERMINE) {
395277e5a1f9SBarry Smith     snes->abstol = snes->default_abstol;
395377e5a1f9SBarry Smith   } else if (abstol != (PetscReal)PETSC_CURRENT) {
39545f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3955ab54825eSJed Brown     snes->abstol = abstol;
3956ab54825eSJed Brown   }
395777e5a1f9SBarry Smith 
395877e5a1f9SBarry Smith   if (rtol == (PetscReal)PETSC_DETERMINE) {
395977e5a1f9SBarry Smith     snes->rtol = snes->default_rtol;
396077e5a1f9SBarry Smith   } else if (rtol != (PetscReal)PETSC_CURRENT) {
39615f80ce2aSJacob Faibussowitsch     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);
3962ab54825eSJed Brown     snes->rtol = rtol;
3963ab54825eSJed Brown   }
396477e5a1f9SBarry Smith 
396577e5a1f9SBarry Smith   if (stol == (PetscReal)PETSC_DETERMINE) {
396677e5a1f9SBarry Smith     snes->stol = snes->default_stol;
396777e5a1f9SBarry Smith   } else if (stol != (PetscReal)PETSC_CURRENT) {
39685f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3969c60f73f4SPeter Brune     snes->stol = stol;
3970ab54825eSJed Brown   }
397177e5a1f9SBarry Smith 
3972835f2295SStefano Zampini   if (maxit == PETSC_DETERMINE) {
397377e5a1f9SBarry Smith     snes->max_its = snes->default_max_its;
3974835f2295SStefano Zampini   } else if (maxit == PETSC_UNLIMITED) {
397577e5a1f9SBarry Smith     snes->max_its = PETSC_INT_MAX;
397677e5a1f9SBarry Smith   } else if (maxit != PETSC_CURRENT) {
397763a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3978ab54825eSJed Brown     snes->max_its = maxit;
3979ab54825eSJed Brown   }
398077e5a1f9SBarry Smith 
3981835f2295SStefano Zampini   if (maxf == PETSC_DETERMINE) {
398277e5a1f9SBarry Smith     snes->max_funcs = snes->default_max_funcs;
3983835f2295SStefano Zampini   } else if (maxf == PETSC_UNLIMITED || maxf == -1) {
398477e5a1f9SBarry Smith     snes->max_funcs = PETSC_UNLIMITED;
398577e5a1f9SBarry Smith   } else if (maxf != PETSC_CURRENT) {
398677e5a1f9SBarry Smith     PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf);
3987ab54825eSJed Brown     snes->max_funcs = maxf;
3988ab54825eSJed Brown   }
39893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39909b94acceSBarry Smith }
39919b94acceSBarry Smith 
3992e4d06f11SPatrick Farrell /*@
3993f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3994e4d06f11SPatrick Farrell 
3995c3339decSBarry Smith   Logically Collective
3996e4d06f11SPatrick Farrell 
3997e4d06f11SPatrick Farrell   Input Parameters:
3998f6dfbefdSBarry Smith + snes   - the `SNES` context
39990b4b7b1cSBarry Smith - divtol - the divergence tolerance. Use `PETSC_UNLIMITED` to deactivate the test. If the residual norm $ F(x^n) \ge divtol * F(x^0) $ the solver
40000b4b7b1cSBarry Smith            is stopped due to divergence.
4001e4d06f11SPatrick Farrell 
4002f6dfbefdSBarry Smith   Options Database Key:
4003dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
4004e4d06f11SPatrick Farrell 
4005e4d06f11SPatrick Farrell   Level: intermediate
4006e4d06f11SPatrick Farrell 
400777e5a1f9SBarry Smith   Notes:
400877e5a1f9SBarry Smith   Use `PETSC_DETERMINE` to use the default value from when the object's type was set.
4009e5cd489fSStefano Zampini 
401077e5a1f9SBarry Smith   Fortran Note:
401177e5a1f9SBarry Smith   Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL`
401277e5a1f9SBarry Smith 
401377e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()`
4014e4d06f11SPatrick Farrell @*/
4015d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
4016d71ae5a4SJacob Faibussowitsch {
4017e4d06f11SPatrick Farrell   PetscFunctionBegin;
4018e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4019e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
402077e5a1f9SBarry Smith 
402177e5a1f9SBarry Smith   if (divtol == (PetscReal)PETSC_DETERMINE) {
402277e5a1f9SBarry Smith     snes->divtol = snes->default_divtol;
402377e5a1f9SBarry Smith   } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) {
402477e5a1f9SBarry Smith     snes->divtol = PETSC_UNLIMITED;
402577e5a1f9SBarry Smith   } else if (divtol != (PetscReal)PETSC_CURRENT) {
402677e5a1f9SBarry Smith     PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol);
402777e5a1f9SBarry Smith     snes->divtol = divtol;
402877e5a1f9SBarry Smith   }
40293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4030e4d06f11SPatrick Farrell }
4031e4d06f11SPatrick Farrell 
40329b94acceSBarry Smith /*@
40330b4b7b1cSBarry Smith   SNESGetTolerances - Gets various parameters used in `SNES` convergence tests.
403433174efeSLois Curfman McInnes 
4035c7afd0dbSLois Curfman McInnes   Not Collective
4036c7afd0dbSLois Curfman McInnes 
403777e5a1f9SBarry Smith   Input Parameter:
403877e5a1f9SBarry Smith . snes - the `SNES` context
403977e5a1f9SBarry Smith 
404077e5a1f9SBarry Smith   Output Parameters:
40410b4b7b1cSBarry Smith + atol  - the absolute convergence tolerance
40420b4b7b1cSBarry Smith . rtol  - the relative convergence tolerance
404377e5a1f9SBarry Smith . stol  - convergence tolerance in terms of the norm of the change in the solution between steps
40440b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed
40450b4b7b1cSBarry Smith - maxf  - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound
4046fee21e36SBarry Smith 
404736851e7fSLois Curfman McInnes   Level: intermediate
404836851e7fSLois Curfman McInnes 
40490b4b7b1cSBarry Smith   Notes:
40500b4b7b1cSBarry Smith   See `SNESSetTolerances()` for details on the parameters.
40510b4b7b1cSBarry Smith 
4052dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
4053dc4c0fb0SBarry Smith 
40541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
405533174efeSLois Curfman McInnes @*/
4056d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
4057d71ae5a4SJacob Faibussowitsch {
40583a40ed3dSBarry Smith   PetscFunctionBegin;
40590700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
406085385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
406133174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
4062c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
406333174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
406433174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
40653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
406633174efeSLois Curfman McInnes }
406733174efeSLois Curfman McInnes 
4068e4d06f11SPatrick Farrell /*@
4069e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
4070e4d06f11SPatrick Farrell 
4071e4d06f11SPatrick Farrell   Not Collective
4072e4d06f11SPatrick Farrell 
4073e4d06f11SPatrick Farrell   Input Parameters:
4074f6dfbefdSBarry Smith + snes   - the `SNES` context
4075e4d06f11SPatrick Farrell - divtol - divergence tolerance
4076e4d06f11SPatrick Farrell 
4077e4d06f11SPatrick Farrell   Level: intermediate
4078e4d06f11SPatrick Farrell 
40791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
4080e4d06f11SPatrick Farrell @*/
4081d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
4082d71ae5a4SJacob Faibussowitsch {
4083e4d06f11SPatrick Farrell   PetscFunctionBegin;
4084e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4085e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
40863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4087e4d06f11SPatrick Farrell }
4088e4d06f11SPatrick Farrell 
40896ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
40906ba87a44SLisandro Dalcin 
4091d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
4092d71ae5a4SJacob Faibussowitsch {
4093b271bb04SBarry Smith   PetscDrawLG      lg;
4094b271bb04SBarry Smith   PetscReal        x, y, per;
4095b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
4096b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
4097b271bb04SBarry Smith   PetscDraw        draw;
4098b271bb04SBarry Smith 
4099459f5d12SBarry Smith   PetscFunctionBegin;
41004d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
41019566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
41029566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
41039566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
41049566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
4105b271bb04SBarry Smith   x = (PetscReal)n;
410677b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
410794c9c6d3SKarl Rupp   else y = -15.0;
41089566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
41096934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41109566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41119566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4112b271bb04SBarry Smith   }
4113b271bb04SBarry Smith 
41149566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
41159566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
41169566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4117aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
41189566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
4119b271bb04SBarry Smith   x = (PetscReal)n;
4120b271bb04SBarry Smith   y = 100.0 * per;
41219566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
41226934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41239566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41249566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4125b271bb04SBarry Smith   }
4126b271bb04SBarry Smith 
41279566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
41289371c9d4SSatish Balay   if (!n) {
41299371c9d4SSatish Balay     prev = rnorm;
41309371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
41319371c9d4SSatish Balay   }
41329566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
41339566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
4134b271bb04SBarry Smith   x = (PetscReal)n;
4135b271bb04SBarry Smith   y = (prev - rnorm) / prev;
41369566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
41376934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41389566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41399566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4140b271bb04SBarry Smith   }
4141b271bb04SBarry Smith 
41429566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
41439566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
41449566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
41459566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
4146b271bb04SBarry Smith   x = (PetscReal)n;
4147b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
4148b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
41499566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4150b271bb04SBarry Smith   }
41516934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41529566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41539566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4154b271bb04SBarry Smith   }
4155b271bb04SBarry Smith   prev = rnorm;
41563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4157b271bb04SBarry Smith }
4158b271bb04SBarry Smith 
4159228d79bcSJed Brown /*@
41602d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
41612d157150SStefano Zampini 
41622d157150SStefano Zampini   Collective
41632d157150SStefano Zampini 
41642d157150SStefano Zampini   Input Parameters:
41652d157150SStefano Zampini + snes  - the `SNES` context
41662d157150SStefano Zampini . it    - current iteration
41672d157150SStefano Zampini . xnorm - 2-norm of current iterate
41682d157150SStefano Zampini . snorm - 2-norm of current step
41692d157150SStefano Zampini - fnorm - 2-norm of function
41702d157150SStefano Zampini 
41712d157150SStefano Zampini   Level: developer
41722d157150SStefano Zampini 
41732d157150SStefano Zampini   Note:
4174420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
41752d157150SStefano Zampini   It does not typically need to be called by the user.
41762d157150SStefano Zampini 
4177c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
41782d157150SStefano Zampini @*/
41792d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
41802d157150SStefano Zampini {
41812d157150SStefano Zampini   PetscFunctionBegin;
41822d157150SStefano Zampini   if (!snes->reason) {
41832d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
41842d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
41852d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
41862d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
41872d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
41882d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
41892d157150SStefano Zampini     }
41902d157150SStefano Zampini   }
41912d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
41922d157150SStefano Zampini }
41932d157150SStefano Zampini 
41942d157150SStefano Zampini /*@
41950b4b7b1cSBarry Smith   SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database
4196228d79bcSJed Brown 
4197c3339decSBarry Smith   Collective
4198228d79bcSJed Brown 
4199228d79bcSJed Brown   Input Parameters:
4200f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
42010b4b7b1cSBarry Smith . iter  - current iteration number
42020b4b7b1cSBarry Smith - rnorm - current relative norm of the residual
4203228d79bcSJed Brown 
4204dc4c0fb0SBarry Smith   Level: developer
4205dc4c0fb0SBarry Smith 
4206f6dfbefdSBarry Smith   Note:
4207420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
4208228d79bcSJed Brown   It does not typically need to be called by the user.
4209228d79bcSJed Brown 
42101cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4211228d79bcSJed Brown @*/
4212d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4213d71ae5a4SJacob Faibussowitsch {
42147a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
42157a03ce2fSLisandro Dalcin 
42167a03ce2fSLisandro Dalcin   PetscFunctionBegin;
42179566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
421848a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
42199566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
42203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42217a03ce2fSLisandro Dalcin }
42227a03ce2fSLisandro Dalcin 
42239b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
42249b94acceSBarry Smith 
4225bf388a1fSBarry Smith /*MC
4226f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4227bf388a1fSBarry Smith 
4228bf388a1fSBarry Smith      Synopsis:
4229aaa7dc30SBarry Smith      #include <petscsnes.h>
423037fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4231bf388a1fSBarry Smith 
4232c3339decSBarry Smith      Collective
42331843f636SBarry Smith 
42341843f636SBarry Smith     Input Parameters:
4235f6dfbefdSBarry Smith +    snes - the `SNES` context
4236bf388a1fSBarry Smith .    its - iteration number
4237bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
4238bf388a1fSBarry Smith -    mctx - [optional] monitoring context
4239bf388a1fSBarry Smith 
4240878cb397SSatish Balay    Level: advanced
4241878cb397SSatish Balay 
424256296ac4SStefano Zampini .seealso: [](ch_snes), `SNESMonitorSet()`
4243bf388a1fSBarry Smith M*/
4244bf388a1fSBarry Smith 
42459b94acceSBarry Smith /*@C
4246a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
42470b4b7b1cSBarry Smith   iteration of the `SNES` nonlinear solver to display the iteration's
42489b94acceSBarry Smith   progress.
42499b94acceSBarry Smith 
4250c3339decSBarry Smith   Logically Collective
4251fee21e36SBarry Smith 
4252c7afd0dbSLois Curfman McInnes   Input Parameters:
4253f6dfbefdSBarry Smith + snes           - the `SNES` context
425420f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4255420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
425649abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
42579b94acceSBarry Smith 
42589665c990SLois Curfman McInnes   Options Database Keys:
4259f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4260798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4261dc4c0fb0SBarry Smith - -snes_monitor_cancel        - cancels all monitors that have been hardwired into a code by calls to `SNESMonitorSet()`, but does not cancel those set via
4262c7afd0dbSLois Curfman McInnes                                 the options database.
42639665c990SLois Curfman McInnes 
4264dc4c0fb0SBarry Smith   Level: intermediate
4265dc4c0fb0SBarry Smith 
4266f6dfbefdSBarry Smith   Note:
42676bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4268f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
42696bc08f3fSLois Curfman McInnes   order in which they were set.
4270639f9d9dSBarry Smith 
4271420bcc1bSBarry Smith   Fortran Note:
4272f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4273025f1a04SBarry Smith 
427449abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn`
42759b94acceSBarry Smith @*/
427649abdd8aSBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy)
4277d71ae5a4SJacob Faibussowitsch {
42783a40ed3dSBarry Smith   PetscFunctionBegin;
42790700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4280453a69bbSBarry Smith   for (PetscInt i = 0; i < snes->numbermonitors; i++) {
4281453a69bbSBarry Smith     PetscBool identical;
4282453a69bbSBarry Smith 
4283453a69bbSBarry Smith     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, mctx, monitordestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
42843ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4285649052a6SBarry Smith   }
42865f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
42876e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4288b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4289835f2295SStefano Zampini   snes->monitorcontext[snes->numbermonitors++] = mctx;
42903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42919b94acceSBarry Smith }
42929b94acceSBarry Smith 
4293a278d85bSSatish Balay /*@
4294f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
42955cd90555SBarry Smith 
4296c3339decSBarry Smith   Logically Collective
4297c7afd0dbSLois Curfman McInnes 
42982fe279fdSBarry Smith   Input Parameter:
4299f6dfbefdSBarry Smith . snes - the `SNES` context
43005cd90555SBarry Smith 
43011a480d89SAdministrator   Options Database Key:
4302a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4303dc4c0fb0SBarry Smith                          into a code by calls to `SNESMonitorSet()`, but does not cancel those
4304c7afd0dbSLois Curfman McInnes                          set via the options database
43055cd90555SBarry Smith 
4306dc4c0fb0SBarry Smith   Level: intermediate
4307dc4c0fb0SBarry Smith 
4308f6dfbefdSBarry Smith   Note:
4309f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
43105cd90555SBarry Smith 
431156296ac4SStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESMonitorDefault()`, `SNESMonitorSet()`
43125cd90555SBarry Smith @*/
4313d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4314d71ae5a4SJacob Faibussowitsch {
4315d952e501SBarry Smith   PetscInt i;
4316d952e501SBarry Smith 
43175cd90555SBarry Smith   PetscFunctionBegin;
43180700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4319d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
432048a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4321d952e501SBarry Smith   }
43225cd90555SBarry Smith   snes->numbermonitors = 0;
43233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43245cd90555SBarry Smith }
43255cd90555SBarry Smith 
4326bf388a1fSBarry Smith /*MC
4327bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4328bf388a1fSBarry Smith 
4329bf388a1fSBarry Smith      Synopsis:
4330aaa7dc30SBarry Smith      #include <petscsnes.h>
433137fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4332bf388a1fSBarry Smith 
4333c3339decSBarry Smith      Collective
43341843f636SBarry Smith 
43351843f636SBarry Smith     Input Parameters:
4336f6dfbefdSBarry Smith +    snes - the `SNES` context
4337bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4338bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4339bf388a1fSBarry Smith .    gnorm - 2-norm of current step
43401843f636SBarry Smith .    f - 2-norm of function
43411843f636SBarry Smith -    cctx - [optional] convergence context
43421843f636SBarry Smith 
43431843f636SBarry Smith     Output Parameter:
43441843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4345bf388a1fSBarry Smith 
4346878cb397SSatish Balay    Level: intermediate
4347bf388a1fSBarry Smith 
4348c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
4349bf388a1fSBarry Smith M*/
4350bf388a1fSBarry Smith 
43519b94acceSBarry Smith /*@C
43529b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
43539b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
43549b94acceSBarry Smith 
4355c3339decSBarry Smith   Logically Collective
4356fee21e36SBarry Smith 
4357c7afd0dbSLois Curfman McInnes   Input Parameters:
4358f6dfbefdSBarry Smith + snes                        - the `SNES` context
4359e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4360dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4361dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
43629b94acceSBarry Smith 
436336851e7fSLois Curfman McInnes   Level: advanced
436436851e7fSLois Curfman McInnes 
43651cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
43669b94acceSBarry Smith @*/
436712651944SBarry Smith PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscCtxDestroyFn *destroy)
4368d71ae5a4SJacob Faibussowitsch {
43693a40ed3dSBarry Smith   PetscFunctionBegin;
43700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4371e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
437212651944SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(&snes->cnvP));
4373bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
43747f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
437585385478SLisandro Dalcin   snes->cnvP                  = cctx;
43763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43779b94acceSBarry Smith }
43789b94acceSBarry Smith 
437952baeb72SSatish Balay /*@
43800b4b7b1cSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation
4381184914b5SBarry Smith 
4382184914b5SBarry Smith   Not Collective
4383184914b5SBarry Smith 
4384184914b5SBarry Smith   Input Parameter:
4385f6dfbefdSBarry Smith . snes - the `SNES` context
4386184914b5SBarry Smith 
4387184914b5SBarry Smith   Output Parameter:
4388f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4389184914b5SBarry Smith 
4390f6dfbefdSBarry Smith   Options Database Key:
43916a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
43926a4d7782SBarry Smith 
4393184914b5SBarry Smith   Level: intermediate
4394184914b5SBarry Smith 
4395f6dfbefdSBarry Smith   Note:
4396f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4397184914b5SBarry Smith 
43981cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4399184914b5SBarry Smith @*/
4400d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4401d71ae5a4SJacob Faibussowitsch {
4402184914b5SBarry Smith   PetscFunctionBegin;
44030700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44044f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4405184914b5SBarry Smith   *reason = snes->reason;
44063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4407184914b5SBarry Smith }
4408184914b5SBarry Smith 
4409c4421ceaSFande Kong /*@C
4410f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4411c4421ceaSFande Kong 
4412c4421ceaSFande Kong   Not Collective
4413c4421ceaSFande Kong 
4414c4421ceaSFande Kong   Input Parameter:
4415f6dfbefdSBarry Smith . snes - the `SNES` context
4416c4421ceaSFande Kong 
4417c4421ceaSFande Kong   Output Parameter:
4418dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4419c4421ceaSFande Kong 
442099c90e12SSatish Balay   Level: beginner
4421c4421ceaSFande Kong 
44221cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4423c4421ceaSFande Kong @*/
4424d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4425d71ae5a4SJacob Faibussowitsch {
4426c4421ceaSFande Kong   PetscFunctionBegin;
4427c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44284f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4429c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
44303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4431c4421ceaSFande Kong }
4432c4421ceaSFande Kong 
443333866048SMatthew G. Knepley /*@
4434f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
443533866048SMatthew G. Knepley 
443633866048SMatthew G. Knepley   Not Collective
443733866048SMatthew G. Knepley 
443833866048SMatthew G. Knepley   Input Parameters:
4439f6dfbefdSBarry Smith + snes   - the `SNES` context
4440f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
444133866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
444233866048SMatthew G. Knepley 
4443f6dfbefdSBarry Smith   Level: developer
4444f6dfbefdSBarry Smith 
4445420bcc1bSBarry Smith   Developer Note:
4446f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
444733866048SMatthew G. Knepley 
44481cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
444933866048SMatthew G. Knepley @*/
4450d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4451d71ae5a4SJacob Faibussowitsch {
445233866048SMatthew G. Knepley   PetscFunctionBegin;
445333866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44545f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
445533866048SMatthew G. Knepley   snes->reason = reason;
44563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
445733866048SMatthew G. Knepley }
445833866048SMatthew G. Knepley 
4459c9005455SLois Curfman McInnes /*@
4460420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4461c9005455SLois Curfman McInnes 
4462c3339decSBarry Smith   Logically Collective
4463fee21e36SBarry Smith 
4464c7afd0dbSLois Curfman McInnes   Input Parameters:
4465f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
44668c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4467cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4468420bcc1bSBarry Smith . na    - size of `a` and `its`
4469f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4470758f92a0SBarry Smith           else it continues storing new values for new nonlinear solves after the old ones
4471c7afd0dbSLois Curfman McInnes 
4472dc4c0fb0SBarry Smith   Level: intermediate
4473dc4c0fb0SBarry Smith 
4474308dcc3eSBarry Smith   Notes:
4475ce78bad3SBarry Smith   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` (or, deprecated, `PETSC_DEFAULT`) then a
447677e5a1f9SBarry Smith   default array of length 1,000 is allocated.
4477308dcc3eSBarry Smith 
4478c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4479c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4480c9005455SLois Curfman McInnes   during the section of code that is being timed.
4481c9005455SLois Curfman McInnes 
4482420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4483420bcc1bSBarry Smith 
44841cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4485c9005455SLois Curfman McInnes @*/
4486d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4487d71ae5a4SJacob Faibussowitsch {
44883a40ed3dSBarry Smith   PetscFunctionBegin;
44890700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44904f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
44914f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
44927a1ec6d4SBarry Smith   if (!a) {
449377e5a1f9SBarry Smith     if (na == PETSC_DECIDE) na = 1000;
44949566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4495071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4496308dcc3eSBarry Smith   }
4497c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4498758f92a0SBarry Smith   snes->conv_hist_its   = its;
4499115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4500a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4501758f92a0SBarry Smith   snes->conv_hist_reset = reset;
45023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4503758f92a0SBarry Smith }
4504758f92a0SBarry Smith 
4505d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4506c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4507c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
450899e0435eSBarry Smith 
4509d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4510d71ae5a4SJacob Faibussowitsch {
4511308dcc3eSBarry Smith   mxArray   *mat;
4512308dcc3eSBarry Smith   PetscInt   i;
4513308dcc3eSBarry Smith   PetscReal *ar;
4514308dcc3eSBarry Smith 
4515308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4516308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4517f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
451811cc89d2SBarry Smith   return mat;
4519308dcc3eSBarry Smith }
4520308dcc3eSBarry Smith #endif
4521308dcc3eSBarry Smith 
45220c4c9dddSBarry Smith /*@C
4523420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4524758f92a0SBarry Smith 
45253f9fe445SBarry Smith   Not Collective
4526758f92a0SBarry Smith 
4527758f92a0SBarry Smith   Input Parameter:
4528f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4529758f92a0SBarry Smith 
4530758f92a0SBarry Smith   Output Parameters:
4531f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4532758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4533758f92a0SBarry Smith          negative if not converged) for each solve.
453420f4b53cSBarry Smith - na  - size of `a` and `its`
4535758f92a0SBarry Smith 
4536dc4c0fb0SBarry Smith   Level: intermediate
4537dc4c0fb0SBarry Smith 
453820f4b53cSBarry Smith   Note:
453920f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
454020f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
454120f4b53cSBarry Smith   during the section of code that is being timed.
454220f4b53cSBarry Smith 
4543ce78bad3SBarry Smith   Fortran Notes:
4544ce78bad3SBarry Smith   Return the arrays with ``SNESRestoreConvergenceHistory()`
4545ce78bad3SBarry Smith 
4546ce78bad3SBarry Smith   Use the arguments
4547dc4c0fb0SBarry Smith .vb
4548ce78bad3SBarry Smith   PetscReal, pointer :: a(:)
4549ce78bad3SBarry Smith   PetscInt, pointer :: its(:)
4550dc4c0fb0SBarry Smith .ve
4551758f92a0SBarry Smith 
45521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4553758f92a0SBarry Smith @*/
4554d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4555d71ae5a4SJacob Faibussowitsch {
4556758f92a0SBarry Smith   PetscFunctionBegin;
45570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4558758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4559758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4560115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
45613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4562c9005455SLois Curfman McInnes }
4563c9005455SLois Curfman McInnes 
4564ac226902SBarry Smith /*@C
456576b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4566eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
456753e5d35bSStefano Zampini   it is called just before the Jacobian is "evaluated" and after the function
456853e5d35bSStefano Zampini   evaluation.
456976b2cf59SMatthew Knepley 
4570c3339decSBarry Smith   Logically Collective
457176b2cf59SMatthew Knepley 
457276b2cf59SMatthew Knepley   Input Parameters:
4573a2b725a8SWilliam Gropp + snes - The nonlinear solver context
457453e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn`
457576b2cf59SMatthew Knepley 
4576fe97e370SBarry Smith   Level: advanced
4577fe97e370SBarry Smith 
4578420bcc1bSBarry Smith   Notes:
4579f6dfbefdSBarry Smith   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
4580f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
458153e5d35bSStefano Zampini   This is not used by most users, and it is intended to provide a general hook that is run
458253e5d35bSStefano Zampini   right before the direction step is computed.
4583ce78bad3SBarry Smith 
458453e5d35bSStefano Zampini   Users are free to modify the current residual vector,
458553e5d35bSStefano Zampini   the current linearization point, or any other vector associated to the specific solver used.
458653e5d35bSStefano Zampini   If such modifications take place, it is the user responsibility to update all the relevant
4587ce78bad3SBarry Smith   vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like
4588ce78bad3SBarry Smith .vb
4589ce78bad3SBarry Smith   PetscErrorCode update(SNES snes, PetscInt iteration)
4590ce78bad3SBarry Smith   {
4591ce78bad3SBarry Smith     PetscFunctionBeginUser;
4592ce78bad3SBarry Smith     if (iteration > 0) {
4593ce78bad3SBarry Smith       // update the model parameters here
4594ce78bad3SBarry Smith       Vec x,f;
4595ce78bad3SBarry Smith       PetscCall(SNESGetSolution(snes,&x));
4596ce78bad3SBarry Smith       PetcCall(SNESGetFunction(snes,&f,NULL,NULL));
4597ce78bad3SBarry Smith       PetscCall(SNESComputeFunction(snes,x,f));
4598ce78bad3SBarry Smith     }
4599ce78bad3SBarry Smith     PetscFunctionReturn(PETSC_SUCCESS);
4600ce78bad3SBarry Smith   }
4601ce78bad3SBarry Smith .ve
460276b2cf59SMatthew Knepley 
4603aaa8cc7dSPierre Jolivet   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.
46046b7fb656SBarry Smith 
4605e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
460653e5d35bSStefano Zampini          `SNESMonitorSet()`
460776b2cf59SMatthew Knepley @*/
460853e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4609d71ae5a4SJacob Faibussowitsch {
461076b2cf59SMatthew Knepley   PetscFunctionBegin;
46110700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4612e7788613SBarry Smith   snes->ops->update = func;
46133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
461476b2cf59SMatthew Knepley }
461576b2cf59SMatthew Knepley 
4616ffeef943SBarry Smith /*@
4617f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
46182a359c20SBarry Smith 
4619c3339decSBarry Smith   Collective
46202a359c20SBarry Smith 
4621e4094ef1SJacob Faibussowitsch   Input Parameters:
4622f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
46232a359c20SBarry Smith - viewer - the viewer to display the reason
46242a359c20SBarry Smith 
46252a359c20SBarry Smith   Options Database Keys:
4626ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4627ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4628eafd5ff0SAlex Lindsay 
4629420bcc1bSBarry Smith   Level: beginner
4630420bcc1bSBarry Smith 
4631f6dfbefdSBarry Smith   Note:
4632f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4633f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
46342a359c20SBarry Smith 
46351cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4636f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4637f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4638db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
46392a359c20SBarry Smith @*/
4640d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4641d71ae5a4SJacob Faibussowitsch {
464275cca76cSMatthew G. Knepley   PetscViewerFormat format;
46432a359c20SBarry Smith   PetscBool         isAscii;
46442a359c20SBarry Smith 
46452a359c20SBarry Smith   PetscFunctionBegin;
464619a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
46479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
46482a359c20SBarry Smith   if (isAscii) {
46499566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
465065bf60d2SBarry Smith     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
465175cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
465275cca76cSMatthew G. Knepley       DM       dm;
465375cca76cSMatthew G. Knepley       Vec      u;
465475cca76cSMatthew G. Knepley       PetscDS  prob;
465575cca76cSMatthew G. Knepley       PetscInt Nf, f;
465695cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
465795cbbfd3SMatthew G. Knepley       void    **exactCtx;
465875cca76cSMatthew G. Knepley       PetscReal error;
465975cca76cSMatthew G. Knepley 
46609566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
46619566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
46629566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
46639566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
46649566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
46659566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
46669566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
46679566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
46689566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
466963a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
467075cca76cSMatthew G. Knepley     }
4671eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
46722a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
467363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
46742a359c20SBarry Smith       } else {
467563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46762a359c20SBarry Smith       }
4677eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
46782a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
467963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve did not converge due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
46802a359c20SBarry Smith       } else {
468163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46822a359c20SBarry Smith       }
46832a359c20SBarry Smith     }
468465bf60d2SBarry Smith     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
46852a359c20SBarry Smith   }
46863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46872a359c20SBarry Smith }
46882a359c20SBarry Smith 
4689c4421ceaSFande Kong /*@C
4690c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4691aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4692c4421ceaSFande Kong 
4693c3339decSBarry Smith   Logically Collective
4694c4421ceaSFande Kong 
4695c4421ceaSFande Kong   Input Parameters:
4696f6dfbefdSBarry Smith + snes              - the `SNES` context
4697420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4698420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
469949abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
4700420bcc1bSBarry Smith 
4701420bcc1bSBarry Smith   Calling sequence of `f`:
4702420bcc1bSBarry Smith + snes - the `SNES` context
470349abdd8aSBarry Smith - vctx - [optional] context for private data for the function
4704c4421ceaSFande Kong 
4705c4421ceaSFande Kong   Options Database Keys:
4706f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4707420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4708420bcc1bSBarry Smith                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4709c4421ceaSFande Kong 
4710dc4c0fb0SBarry Smith   Level: intermediate
4711dc4c0fb0SBarry Smith 
4712f6dfbefdSBarry Smith   Note:
4713c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4714f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4715c4421ceaSFande Kong   order in which they were set.
4716c4421ceaSFande Kong 
471749abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`,
471849abdd8aSBarry Smith           `PetscCtxDestroyFn`
4719c4421ceaSFande Kong @*/
472049abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy)
4721d71ae5a4SJacob Faibussowitsch {
4722c4421ceaSFande Kong   PetscFunctionBegin;
4723c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4724453a69bbSBarry Smith   for (PetscInt i = 0; i < snes->numberreasonviews; i++) {
4725453a69bbSBarry Smith     PetscBool identical;
4726453a69bbSBarry Smith 
4727453a69bbSBarry Smith     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
47283ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4729c4421ceaSFande Kong   }
47305f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4731c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4732c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4733835f2295SStefano Zampini   snes->reasonviewcontext[snes->numberreasonviews++] = vctx;
47343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4735c4421ceaSFande Kong }
4736c4421ceaSFande Kong 
473791f3e32bSBarry Smith /*@
4738420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
47390b4b7b1cSBarry Smith   All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist.
47402a359c20SBarry Smith 
4741c3339decSBarry Smith   Collective
47422a359c20SBarry Smith 
47432fe279fdSBarry Smith   Input Parameter:
4744f6dfbefdSBarry Smith . snes - the `SNES` object
47452a359c20SBarry Smith 
4746f6dfbefdSBarry Smith   Level: advanced
47472a359c20SBarry Smith 
47481cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4749f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
47502a359c20SBarry Smith @*/
4751d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4752d71ae5a4SJacob Faibussowitsch {
47532a359c20SBarry Smith   static PetscBool incall = PETSC_FALSE;
47542a359c20SBarry Smith 
47552a359c20SBarry Smith   PetscFunctionBegin;
47563ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
47572a359c20SBarry Smith   incall = PETSC_TRUE;
4758c4421ceaSFande Kong 
4759c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
476036d43d94SBarry Smith   for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4761c4421ceaSFande Kong 
4762c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
476336d43d94SBarry Smith   if (snes->convergedreasonviewer) {
476436d43d94SBarry Smith     PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
476536d43d94SBarry Smith     PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
476636d43d94SBarry Smith     PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
47672a359c20SBarry Smith   }
47682a359c20SBarry Smith   incall = PETSC_FALSE;
47693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47702a359c20SBarry Smith }
47712a359c20SBarry Smith 
4772487a658cSBarry Smith /*@
47730b4b7b1cSBarry Smith   SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object
47749b94acceSBarry Smith 
4775c3339decSBarry Smith   Collective
4776c7afd0dbSLois Curfman McInnes 
4777b2002411SLois Curfman McInnes   Input Parameters:
4778f6dfbefdSBarry Smith + snes - the `SNES` context
47790b4b7b1cSBarry Smith . b    - the constant part of the equation $F(x) = b$, or `NULL` to use zero.
478085385478SLisandro Dalcin - x    - the solution vector.
47819b94acceSBarry Smith 
4782dc4c0fb0SBarry Smith   Level: beginner
4783dc4c0fb0SBarry Smith 
4784f6dfbefdSBarry Smith   Note:
4785420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4786a9b45538SStefano Zampini   for the nonlinear solve prior to calling `SNESSolve()` .
47878ddd3da0SLois Curfman McInnes 
47881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4789db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4790a9b45538SStefano Zampini           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
47919b94acceSBarry Smith @*/
4792d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4793d71ae5a4SJacob Faibussowitsch {
4794ace3abfcSBarry Smith   PetscBool flg;
4795efd51863SBarry Smith   PetscInt  grid;
47960298fd71SBarry Smith   Vec       xcreated = NULL;
4797caa4e7f2SJed Brown   DM        dm;
4798052efed2SBarry Smith 
47993a40ed3dSBarry Smith   PetscFunctionBegin;
48000700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4801a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4802a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
48030700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
480485385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
480585385478SLisandro Dalcin 
480634b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
480706fc46c8SMatthew G. Knepley   {
480806fc46c8SMatthew G. Knepley     PetscViewer       viewer;
480906fc46c8SMatthew G. Knepley     PetscViewerFormat format;
48107c88af5aSMatthew G. Knepley     PetscInt          num;
481106fc46c8SMatthew G. Knepley     PetscBool         flg;
481206fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
481306fc46c8SMatthew G. Knepley 
481406fc46c8SMatthew G. Knepley     if (!incall) {
481534b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
4816648c30bcSBarry Smith       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
481706fc46c8SMatthew G. Knepley       if (flg) {
481806fc46c8SMatthew G. Knepley         PetscConvEst conv;
481946079b62SMatthew G. Knepley         DM           dm;
482046079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
482146079b62SMatthew G. Knepley         PetscInt     Nf;
482206fc46c8SMatthew G. Knepley 
482306fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
48249566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
48259566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
48269566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
48279566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
48289566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
48299566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
48309566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
48319566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
48329566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
48339566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
48349566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4835648c30bcSBarry Smith         PetscCall(PetscViewerDestroy(&viewer));
48369566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
48379566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
483806fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
483906fc46c8SMatthew G. Knepley       }
484034b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4841b2588ea6SMatthew G. Knepley       num = 1;
48429566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
484334b4d3a8SMatthew G. Knepley       if (flg) {
484434b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
484534b4d3a8SMatthew G. Knepley 
484634b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
48479566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
48489566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48499566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48509566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48519566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
48529566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
48539566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
485434b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
485534b4d3a8SMatthew G. Knepley       }
48567c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
48577c88af5aSMatthew G. Knepley       num = 0;
48589566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
48597c88af5aSMatthew G. Knepley       if (num) {
48607c88af5aSMatthew G. Knepley         DMAdaptor   adaptor;
4861e03fd340SMatthew G. Knepley         const char *prefix;
48627c88af5aSMatthew G. Knepley 
48637c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
48649566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4865e03fd340SMatthew G. Knepley         PetscCall(SNESGetOptionsPrefix(snes, &prefix));
4866e03fd340SMatthew G. Knepley         PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix));
48679566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48689566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48699566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48709566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
4871e5148a0bSMatthew G. Knepley         PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
48729566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
48739566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
48747c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
48757c88af5aSMatthew G. Knepley       }
487606fc46c8SMatthew G. Knepley     }
487706fc46c8SMatthew G. Knepley   }
4878ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4879caa4e7f2SJed Brown   if (!x) {
48809566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
48819566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4882a69afd8bSBarry Smith     x = xcreated;
4883a69afd8bSBarry Smith   }
48849566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4885f05ece33SBarry Smith 
48869566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4887efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
488885385478SLisandro Dalcin     /* set solution vector */
48899566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
48909566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
489185385478SLisandro Dalcin     snes->vec_sol = x;
48929566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4893caa4e7f2SJed Brown 
4894caa4e7f2SJed Brown     /* set affine vector if provided */
48959566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
48969566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
489785385478SLisandro Dalcin     snes->vec_rhs = b;
489885385478SLisandro Dalcin 
48995f80ce2aSJacob Faibussowitsch     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");
49005f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4901dd8e379bSPierre Jolivet     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4902aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
49039566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
49049566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
49053f149594SLisandro Dalcin 
49067eee914bSBarry Smith     if (!grid) {
49079927e4dfSBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4908dd568438SSatish Balay     }
4909d25893d9SBarry Smith 
4910abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
491112b1dd1aSStefano Zampini     PetscCall(SNESResetCounters(snes));
49122d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
49139566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4914dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
49159566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
49162d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4917*76c63389SBarry Smith     snes->functiondomainerror  = PETSC_FALSE; /* clear the flag if it has been set */
4918*76c63389SBarry Smith     snes->objectivedomainerror = PETSC_FALSE; /* clear the flag if it has been set */
4919*76c63389SBarry Smith     snes->jacobiandomainerror  = PETSC_FALSE; /* clear the flag if it has been set */
49203f149594SLisandro Dalcin 
492137ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
492237ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
492337ec4e1aSPeter Brune 
4924648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
49259566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4926c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
49279566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
49285968eb51SBarry Smith 
49291b3000acSStefano Zampini     if (snes->errorifnotconverged) {
49301b3000acSStefano Zampini       if (snes->reason < 0) PetscCall(SNESMonitorCancel(snes));
49311b3000acSStefano Zampini       PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
49321b3000acSStefano Zampini     }
49339c8e83a9SBarry Smith     if (snes->reason < 0) break;
4934efd51863SBarry Smith     if (grid < snes->gridsequence) {
4935efd51863SBarry Smith       DM  fine;
4936efd51863SBarry Smith       Vec xnew;
4937efd51863SBarry Smith       Mat interp;
4938efd51863SBarry Smith 
49399566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
49405f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
49412eace19aSMatthew G. Knepley       PetscCall(DMGetCoordinatesLocalSetUp(fine));
49429566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
49439566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
49449566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
49459566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
49469566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4947efd51863SBarry Smith       x = xnew;
4948efd51863SBarry Smith 
49499566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
49509566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
49519566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
49529566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
49539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4954efd51863SBarry Smith     }
4955efd51863SBarry Smith   }
49569566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
49579566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
49589566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
49599566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
49603f7e2da0SPeter Brune 
49619566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
49629566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
49633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49649b94acceSBarry Smith }
49659b94acceSBarry Smith 
49669b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
49679b94acceSBarry Smith 
4968cc4c1da9SBarry Smith /*@
49690b4b7b1cSBarry Smith   SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES`
49709b94acceSBarry Smith 
4971c3339decSBarry Smith   Collective
4972fee21e36SBarry Smith 
4973c7afd0dbSLois Curfman McInnes   Input Parameters:
4974f6dfbefdSBarry Smith + snes - the `SNES` context
4975454a90a3SBarry Smith - type - a known method
4976c7afd0dbSLois Curfman McInnes 
4977c7afd0dbSLois Curfman McInnes   Options Database Key:
4978454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
497904d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4980ae12b187SLois Curfman McInnes 
4981dc4c0fb0SBarry Smith   Level: intermediate
4982dc4c0fb0SBarry Smith 
49839b94acceSBarry Smith   Notes:
49840b4b7b1cSBarry Smith   See `SNESType` for available methods (for instance)
4985f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4986c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49874a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4988c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49899b94acceSBarry Smith 
4990f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4991f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4992ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4993ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4994f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4995ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4996ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4997ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4998ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4999b0a32e0cSBarry Smith   appropriate method.
500036851e7fSLois Curfman McInnes 
5001420bcc1bSBarry Smith   Developer Note:
5002f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
5003f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
50048f6c3df8SBarry Smith 
50051cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
50069b94acceSBarry Smith @*/
5007d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
5008d71ae5a4SJacob Faibussowitsch {
5009ace3abfcSBarry Smith   PetscBool match;
50105f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
50113a40ed3dSBarry Smith 
50123a40ed3dSBarry Smith   PetscFunctionBegin;
50130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50144f572ea9SToby Isaac   PetscAssertPointer(type, 2);
501582bf6240SBarry Smith 
50169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
50173ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
501892ff6ae8SBarry Smith 
50199566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
50206adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
502175396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
5022dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
502343547594SStefano Zampini   /* Reinitialize type-specific function pointers in SNESOps structure */
502443547594SStefano Zampini   snes->ops->reset          = NULL;
50259e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
50269e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
50279e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
50289e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
50299e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
50307fe760d5SStefano Zampini 
50317fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
50329566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
50337fe760d5SStefano Zampini 
503475396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
503575396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
5036f5af7f23SKarl Rupp 
50379566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
50389566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
50393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50409b94acceSBarry Smith }
50419b94acceSBarry Smith 
5042cc4c1da9SBarry Smith /*@
5043f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
50449b94acceSBarry Smith 
5045c7afd0dbSLois Curfman McInnes   Not Collective
5046c7afd0dbSLois Curfman McInnes 
50479b94acceSBarry Smith   Input Parameter:
50484b0e389bSBarry Smith . snes - nonlinear solver context
50499b94acceSBarry Smith 
50509b94acceSBarry Smith   Output Parameter:
5051f6dfbefdSBarry Smith . type - `SNES` method (a character string)
50529b94acceSBarry Smith 
505336851e7fSLois Curfman McInnes   Level: intermediate
505436851e7fSLois Curfman McInnes 
50551cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
50569b94acceSBarry Smith @*/
5057d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
5058d71ae5a4SJacob Faibussowitsch {
50593a40ed3dSBarry Smith   PetscFunctionBegin;
50600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50614f572ea9SToby Isaac   PetscAssertPointer(type, 2);
50627adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
50633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50649b94acceSBarry Smith }
50659b94acceSBarry Smith 
50663cd8a7caSMatthew G. Knepley /*@
5067f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
50683cd8a7caSMatthew G. Knepley 
5069c3339decSBarry Smith   Logically Collective
50703cd8a7caSMatthew G. Knepley 
50713cd8a7caSMatthew G. Knepley   Input Parameters:
5072f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
50733cd8a7caSMatthew G. Knepley - u    - the solution vector
50743cd8a7caSMatthew G. Knepley 
50753cd8a7caSMatthew G. Knepley   Level: beginner
50763cd8a7caSMatthew G. Knepley 
50771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
50783cd8a7caSMatthew G. Knepley @*/
5079d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
5080d71ae5a4SJacob Faibussowitsch {
50813cd8a7caSMatthew G. Knepley   DM dm;
50823cd8a7caSMatthew G. Knepley 
50833cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
50843cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50853cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
50869566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
50879566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
50883cd8a7caSMatthew G. Knepley 
50893cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
50903cd8a7caSMatthew G. Knepley 
50919566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50929566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
50933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50943cd8a7caSMatthew G. Knepley }
50953cd8a7caSMatthew G. Knepley 
509652baeb72SSatish Balay /*@
50979b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
5098f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
50999b94acceSBarry Smith 
5100420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5101c7afd0dbSLois Curfman McInnes 
51029b94acceSBarry Smith   Input Parameter:
5103f6dfbefdSBarry Smith . snes - the `SNES` context
51049b94acceSBarry Smith 
51059b94acceSBarry Smith   Output Parameter:
51069b94acceSBarry Smith . x - the solution
51079b94acceSBarry Smith 
510870e92668SMatthew Knepley   Level: intermediate
510936851e7fSLois Curfman McInnes 
51101cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
51119b94acceSBarry Smith @*/
5112d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
5113d71ae5a4SJacob Faibussowitsch {
51143a40ed3dSBarry Smith   PetscFunctionBegin;
51150700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51164f572ea9SToby Isaac   PetscAssertPointer(x, 2);
511785385478SLisandro Dalcin   *x = snes->vec_sol;
51183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
511970e92668SMatthew Knepley }
512070e92668SMatthew Knepley 
512152baeb72SSatish Balay /*@
51229b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
51239b94acceSBarry Smith   stored.
51249b94acceSBarry Smith 
5125420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5126c7afd0dbSLois Curfman McInnes 
51279b94acceSBarry Smith   Input Parameter:
5128f6dfbefdSBarry Smith . snes - the `SNES` context
51299b94acceSBarry Smith 
51309b94acceSBarry Smith   Output Parameter:
51319b94acceSBarry Smith . x - the solution update
51329b94acceSBarry Smith 
513336851e7fSLois Curfman McInnes   Level: advanced
513436851e7fSLois Curfman McInnes 
51351cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
51369b94acceSBarry Smith @*/
5137d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
5138d71ae5a4SJacob Faibussowitsch {
51393a40ed3dSBarry Smith   PetscFunctionBegin;
51400700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51414f572ea9SToby Isaac   PetscAssertPointer(x, 2);
514285385478SLisandro Dalcin   *x = snes->vec_sol_update;
51433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51449b94acceSBarry Smith }
51459b94acceSBarry Smith 
51469b94acceSBarry Smith /*@C
5147f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
51489b94acceSBarry Smith 
5149420bcc1bSBarry Smith   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
5150c7afd0dbSLois Curfman McInnes 
51519b94acceSBarry Smith   Input Parameter:
5152f6dfbefdSBarry Smith . snes - the `SNES` context
51539b94acceSBarry Smith 
5154d8d19677SJose E. Roman   Output Parameters:
5155dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
51568434afd1SBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
5157dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
51589b94acceSBarry Smith 
515936851e7fSLois Curfman McInnes   Level: advanced
516036851e7fSLois Curfman McInnes 
5161f6dfbefdSBarry Smith   Note:
5162dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
516304edfde5SBarry Smith 
51648434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
51659b94acceSBarry Smith @*/
51668434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
5167d71ae5a4SJacob Faibussowitsch {
51686cab3a1bSJed Brown   DM dm;
5169a63bb30eSJed Brown 
51703a40ed3dSBarry Smith   PetscFunctionBegin;
51710700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5172a63bb30eSJed Brown   if (r) {
5173a63bb30eSJed Brown     if (!snes->vec_func) {
5174a63bb30eSJed Brown       if (snes->vec_rhs) {
51759566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5176a63bb30eSJed Brown       } else if (snes->vec_sol) {
51779566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5178a63bb30eSJed Brown       } else if (snes->dm) {
51799566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5180a63bb30eSJed Brown       }
5181a63bb30eSJed Brown     }
5182a63bb30eSJed Brown     *r = snes->vec_func;
5183a63bb30eSJed Brown   }
51849566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51859566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
51863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51879b94acceSBarry Smith }
51889b94acceSBarry Smith 
5189c79ef259SPeter Brune /*@C
519037fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5191c79ef259SPeter Brune 
5192c79ef259SPeter Brune   Input Parameter:
5193f6dfbefdSBarry Smith . snes - the `SNES` context
5194c79ef259SPeter Brune 
5195d8d19677SJose E. Roman   Output Parameters:
51968434afd1SBarry Smith + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5197dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
5198c79ef259SPeter Brune 
5199c79ef259SPeter Brune   Level: advanced
5200c79ef259SPeter Brune 
52018434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5202c79ef259SPeter Brune @*/
52038434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5204d71ae5a4SJacob Faibussowitsch {
52056cab3a1bSJed Brown   DM dm;
52066cab3a1bSJed Brown 
5207646217ecSPeter Brune   PetscFunctionBegin;
5208646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52099566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
52109566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
52113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5212646217ecSPeter Brune }
5213646217ecSPeter Brune 
5214cc4c1da9SBarry Smith /*@
52153c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5216f6dfbefdSBarry Smith   `SNES` options in the database.
52173c7409f5SSatish Balay 
5218c3339decSBarry Smith   Logically Collective
5219fee21e36SBarry Smith 
5220d8d19677SJose E. Roman   Input Parameters:
5221f6dfbefdSBarry Smith + snes   - the `SNES` context
5222c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5223c7afd0dbSLois Curfman McInnes 
5224dc4c0fb0SBarry Smith   Level: advanced
5225dc4c0fb0SBarry Smith 
5226f6dfbefdSBarry Smith   Note:
5227a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5228c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5229d850072dSLois Curfman McInnes 
52301cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
52313c7409f5SSatish Balay @*/
5232d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5233d71ae5a4SJacob Faibussowitsch {
52343a40ed3dSBarry Smith   PetscFunctionBegin;
52350700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52369566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
52379566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
523835f5d045SPeter Brune   if (snes->linesearch) {
52399566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
52409566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
524135f5d045SPeter Brune   }
52429566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
52433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52443c7409f5SSatish Balay }
52453c7409f5SSatish Balay 
5246cc4c1da9SBarry Smith /*@
5247f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5248f6dfbefdSBarry Smith   `SNES` options in the database.
52493c7409f5SSatish Balay 
5250c3339decSBarry Smith   Logically Collective
5251fee21e36SBarry Smith 
5252c7afd0dbSLois Curfman McInnes   Input Parameters:
5253f6dfbefdSBarry Smith + snes   - the `SNES` context
5254c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5255c7afd0dbSLois Curfman McInnes 
5256dc4c0fb0SBarry Smith   Level: advanced
5257dc4c0fb0SBarry Smith 
5258f6dfbefdSBarry Smith   Note:
5259a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5260c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5261d850072dSLois Curfman McInnes 
52621cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
52633c7409f5SSatish Balay @*/
5264d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5265d71ae5a4SJacob Faibussowitsch {
52663a40ed3dSBarry Smith   PetscFunctionBegin;
52670700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52689566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
52699566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
527035f5d045SPeter Brune   if (snes->linesearch) {
52719566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
52729566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
527335f5d045SPeter Brune   }
52749566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
52753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52763c7409f5SSatish Balay }
52773c7409f5SSatish Balay 
5278cc4c1da9SBarry Smith /*@
5279f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5280f6dfbefdSBarry Smith   `SNES` options in the database.
52813c7409f5SSatish Balay 
5282c7afd0dbSLois Curfman McInnes   Not Collective
5283c7afd0dbSLois Curfman McInnes 
52843c7409f5SSatish Balay   Input Parameter:
5285f6dfbefdSBarry Smith . snes - the `SNES` context
52863c7409f5SSatish Balay 
52873c7409f5SSatish Balay   Output Parameter:
52883c7409f5SSatish Balay . prefix - pointer to the prefix string used
52893c7409f5SSatish Balay 
529036851e7fSLois Curfman McInnes   Level: advanced
529136851e7fSLois Curfman McInnes 
52921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
52933c7409f5SSatish Balay @*/
5294d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5295d71ae5a4SJacob Faibussowitsch {
52963a40ed3dSBarry Smith   PetscFunctionBegin;
52970700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52989566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
52993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53003c7409f5SSatish Balay }
53013c7409f5SSatish Balay 
53023cea93caSBarry Smith /*@C
53031c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
53041c84c290SBarry Smith 
530520f4b53cSBarry Smith   Not Collective
53061c84c290SBarry Smith 
53071c84c290SBarry Smith   Input Parameters:
530820f4b53cSBarry Smith + sname    - name of a new user-defined solver
530920f4b53cSBarry Smith - function - routine to create method context
53101c84c290SBarry Smith 
5311dc4c0fb0SBarry Smith   Level: advanced
5312dc4c0fb0SBarry Smith 
5313f6dfbefdSBarry Smith   Note:
5314f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
53151c84c290SBarry Smith 
5316e4094ef1SJacob Faibussowitsch   Example Usage:
53171c84c290SBarry Smith .vb
5318bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
53191c84c290SBarry Smith .ve
53201c84c290SBarry Smith 
53211c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
5322b44f4de4SBarry Smith .vb
5323b44f4de4SBarry Smith   SNESSetType(snes, "my_solver")
5324b44f4de4SBarry Smith .ve
53251c84c290SBarry Smith   or at runtime via the option
5326b44f4de4SBarry Smith .vb
5327b44f4de4SBarry Smith   -snes_type my_solver
5328b44f4de4SBarry Smith .ve
53291c84c290SBarry Smith 
53301cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
53313cea93caSBarry Smith @*/
5332d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5333d71ae5a4SJacob Faibussowitsch {
5334b2002411SLois Curfman McInnes   PetscFunctionBegin;
53359566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
53369566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
53373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5338b2002411SLois Curfman McInnes }
5339da9b6338SBarry Smith 
5340d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5341d71ae5a4SJacob Faibussowitsch {
534277431f27SBarry Smith   PetscInt    N, i, j;
5343da9b6338SBarry Smith   Vec         u, uh, fh;
5344da9b6338SBarry Smith   PetscScalar value;
5345da9b6338SBarry Smith   PetscReal   norm;
5346da9b6338SBarry Smith 
5347da9b6338SBarry Smith   PetscFunctionBegin;
53489566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
53499566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
53509566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5351da9b6338SBarry Smith 
5352da9b6338SBarry Smith   /* currently only works for sequential */
53539566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
53549566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5355da9b6338SBarry Smith   for (i = 0; i < N; i++) {
53569566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
535763a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5358da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
53598b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
53609566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
53619566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
5362*76c63389SBarry Smith       PetscCall(VecNorm(fh, NORM_2, &norm)); /* does not handle use of SNESSetFunctionDomainError() correctly */
536363a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5364da9b6338SBarry Smith       value = -value;
53659566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5366da9b6338SBarry Smith     }
5367da9b6338SBarry Smith   }
53689566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
53699566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
53703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5371da9b6338SBarry Smith }
537271f87433Sdalcinl 
537371f87433Sdalcinl /*@
5374*76c63389SBarry Smith   SNESGetLineSearch - Returns the line search associated with the `SNES`.
5375*76c63389SBarry Smith 
5376*76c63389SBarry Smith   Not Collective
5377*76c63389SBarry Smith 
5378*76c63389SBarry Smith   Input Parameter:
5379*76c63389SBarry Smith . snes - iterative context obtained from `SNESCreate()`
5380*76c63389SBarry Smith 
5381*76c63389SBarry Smith   Output Parameter:
5382*76c63389SBarry Smith . linesearch - linesearch context
5383*76c63389SBarry Smith 
5384*76c63389SBarry Smith   Level: beginner
5385*76c63389SBarry Smith 
5386*76c63389SBarry Smith   Notes:
5387*76c63389SBarry Smith   It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`.
5388*76c63389SBarry Smith 
5389*76c63389SBarry Smith   You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options.
5390*76c63389SBarry Smith 
5391*76c63389SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`
5392*76c63389SBarry Smith @*/
5393*76c63389SBarry Smith PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5394*76c63389SBarry Smith {
5395*76c63389SBarry Smith   const char *optionsprefix;
5396*76c63389SBarry Smith 
5397*76c63389SBarry Smith   PetscFunctionBegin;
5398*76c63389SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5399*76c63389SBarry Smith   PetscAssertPointer(linesearch, 2);
5400*76c63389SBarry Smith   if (!snes->linesearch) {
5401*76c63389SBarry Smith     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
5402*76c63389SBarry Smith     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
5403*76c63389SBarry Smith     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
5404*76c63389SBarry Smith     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
5405*76c63389SBarry Smith     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
5406*76c63389SBarry Smith   }
5407*76c63389SBarry Smith   *linesearch = snes->linesearch;
5408*76c63389SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
5409*76c63389SBarry Smith }
5410*76c63389SBarry Smith 
5411*76c63389SBarry Smith /*@
5412f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
541371f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
541471f87433Sdalcinl   Newton method.
541571f87433Sdalcinl 
5416c3339decSBarry Smith   Logically Collective
541771f87433Sdalcinl 
541871f87433Sdalcinl   Input Parameters:
5419f6dfbefdSBarry Smith + snes - `SNES` context
5420f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
542171f87433Sdalcinl 
5422f6dfbefdSBarry Smith   Options Database Keys:
542364ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
542464ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
542564ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
542664ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
542764ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
542864ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
542964ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
543064ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
543164ba62caSBarry Smith 
5432dc4c0fb0SBarry Smith   Level: advanced
5433dc4c0fb0SBarry Smith 
5434f6dfbefdSBarry Smith   Note:
5435f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
543671f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
54371d27aa22SBarry Smith   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
543871f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
543971f87433Sdalcinl   solver.
544071f87433Sdalcinl 
54411cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
544271f87433Sdalcinl @*/
5443d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5444d71ae5a4SJacob Faibussowitsch {
544571f87433Sdalcinl   PetscFunctionBegin;
54460700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5447acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
544871f87433Sdalcinl   snes->ksp_ewconv = flag;
54493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
545071f87433Sdalcinl }
545171f87433Sdalcinl 
545271f87433Sdalcinl /*@
5453f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
545471f87433Sdalcinl   for computing relative tolerance for linear solvers within an
545571f87433Sdalcinl   inexact Newton method.
545671f87433Sdalcinl 
545771f87433Sdalcinl   Not Collective
545871f87433Sdalcinl 
545971f87433Sdalcinl   Input Parameter:
5460f6dfbefdSBarry Smith . snes - `SNES` context
546171f87433Sdalcinl 
546271f87433Sdalcinl   Output Parameter:
5463f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
546471f87433Sdalcinl 
546571f87433Sdalcinl   Level: advanced
546671f87433Sdalcinl 
54671cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
546871f87433Sdalcinl @*/
5469d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5470d71ae5a4SJacob Faibussowitsch {
547171f87433Sdalcinl   PetscFunctionBegin;
54720700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54734f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
547471f87433Sdalcinl   *flag = snes->ksp_ewconv;
54753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
547671f87433Sdalcinl }
547771f87433Sdalcinl 
547871f87433Sdalcinl /*@
5479fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
548071f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
548171f87433Sdalcinl   Newton method.
548271f87433Sdalcinl 
5483c3339decSBarry Smith   Logically Collective
548471f87433Sdalcinl 
548571f87433Sdalcinl   Input Parameters:
5486f6dfbefdSBarry Smith + snes      - `SNES` context
54870f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
548871f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
548971f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
549071f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
549171f87433Sdalcinl              (0 <= gamma2 <= 1)
549271f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
549371f87433Sdalcinl . alpha2    - power for safeguard
549471f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
549571f87433Sdalcinl 
5496dc4c0fb0SBarry Smith   Level: advanced
5497dc4c0fb0SBarry Smith 
5498f6dfbefdSBarry Smith   Notes:
549971f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
550071f87433Sdalcinl 
550177e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the default for any of the parameters.
550271f87433Sdalcinl 
55031cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
550471f87433Sdalcinl @*/
5505d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5506d71ae5a4SJacob Faibussowitsch {
5507fa9f3622SBarry Smith   SNESKSPEW *kctx;
55085fd66863SKarl Rupp 
550971f87433Sdalcinl   PetscFunctionBegin;
55100700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5511fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
55125f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5513c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5514c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5515c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5516c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5517c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5518c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5519c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
552071f87433Sdalcinl 
552177e5a1f9SBarry Smith   if (version != PETSC_CURRENT) kctx->version = version;
552277e5a1f9SBarry Smith   if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0;
552377e5a1f9SBarry Smith   if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max;
552477e5a1f9SBarry Smith   if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma;
552577e5a1f9SBarry Smith   if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha;
552677e5a1f9SBarry Smith   if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2;
552777e5a1f9SBarry Smith   if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold;
552871f87433Sdalcinl 
55290f0abf79SStefano Zampini   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);
55300b121fc5SBarry Smith   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);
55310b121fc5SBarry Smith   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);
55320b121fc5SBarry Smith   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);
55330b121fc5SBarry Smith   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);
55340b121fc5SBarry Smith   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);
55353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
553671f87433Sdalcinl }
553771f87433Sdalcinl 
553871f87433Sdalcinl /*@
5539fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
554071f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
554171f87433Sdalcinl   Newton method.
554271f87433Sdalcinl 
554371f87433Sdalcinl   Not Collective
554471f87433Sdalcinl 
554597bb3fdcSJose E. Roman   Input Parameter:
5546f6dfbefdSBarry Smith . snes - `SNES` context
554771f87433Sdalcinl 
554871f87433Sdalcinl   Output Parameters:
55490f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
555071f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
555171f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5552bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
555371f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
555471f87433Sdalcinl . alpha2    - power for safeguard
555571f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
555671f87433Sdalcinl 
555771f87433Sdalcinl   Level: advanced
555871f87433Sdalcinl 
55591cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
556071f87433Sdalcinl @*/
5561d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5562d71ae5a4SJacob Faibussowitsch {
5563fa9f3622SBarry Smith   SNESKSPEW *kctx;
55645fd66863SKarl Rupp 
556571f87433Sdalcinl   PetscFunctionBegin;
55660700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5567fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
55685f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
556971f87433Sdalcinl   if (version) *version = kctx->version;
557071f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
557171f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
557271f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
557371f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
557471f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
557571f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
55763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
557771f87433Sdalcinl }
557871f87433Sdalcinl 
55795c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5580d71ae5a4SJacob Faibussowitsch {
55815c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5582fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
558377e5a1f9SBarry Smith   PetscReal  rtol = PETSC_CURRENT, stol;
558471f87433Sdalcinl 
558571f87433Sdalcinl   PetscFunctionBegin;
55863ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
558730058271SDmitry Karpeev   if (!snes->iter) {
558830058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
55899566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
55900f0abf79SStefano Zampini   } else {
55910fdf79fbSJacob Faibussowitsch     PetscCheck(kctx->version >= 1 && kctx->version <= 4, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only versions 1-4 are supported: %" PetscInt_FMT, kctx->version);
559271f87433Sdalcinl     if (kctx->version == 1) {
55930f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
559485ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
559571f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
559671f87433Sdalcinl     } else if (kctx->version == 2) {
559785ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
559885ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
559971f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
560071f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
560185ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
560271f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
560385ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
560471f87433Sdalcinl       stol = PetscMax(rtol, stol);
560571f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
560671f87433Sdalcinl       /* safeguard: avoid oversolving */
560730058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
560871f87433Sdalcinl       stol = PetscMax(rtol, stol);
560971f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
56100fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
56110fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
56120f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
56130f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
56140f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
56150f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
56160f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
56170f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
56180f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
56190f0abf79SStefano Zampini 
5620a4598233SStefano Zampini       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;
56210f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
56220f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
56230f0abf79SStefano Zampini       kctx->rk_last     = rk;
56240fdf79fbSJacob Faibussowitsch     }
56250f0abf79SStefano Zampini   }
56260f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
562771f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
562877e5a1f9SBarry Smith   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT));
562963a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
56303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
563171f87433Sdalcinl }
563271f87433Sdalcinl 
56335c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5634d71ae5a4SJacob Faibussowitsch {
56355c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5636fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
563771f87433Sdalcinl   PCSide     pcside;
563871f87433Sdalcinl   Vec        lres;
563971f87433Sdalcinl 
564071f87433Sdalcinl   PetscFunctionBegin;
56413ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
56429566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
564371dbe336SPeter Brune   kctx->norm_last = snes->norm;
56440f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
56454f00ce20SMatthew G. Knepley     PC        pc;
56460f0abf79SStefano Zampini     PetscBool getRes;
56474f00ce20SMatthew G. Knepley 
56489566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
56490f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
56500f0abf79SStefano Zampini     if (!getRes) {
56510f0abf79SStefano Zampini       KSPNormType normtype;
56520f0abf79SStefano Zampini 
56530f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
56540f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
56550f0abf79SStefano Zampini     }
56569566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
56570f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
56589566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
565971f87433Sdalcinl     } else {
566071f87433Sdalcinl       /* KSP residual is preconditioned residual */
566171f87433Sdalcinl       /* compute true linear residual norm */
56620f0abf79SStefano Zampini       Mat J;
56630f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
56649566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
56650f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
56669566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
56679566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
56689566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
566971f87433Sdalcinl     }
567071f87433Sdalcinl   }
56713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
567271f87433Sdalcinl }
567371f87433Sdalcinl 
5674d4211eb9SBarry Smith /*@
5675f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5676d4211eb9SBarry Smith 
5677420bcc1bSBarry Smith   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5678d4211eb9SBarry Smith 
5679d4211eb9SBarry Smith   Input Parameter:
5680f6dfbefdSBarry Smith . snes - the `SNES` context
5681d4211eb9SBarry Smith 
5682d4211eb9SBarry Smith   Output Parameter:
5683f6dfbefdSBarry Smith . ksp - the `KSP` context
5684d4211eb9SBarry Smith 
5685dc4c0fb0SBarry Smith   Level: beginner
5686dc4c0fb0SBarry Smith 
5687d4211eb9SBarry Smith   Notes:
5688f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5689d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5690f6dfbefdSBarry Smith   `PC` contexts as well.
5691f6dfbefdSBarry Smith 
56920b4b7b1cSBarry Smith   Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function, changes to that `KSP` will have no effect.
5693d4211eb9SBarry Smith 
56941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5695d4211eb9SBarry Smith @*/
5696d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5697d71ae5a4SJacob Faibussowitsch {
569871f87433Sdalcinl   PetscFunctionBegin;
5699d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57004f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5701d4211eb9SBarry Smith 
5702d4211eb9SBarry Smith   if (!snes->ksp) {
57039566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
57049566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5705d4211eb9SBarry Smith 
57065c0db29aSPierre Jolivet     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
57075c0db29aSPierre Jolivet     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5708a5c2985bSBarry Smith 
57099566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
57109566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5711d4211eb9SBarry Smith   }
5712d4211eb9SBarry Smith   *ksp = snes->ksp;
57133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
571471f87433Sdalcinl }
57156c699258SBarry Smith 
5716af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
57176c699258SBarry Smith /*@
57180b4b7b1cSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners
57196c699258SBarry Smith 
5720c3339decSBarry Smith   Logically Collective
57216c699258SBarry Smith 
57226c699258SBarry Smith   Input Parameters:
57232a808120SBarry Smith + snes - the nonlinear solver context
5724420bcc1bSBarry Smith - dm   - the `DM`, cannot be `NULL`
5725dc4c0fb0SBarry Smith 
5726dc4c0fb0SBarry Smith   Level: intermediate
57276c699258SBarry Smith 
5728f6dfbefdSBarry Smith   Note:
5729f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5730f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5731e03a659cSJed Brown   problems using the same function space.
5732e03a659cSJed Brown 
5733420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
57346c699258SBarry Smith @*/
5735d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5736d71ae5a4SJacob Faibussowitsch {
5737345fed2cSBarry Smith   KSP    ksp;
5738942e3340SBarry Smith   DMSNES sdm;
57396c699258SBarry Smith 
57406c699258SBarry Smith   PetscFunctionBegin;
57410700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57422a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
57439566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5744942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
574551f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
57469566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
57479566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5748f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
57496cab3a1bSJed Brown     }
57509566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
57519566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
57526cab3a1bSJed Brown   }
57536c699258SBarry Smith   snes->dm     = dm;
5754116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5755f5af7f23SKarl Rupp 
57569566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
57579566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
57589566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5759efd4aadfSBarry Smith   if (snes->npc) {
57609566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
57619566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
57622c155ee1SBarry Smith   }
57633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57646c699258SBarry Smith }
57656c699258SBarry Smith 
57666c699258SBarry Smith /*@
57670b4b7b1cSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners
57686c699258SBarry Smith 
57690b4b7b1cSBarry Smith   Not Collective but `dm` obtained is parallel on `snes`
57706c699258SBarry Smith 
57716c699258SBarry Smith   Input Parameter:
5772420bcc1bSBarry Smith . snes - the `SNES` context
57736c699258SBarry Smith 
57746c699258SBarry Smith   Output Parameter:
5775420bcc1bSBarry Smith . dm - the `DM`
57766c699258SBarry Smith 
57776c699258SBarry Smith   Level: intermediate
57786c699258SBarry Smith 
5779420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
57806c699258SBarry Smith @*/
5781d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5782d71ae5a4SJacob Faibussowitsch {
57836c699258SBarry Smith   PetscFunctionBegin;
57840700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57856cab3a1bSJed Brown   if (!snes->dm) {
57869566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5787116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
57886cab3a1bSJed Brown   }
57896c699258SBarry Smith   *dm = snes->dm;
57903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57916c699258SBarry Smith }
57920807856dSBarry Smith 
579331823bd8SMatthew G Knepley /*@
5794be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
579531823bd8SMatthew G Knepley 
5796c3339decSBarry Smith   Collective
579731823bd8SMatthew G Knepley 
579831823bd8SMatthew G Knepley   Input Parameters:
5799f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
580062842358SBarry Smith - npc  - the `SNES` nonlinear preconditioner object
580162842358SBarry Smith 
580262842358SBarry Smith   Options Database Key:
580362842358SBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
580431823bd8SMatthew G Knepley 
5805dc4c0fb0SBarry Smith   Level: developer
5806dc4c0fb0SBarry Smith 
580731823bd8SMatthew G Knepley   Notes:
580862842358SBarry Smith   This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API.
580931823bd8SMatthew G Knepley 
5810f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5811f6dfbefdSBarry Smith 
5812420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
581331823bd8SMatthew G Knepley @*/
5814d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5815d71ae5a4SJacob Faibussowitsch {
581631823bd8SMatthew G Knepley   PetscFunctionBegin;
581731823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5818f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5819f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5820f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
58219566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5822f6dfbefdSBarry Smith   snes->npc = npc;
58233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
582431823bd8SMatthew G Knepley }
582531823bd8SMatthew G Knepley 
582631823bd8SMatthew G Knepley /*@
5827f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
582831823bd8SMatthew G Knepley 
58290b4b7b1cSBarry Smith   Not Collective; but any changes to the obtained the `pc` object must be applied collectively
583031823bd8SMatthew G Knepley 
583131823bd8SMatthew G Knepley   Input Parameter:
5832f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
583331823bd8SMatthew G Knepley 
583431823bd8SMatthew G Knepley   Output Parameter:
583562842358SBarry Smith . pc - the `SNES` preconditioner context
583631823bd8SMatthew G Knepley 
5837f6dfbefdSBarry Smith   Options Database Key:
5838f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5839b5badacbSBarry Smith 
58400b4b7b1cSBarry Smith   Level: advanced
5841dc4c0fb0SBarry Smith 
584295452b02SPatrick Sanan   Notes:
58430b4b7b1cSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will
58440b4b7b1cSBarry Smith   be used as the nonlinear preconditioner for the current `SNES`.
5845be95d8f1SBarry Smith 
5846f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
584762842358SBarry Smith   `SNES`. These may be overwritten if needed.
584862842358SBarry Smith 
584962842358SBarry Smith   Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner
5850951fe5abSBarry Smith 
58511cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
585231823bd8SMatthew G Knepley @*/
5853d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5854d71ae5a4SJacob Faibussowitsch {
5855a64e098fSPeter Brune   const char *optionsprefix;
585631823bd8SMatthew G Knepley 
585731823bd8SMatthew G Knepley   PetscFunctionBegin;
585831823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58594f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5860efd4aadfSBarry Smith   if (!snes->npc) {
5861ec785e5bSStefano Zampini     void *ctx;
5862ec785e5bSStefano Zampini 
58639566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
58649566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
58659566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
58669566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
58679566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5868fb87a551SStefano Zampini     if (snes->ops->usercompute) {
586949abdd8aSBarry Smith       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy));
5870fb87a551SStefano Zampini     } else {
5871ec785e5bSStefano Zampini       PetscCall(SNESGetApplicationContext(snes, &ctx));
5872ec785e5bSStefano Zampini       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5873fb87a551SStefano Zampini     }
58749566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
587531823bd8SMatthew G Knepley   }
5876efd4aadfSBarry Smith   *pc = snes->npc;
58773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
587831823bd8SMatthew G Knepley }
587931823bd8SMatthew G Knepley 
58803ad1a0b9SPatrick Farrell /*@
58810b4b7b1cSBarry Smith   SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES`
58823ad1a0b9SPatrick Farrell 
58833ad1a0b9SPatrick Farrell   Not Collective
58843ad1a0b9SPatrick Farrell 
58853ad1a0b9SPatrick Farrell   Input Parameter:
5886f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
58873ad1a0b9SPatrick Farrell 
58883ad1a0b9SPatrick Farrell   Output Parameter:
5889420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
58903ad1a0b9SPatrick Farrell 
58913ad1a0b9SPatrick Farrell   Level: developer
58923ad1a0b9SPatrick Farrell 
58931cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
58943ad1a0b9SPatrick Farrell @*/
5895d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5896d71ae5a4SJacob Faibussowitsch {
58973ad1a0b9SPatrick Farrell   PetscFunctionBegin;
58983ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5899835f2295SStefano Zampini   PetscAssertPointer(has_npc, 2);
5900835f2295SStefano Zampini   *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE;
59013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59023ad1a0b9SPatrick Farrell }
59033ad1a0b9SPatrick Farrell 
5904c40d0f55SPeter Brune /*@
590562842358SBarry Smith   SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`.
5906c40d0f55SPeter Brune 
5907c3339decSBarry Smith   Logically Collective
5908c40d0f55SPeter Brune 
5909c40d0f55SPeter Brune   Input Parameter:
5910f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5911c40d0f55SPeter Brune 
5912c40d0f55SPeter Brune   Output Parameter:
5913c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5914c40d0f55SPeter Brune .vb
59152d547940SBarry Smith       PC_LEFT  - left preconditioning
59162d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5917c40d0f55SPeter Brune .ve
5918c40d0f55SPeter Brune 
5919f6dfbefdSBarry Smith   Options Database Key:
592067b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5921c40d0f55SPeter Brune 
5922dc4c0fb0SBarry Smith   Level: intermediate
5923dc4c0fb0SBarry Smith 
5924f6dfbefdSBarry Smith   Note:
5925f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
59262d547940SBarry Smith 
592762842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5928c40d0f55SPeter Brune @*/
5929d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5930d71ae5a4SJacob Faibussowitsch {
5931c40d0f55SPeter Brune   PetscFunctionBegin;
5932c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5933c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5934b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
593554c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5936efd4aadfSBarry Smith   snes->npcside = side;
59373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5938c40d0f55SPeter Brune }
5939c40d0f55SPeter Brune 
5940c40d0f55SPeter Brune /*@
594162842358SBarry Smith   SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`.
5942c40d0f55SPeter Brune 
5943c40d0f55SPeter Brune   Not Collective
5944c40d0f55SPeter Brune 
5945c40d0f55SPeter Brune   Input Parameter:
5946f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5947c40d0f55SPeter Brune 
5948c40d0f55SPeter Brune   Output Parameter:
5949c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5950c40d0f55SPeter Brune .vb
5951f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5952f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5953c40d0f55SPeter Brune .ve
5954c40d0f55SPeter Brune 
5955c40d0f55SPeter Brune   Level: intermediate
5956c40d0f55SPeter Brune 
595762842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5958c40d0f55SPeter Brune @*/
5959d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5960d71ae5a4SJacob Faibussowitsch {
5961c40d0f55SPeter Brune   PetscFunctionBegin;
5962c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
59634f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5964efd4aadfSBarry Smith   *side = snes->npcside;
59653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5966c40d0f55SPeter Brune }
5967c40d0f55SPeter Brune 
59689e764e56SPeter Brune /*@
59690b4b7b1cSBarry Smith   SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES`
59709e764e56SPeter Brune 
5971c3339decSBarry Smith   Collective
59729e764e56SPeter Brune 
59739e764e56SPeter Brune   Input Parameters:
5974f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
59759e764e56SPeter Brune - linesearch - the linesearch object
59769e764e56SPeter Brune 
5977dc4c0fb0SBarry Smith   Level: developer
5978dc4c0fb0SBarry Smith 
5979f6dfbefdSBarry Smith   Note:
5980420bcc1bSBarry Smith   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
59819e764e56SPeter Brune   to configure it using the API).
59829e764e56SPeter Brune 
5983420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
59849e764e56SPeter Brune @*/
5985d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5986d71ae5a4SJacob Faibussowitsch {
59879e764e56SPeter Brune   PetscFunctionBegin;
59889e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5989f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
59909e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
59919566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
59929566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5993f5af7f23SKarl Rupp 
59949e764e56SPeter Brune   snes->linesearch = linesearch;
59953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59969e764e56SPeter Brune }
5997