xref: /petsc/src/snes/interface/snes.c (revision 6b1535e8f0d6001e577d602d70da3ce8111cf3aa)
1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h"  I*/
207475bc1SBarry Smith #include <petscdmshell.h>
3d96771aaSLisandro Dalcin #include <petscdraw.h>
4a01aa210SMatthew G. Knepley #include <petscds.h>
534b4d3a8SMatthew G. Knepley #include <petscdmadaptor.h>
606fc46c8SMatthew G. Knepley #include <petscconvest.h>
79b94acceSBarry Smith 
8ace3abfcSBarry Smith PetscBool         SNESRegisterAllCalled = PETSC_FALSE;
90298fd71SBarry Smith PetscFunctionList SNESList              = NULL;
108ba1e511SMatthew Knepley 
118ba1e511SMatthew Knepley /* Logging support */
1222c6f798SBarry Smith PetscClassId  SNES_CLASSID, DMSNES_CLASSID;
1397276fddSZach Atkins PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NewtonALEval, SNES_NPCSolve, SNES_ObjectiveEval;
14a09944afSBarry Smith 
15e113a28aSBarry Smith /*@
16dc4c0fb0SBarry Smith   SNESSetErrorIfNotConverged - Causes `SNESSolve()` to generate an error immediately if the solver has not converged.
17e113a28aSBarry Smith 
18c3339decSBarry Smith   Logically Collective
19e113a28aSBarry Smith 
20e113a28aSBarry Smith   Input Parameters:
21f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
22f6dfbefdSBarry Smith - flg  - `PETSC_TRUE` indicates you want the error generated
23e113a28aSBarry Smith 
2420f4b53cSBarry Smith   Options Database Key:
2567b8a455SSatish Balay . -snes_error_if_not_converged <true,false> - cause an immediate error condition and stop the program if the solver does not converge
26e113a28aSBarry Smith 
27e113a28aSBarry Smith   Level: intermediate
28e113a28aSBarry Smith 
29f6dfbefdSBarry Smith   Note:
30f6dfbefdSBarry Smith   Normally PETSc continues if a solver fails to converge, you can call `SNESGetConvergedReason()` after a `SNESSolve()`
31f6dfbefdSBarry Smith   to determine if it has converged. Otherwise the solution may be inaccurate or wrong
32e113a28aSBarry Smith 
331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()`
34e113a28aSBarry Smith @*/
35d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetErrorIfNotConverged(SNES snes, PetscBool flg)
36d71ae5a4SJacob Faibussowitsch {
37e113a28aSBarry Smith   PetscFunctionBegin;
38e113a28aSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
39acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flg, 2);
40e113a28aSBarry Smith   snes->errorifnotconverged = flg;
413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42e113a28aSBarry Smith }
43e113a28aSBarry Smith 
44e113a28aSBarry Smith /*@
45f6dfbefdSBarry Smith   SNESGetErrorIfNotConverged - Indicates if `SNESSolve()` will generate an error if the solver does not converge?
46e113a28aSBarry Smith 
47e113a28aSBarry Smith   Not Collective
48e113a28aSBarry Smith 
49e113a28aSBarry Smith   Input Parameter:
50f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
51e113a28aSBarry Smith 
52e113a28aSBarry Smith   Output Parameter:
53f6dfbefdSBarry Smith . flag - `PETSC_TRUE` if it will generate an error, else `PETSC_FALSE`
54e113a28aSBarry Smith 
55e113a28aSBarry Smith   Level: intermediate
56e113a28aSBarry Smith 
571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()`
58e113a28aSBarry Smith @*/
59d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetErrorIfNotConverged(SNES snes, PetscBool *flag)
60d71ae5a4SJacob Faibussowitsch {
61e113a28aSBarry Smith   PetscFunctionBegin;
62e113a28aSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
634f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
64e113a28aSBarry Smith   *flag = snes->errorifnotconverged;
653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66e113a28aSBarry Smith }
67e113a28aSBarry Smith 
684fc747eaSLawrence Mitchell /*@
69dc4c0fb0SBarry Smith   SNESSetAlwaysComputesFinalResidual - tells the `SNES` to always compute the residual (nonlinear function value) at the final solution
704fc747eaSLawrence Mitchell 
71c3339decSBarry Smith   Logically Collective
724fc747eaSLawrence Mitchell 
734fc747eaSLawrence Mitchell   Input Parameters:
74f6dfbefdSBarry Smith + snes - the shell `SNES`
75f6dfbefdSBarry Smith - flg  - `PETSC_TRUE` to always compute the residual
764fc747eaSLawrence Mitchell 
774fc747eaSLawrence Mitchell   Level: advanced
784fc747eaSLawrence Mitchell 
79f6dfbefdSBarry Smith   Note:
80f6dfbefdSBarry Smith   Some solvers (such as smoothers in a `SNESFAS`) do not need the residual computed at the final solution so skip computing it
81f6dfbefdSBarry Smith   to save time.
82f6dfbefdSBarry Smith 
83420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESGetAlwaysComputesFinalResidual()`
844fc747eaSLawrence Mitchell @*/
85d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetAlwaysComputesFinalResidual(SNES snes, PetscBool flg)
86d71ae5a4SJacob Faibussowitsch {
874fc747eaSLawrence Mitchell   PetscFunctionBegin;
884fc747eaSLawrence Mitchell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
894fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = flg;
903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
914fc747eaSLawrence Mitchell }
924fc747eaSLawrence Mitchell 
934fc747eaSLawrence Mitchell /*@
94f6dfbefdSBarry Smith   SNESGetAlwaysComputesFinalResidual - checks if the `SNES` always computes the residual at the final solution
954fc747eaSLawrence Mitchell 
96c3339decSBarry Smith   Logically Collective
974fc747eaSLawrence Mitchell 
984fc747eaSLawrence Mitchell   Input Parameter:
99f6dfbefdSBarry Smith . snes - the `SNES` context
1004fc747eaSLawrence Mitchell 
1014fc747eaSLawrence Mitchell   Output Parameter:
102f6dfbefdSBarry Smith . flg - `PETSC_TRUE` if the residual is computed
1034fc747eaSLawrence Mitchell 
1044fc747eaSLawrence Mitchell   Level: advanced
1054fc747eaSLawrence Mitchell 
106420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESSetAlwaysComputesFinalResidual()`
1074fc747eaSLawrence Mitchell @*/
108d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg)
109d71ae5a4SJacob Faibussowitsch {
1104fc747eaSLawrence Mitchell   PetscFunctionBegin;
1114fc747eaSLawrence Mitchell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1124fc747eaSLawrence Mitchell   *flg = snes->alwayscomputesfinalresidual;
1133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1144fc747eaSLawrence Mitchell }
1154fc747eaSLawrence Mitchell 
116e725d27bSBarry Smith /*@
117f6dfbefdSBarry Smith   SNESSetFunctionDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetFunction()` is not
118f0b84518SBarry Smith   in the functions domain. For example, a step with negative pressure.
1194936397dSBarry Smith 
120*6b1535e8SBarry Smith   Not Collective
1214936397dSBarry Smith 
1222fe279fdSBarry Smith   Input Parameter:
123f6dfbefdSBarry Smith . snes - the `SNES` context
1244936397dSBarry Smith 
12528529972SSatish Balay   Level: advanced
1264936397dSBarry Smith 
127ced0f3aeSBarry Smith   Notes:
128*6b1535e8SBarry Smith   This does not need to be called by all processes in the `SNES` MPI communicator.
129*6b1535e8SBarry Smith 
130ced0f3aeSBarry Smith   If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
131ced0f3aeSBarry Smith 
132ced0f3aeSBarry Smith   You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
133ced0f3aeSBarry Smith 
134f0b84518SBarry Smith   You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
135f0b84518SBarry Smith   `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
136f0b84518SBarry Smith 
137*6b1535e8SBarry Smith   You can call `SNESSetJacobianDomainError()` during a Jacobian computation to indicate the proposed solution is not in the domain.
138*6b1535e8SBarry Smith 
139*6b1535e8SBarry Smith   Developer Note:
140*6b1535e8SBarry Smith   This value is used by `SNESCheckFunctionNorm()` to determine if the `SNESConvergedReason` is set to `SNES_DIVERGED_FUNCTION_DOMAIN`
141*6b1535e8SBarry Smith 
1428434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`,
143*6b1535e8SBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`,
144*6b1535e8SBarry Smith           `SNES_DIVERGED_FUNCTION_DOMAIN`
1454936397dSBarry Smith @*/
146d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionDomainError(SNES snes)
147d71ae5a4SJacob Faibussowitsch {
1484936397dSBarry Smith   PetscFunctionBegin;
1490700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1505f80ce2aSJacob Faibussowitsch   PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates input vector is not in the function domain");
1514936397dSBarry Smith   snes->domainerror = PETSC_TRUE;
1523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1534936397dSBarry Smith }
1544936397dSBarry Smith 
1556a388c36SPeter Brune /*@
156f6dfbefdSBarry Smith   SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation.
15707b62357SFande Kong 
158c3339decSBarry Smith   Logically Collective
15907b62357SFande Kong 
1602fe279fdSBarry Smith   Input Parameter:
161f6dfbefdSBarry Smith . snes - the `SNES` context
16207b62357SFande Kong 
16307b62357SFande Kong   Level: advanced
16407b62357SFande Kong 
165ced0f3aeSBarry Smith   Notes:
166ced0f3aeSBarry Smith   If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
167ced0f3aeSBarry Smith 
168ced0f3aeSBarry Smith   You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
169ced0f3aeSBarry Smith 
170f0b84518SBarry Smith   You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
171f0b84518SBarry Smith   `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
172f0b84518SBarry Smith 
1738434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`,
174ced0f3aeSBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`
17507b62357SFande Kong @*/
176d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes)
177d71ae5a4SJacob Faibussowitsch {
17807b62357SFande Kong   PetscFunctionBegin;
17907b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1805f80ce2aSJacob Faibussowitsch   PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense");
18107b62357SFande Kong   snes->jacobiandomainerror = PETSC_TRUE;
1823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18307b62357SFande Kong }
18407b62357SFande Kong 
18507b62357SFande Kong /*@
186f6dfbefdSBarry Smith   SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` Jacobian domain error after
187420bcc1bSBarry Smith   each Jacobian evaluation. By default, it checks for the Jacobian domain error in the debug mode, and does not check it in the optimized mode.
188b351a90bSFande Kong 
189c3339decSBarry Smith   Logically Collective
190b351a90bSFande Kong 
191b351a90bSFande Kong   Input Parameters:
19220f4b53cSBarry Smith + snes - the `SNES` context
193f6dfbefdSBarry Smith - flg  - indicates if or not to check Jacobian domain error after each Jacobian evaluation
194b351a90bSFande Kong 
195b351a90bSFande Kong   Level: advanced
196b351a90bSFande Kong 
197f6dfbefdSBarry Smith   Note:
198f6dfbefdSBarry Smith   Checks require one extra parallel synchronization for each Jacobian evaluation
199f6dfbefdSBarry Smith 
2008434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()`
201b351a90bSFande Kong @*/
202d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg)
203d71ae5a4SJacob Faibussowitsch {
204b351a90bSFande Kong   PetscFunctionBegin;
205b351a90bSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
206b351a90bSFande Kong   snes->checkjacdomainerror = flg;
2073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
208b351a90bSFande Kong }
209b351a90bSFande Kong 
210b351a90bSFande Kong /*@
211420bcc1bSBarry Smith   SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation.
2128383d7d7SFande Kong 
213c3339decSBarry Smith   Logically Collective
2148383d7d7SFande Kong 
2152fe279fdSBarry Smith   Input Parameter:
216f6dfbefdSBarry Smith . snes - the `SNES` context
2178383d7d7SFande Kong 
2182fe279fdSBarry Smith   Output Parameter:
219420bcc1bSBarry Smith . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation
2208383d7d7SFande Kong 
2218383d7d7SFande Kong   Level: advanced
2228383d7d7SFande Kong 
2238434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()`
2248383d7d7SFande Kong @*/
225d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg)
226d71ae5a4SJacob Faibussowitsch {
2278383d7d7SFande Kong   PetscFunctionBegin;
2288383d7d7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2294f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
2308383d7d7SFande Kong   *flg = snes->checkjacdomainerror;
2313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2328383d7d7SFande Kong }
2338383d7d7SFande Kong 
2348383d7d7SFande Kong /*@
235420bcc1bSBarry Smith   SNESGetFunctionDomainError - Gets the status of the domain error after a call to `SNESComputeFunction()`
2366a388c36SPeter Brune 
237*6b1535e8SBarry Smith   Not Collective, different MPI processes may return different values
2386a388c36SPeter Brune 
2392fe279fdSBarry Smith   Input Parameter:
240f6dfbefdSBarry Smith . snes - the `SNES` context
2416a388c36SPeter Brune 
2422fe279fdSBarry Smith   Output Parameter:
243f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a domain error; `PETSC_FALSE` otherwise.
2446a388c36SPeter Brune 
245f6dfbefdSBarry Smith   Level: developer
2466a388c36SPeter Brune 
247*6b1535e8SBarry Smith   Notes:
248*6b1535e8SBarry Smith   The value will only be true on those MPI processes that called `SNESSetFunctionDomainError()`
249*6b1535e8SBarry Smith 
250*6b1535e8SBarry Smith   The value is reset to `PETSC_FALSE` when `SNESCheckFunctionNorm()` is called.
251*6b1535e8SBarry Smith 
2521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`
2536a388c36SPeter Brune @*/
254d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror)
255d71ae5a4SJacob Faibussowitsch {
2566a388c36SPeter Brune   PetscFunctionBegin;
2576a388c36SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2584f572ea9SToby Isaac   PetscAssertPointer(domainerror, 2);
2596a388c36SPeter Brune   *domainerror = snes->domainerror;
2603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2616a388c36SPeter Brune }
2626a388c36SPeter Brune 
26307b62357SFande Kong /*@
264420bcc1bSBarry Smith   SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()`
26507b62357SFande Kong 
266*6b1535e8SBarry Smith   Not Collective, different MPI processes may return different values
26707b62357SFande Kong 
2682fe279fdSBarry Smith   Input Parameter:
269f6dfbefdSBarry Smith . snes - the `SNES` context
27007b62357SFande Kong 
2712fe279fdSBarry Smith   Output Parameter:
272f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a Jacobian domain error; `PETSC_FALSE` otherwise.
27307b62357SFande Kong 
27407b62357SFande Kong   Level: advanced
27507b62357SFande Kong 
276*6b1535e8SBarry Smith   Notes:
277*6b1535e8SBarry Smith   The value will only be true on those MPI processes that called `SNESSetJacobianDomainError()`
278*6b1535e8SBarry Smith 
279*6b1535e8SBarry Smith   The value is reset to `PETSC_FALSE` when `SNESCheckJacobianDomainerror()` is called but only `SNESSetCheckJacobianDomainError()` was called
280*6b1535e8SBarry Smith 
2811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`, `SNESGetFunctionDomainError()`
28207b62357SFande Kong @*/
283d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror)
284d71ae5a4SJacob Faibussowitsch {
28507b62357SFande Kong   PetscFunctionBegin;
28607b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2874f572ea9SToby Isaac   PetscAssertPointer(domainerror, 2);
28807b62357SFande Kong   *domainerror = snes->jacobiandomainerror;
2893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29007b62357SFande Kong }
29107b62357SFande Kong 
292ffeef943SBarry Smith /*@
293f6dfbefdSBarry Smith   SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`.
29455849f57SBarry Smith 
295c3339decSBarry Smith   Collective
29655849f57SBarry Smith 
29755849f57SBarry Smith   Input Parameters:
298e4094ef1SJacob Faibussowitsch + snes   - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or
299f6dfbefdSBarry Smith            some related function before a call to `SNESLoad()`.
300f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
30155849f57SBarry Smith 
30255849f57SBarry Smith   Level: intermediate
30355849f57SBarry Smith 
304f6dfbefdSBarry Smith   Note:
305420bcc1bSBarry Smith   The `SNESType` is determined by the data in the file, any type set into the `SNES` before this call is ignored.
30655849f57SBarry Smith 
3071cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()`
30855849f57SBarry Smith @*/
309d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer)
310d71ae5a4SJacob Faibussowitsch {
31155849f57SBarry Smith   PetscBool isbinary;
312060da220SMatthew G. Knepley   PetscInt  classid;
31355849f57SBarry Smith   char      type[256];
31455849f57SBarry Smith   KSP       ksp;
3152d53ad75SBarry Smith   DM        dm;
3162d53ad75SBarry Smith   DMSNES    dmsnes;
31755849f57SBarry Smith 
31855849f57SBarry Smith   PetscFunctionBegin;
3192d53ad75SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
32055849f57SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
3225f80ce2aSJacob Faibussowitsch   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");
32355849f57SBarry Smith 
3249566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
3255f80ce2aSJacob Faibussowitsch   PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file");
3269566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
3279566063dSJacob Faibussowitsch   PetscCall(SNESSetType(snes, type));
328dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, load, viewer);
3299566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3309566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &dmsnes));
3319566063dSJacob Faibussowitsch   PetscCall(DMSNESLoad(dmsnes, viewer));
3329566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
3339566063dSJacob Faibussowitsch   PetscCall(KSPLoad(ksp, viewer));
3343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33555849f57SBarry Smith }
3366a388c36SPeter Brune 
3379804daf3SBarry Smith #include <petscdraw.h>
338e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
339e04113cfSBarry Smith   #include <petscviewersaws.h>
340bfb97211SBarry Smith #endif
3418404b7f3SBarry Smith 
342ffeef943SBarry Smith /*@
343dc4c0fb0SBarry Smith   SNESViewFromOptions - View a `SNES` based on values in the options database
344fe2efc57SMark 
345c3339decSBarry Smith   Collective
346fe2efc57SMark 
347fe2efc57SMark   Input Parameters:
348f6dfbefdSBarry Smith + A    - the `SNES` context
349dc4c0fb0SBarry Smith . obj  - Optional object that provides the options prefix for the checks
350736c3998SJose E. Roman - name - command line option
351fe2efc57SMark 
352fe2efc57SMark   Level: intermediate
353f6dfbefdSBarry Smith 
3541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()`
355fe2efc57SMark @*/
356d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[])
357d71ae5a4SJacob Faibussowitsch {
358fe2efc57SMark   PetscFunctionBegin;
359fe2efc57SMark   PetscValidHeaderSpecific(A, SNES_CLASSID, 1);
3609566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
3613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
362fe2efc57SMark }
363fe2efc57SMark 
364789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *);
365789d8953SBarry Smith 
366ffeef943SBarry Smith /*@
367dc4c0fb0SBarry Smith   SNESView - Prints or visualizes the `SNES` data structure.
3689b94acceSBarry Smith 
369c3339decSBarry Smith   Collective
370fee21e36SBarry Smith 
371c7afd0dbSLois Curfman McInnes   Input Parameters:
372f6dfbefdSBarry Smith + snes   - the `SNES` context
373f6dfbefdSBarry Smith - viewer - the `PetscViewer`
374c7afd0dbSLois Curfman McInnes 
3759b94acceSBarry Smith   Options Database Key:
376f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()`
3779b94acceSBarry Smith 
378dc4c0fb0SBarry Smith   Level: beginner
379dc4c0fb0SBarry Smith 
3809b94acceSBarry Smith   Notes:
3819b94acceSBarry Smith   The available visualization contexts include
382f6dfbefdSBarry Smith +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
383f6dfbefdSBarry Smith -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
384c8a8ba5cSLois Curfman McInnes   output where only the first processor opens
385c8a8ba5cSLois Curfman McInnes   the file.  All other processors send their
386c8a8ba5cSLois Curfman McInnes   data to the first processor to print.
3879b94acceSBarry Smith 
388052bf0daSPierre Jolivet   The available formats include
389f6dfbefdSBarry Smith +     `PETSC_VIEWER_DEFAULT` - standard output (default)
390f6dfbefdSBarry Smith -     `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM`
391052bf0daSPierre Jolivet 
3923e081fefSLois Curfman McInnes   The user can open an alternative visualization context with
393f6dfbefdSBarry Smith   `PetscViewerASCIIOpen()` - output to a specified file.
3949b94acceSBarry Smith 
395f6dfbefdSBarry Smith   In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer).
396595c91d4SBarry Smith 
3971cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()`
3989b94acceSBarry Smith @*/
399d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer)
400d71ae5a4SJacob Faibussowitsch {
401fa9f3622SBarry Smith   SNESKSPEW     *kctx;
40294b7f48cSBarry Smith   KSP            ksp;
4037f1410a3SPeter Brune   SNESLineSearch linesearch;
40472a02f06SBarry Smith   PetscBool      iascii, isstring, isbinary, isdraw;
4052d53ad75SBarry Smith   DMSNES         dmsnes;
406e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
407536b137fSBarry Smith   PetscBool issaws;
408bfb97211SBarry Smith #endif
4099b94acceSBarry Smith 
4103a40ed3dSBarry Smith   PetscFunctionBegin;
4110700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
41248a46eb9SPierre Jolivet   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer));
4130700a824SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
414c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, viewer, 2);
41574679c65SBarry Smith 
4169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4179566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
4189566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
4199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
420e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
4219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
422bfb97211SBarry Smith #endif
42332077d6dSBarry Smith   if (iascii) {
424dc0571f2SMatthew G. Knepley     SNESNormSchedule normschedule;
4258404b7f3SBarry Smith     DM               dm;
4268434afd1SBarry Smith     SNESJacobianFn  *cJ;
4278404b7f3SBarry Smith     void            *ctx;
428789d8953SBarry Smith     const char      *pre = "";
429dc0571f2SMatthew G. Knepley 
4309566063dSJacob Faibussowitsch     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer));
43148a46eb9SPierre Jolivet     if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  SNES has not been set up so information may be incomplete\n"));
432e7788613SBarry Smith     if (snes->ops->view) {
4339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
434dbbe0bcdSBarry Smith       PetscUseTypeMethod(snes, view, viewer);
4359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
4360ef38995SBarry Smith     }
43777e5a1f9SBarry Smith     if (snes->max_funcs == PETSC_UNLIMITED) {
43877e5a1f9SBarry Smith       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=unlimited\n", snes->max_its));
43977e5a1f9SBarry Smith     } else {
44063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs));
44177e5a1f9SBarry Smith     }
4429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol));
44348a46eb9SPierre Jolivet     if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its));
44463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs));
4459566063dSJacob Faibussowitsch     PetscCall(SNESGetNormSchedule(snes, &normschedule));
4469566063dSJacob Faibussowitsch     if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "  norm schedule %s\n", SNESNormSchedules[normschedule]));
44748a46eb9SPierre Jolivet     if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence));
4489b94acceSBarry Smith     if (snes->ksp_ewconv) {
449fa9f3622SBarry Smith       kctx = (SNESKSPEW *)snes->kspconvctx;
4509b94acceSBarry Smith       if (kctx) {
45163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version));
4529566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold));
4539566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2));
4549b94acceSBarry Smith       }
4559b94acceSBarry Smith     }
456eb1f6c34SBarry Smith     if (snes->lagpreconditioner == -1) {
4579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is never rebuilt\n"));
458eb1f6c34SBarry Smith     } else if (snes->lagpreconditioner > 1) {
45963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner));
460eb1f6c34SBarry Smith     }
461eb1f6c34SBarry Smith     if (snes->lagjacobian == -1) {
4629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is never rebuilt\n"));
463eb1f6c34SBarry Smith     } else if (snes->lagjacobian > 1) {
46463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian));
465eb1f6c34SBarry Smith     }
4669566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4679566063dSJacob Faibussowitsch     PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx));
468789d8953SBarry Smith     if (snes->mf_operator) {
4699566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing\n"));
470789d8953SBarry Smith       pre = "Preconditioning ";
471789d8953SBarry Smith     }
4728404b7f3SBarry Smith     if (cJ == SNESComputeJacobianDefault) {
4739566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences one column at a time\n", pre));
4748404b7f3SBarry Smith     } else if (cJ == SNESComputeJacobianDefaultColor) {
4759566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences with coloring\n", pre));
476789d8953SBarry Smith       /* it slightly breaks data encapsulation for access the DMDA information directly */
477789d8953SBarry Smith     } else if (cJ == SNESComputeJacobian_DMDA) {
478789d8953SBarry Smith       MatFDColoring fdcoloring;
4799566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring));
480789d8953SBarry Smith       if (fdcoloring) {
4819566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using colored finite differences on a DMDA\n", pre));
482789d8953SBarry Smith       } else {
4839566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using a DMDA local Jacobian\n", pre));
484789d8953SBarry Smith       }
485996e1cbcSBarry Smith     } else if (snes->mf && !snes->mf_operator) {
4869566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing, no explicit Jacobian\n"));
4878404b7f3SBarry Smith     }
4880f5bd95cSBarry Smith   } else if (isstring) {
489317d6ea6SBarry Smith     const char *type;
4909566063dSJacob Faibussowitsch     PetscCall(SNESGetType(snes, &type));
4919566063dSJacob Faibussowitsch     PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type));
492dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
49355849f57SBarry Smith   } else if (isbinary) {
49455849f57SBarry Smith     PetscInt    classid = SNES_FILE_CLASSID;
49555849f57SBarry Smith     MPI_Comm    comm;
49655849f57SBarry Smith     PetscMPIInt rank;
49755849f57SBarry Smith     char        type[256];
49855849f57SBarry Smith 
4999566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
5009566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
501dd400576SPatrick Sanan     if (rank == 0) {
5029566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
5039566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type)));
5049566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR));
50555849f57SBarry Smith     }
506dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
50772a02f06SBarry Smith   } else if (isdraw) {
50872a02f06SBarry Smith     PetscDraw draw;
50972a02f06SBarry Smith     char      str[36];
51089fd9fafSBarry Smith     PetscReal x, y, bottom, h;
51172a02f06SBarry Smith 
5129566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5139566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
5149566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str)));
5159566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str)));
5169566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h));
51789fd9fafSBarry Smith     bottom = y - h;
5189566063dSJacob Faibussowitsch     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
519dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
520e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
521536b137fSBarry Smith   } else if (issaws) {
522d45a07a7SBarry Smith     PetscMPIInt rank;
5232657e9d9SBarry Smith     const char *name;
524d45a07a7SBarry Smith 
5259566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)snes, &name));
5269566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
527dd400576SPatrick Sanan     if (!((PetscObject)snes)->amsmem && rank == 0) {
528d45a07a7SBarry Smith       char dir[1024];
529d45a07a7SBarry Smith 
5309566063dSJacob Faibussowitsch       PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer));
5319566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name));
532792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT));
53348a46eb9SPierre Jolivet       if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE));
5349566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name));
535792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE));
536f05ece33SBarry Smith     }
537bfb97211SBarry Smith #endif
53872a02f06SBarry Smith   }
53972a02f06SBarry Smith   if (snes->linesearch) {
5409566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &linesearch));
5419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5429566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchView(linesearch, viewer));
5439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
54419bcc07fSBarry Smith   }
545efd4aadfSBarry Smith   if (snes->npc && snes->usesnpc) {
5469566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5479566063dSJacob Faibussowitsch     PetscCall(SNESView(snes->npc, viewer));
5489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5494a0c5b0cSMatthew G Knepley   }
5509566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
5519566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(snes->dm, &dmsnes));
5529566063dSJacob Faibussowitsch   PetscCall(DMSNESView(dmsnes, viewer));
5539566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
5542c155ee1SBarry Smith   if (snes->usesksp) {
5559566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
5569566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5579566063dSJacob Faibussowitsch     PetscCall(KSPView(ksp, viewer));
5589566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5592c155ee1SBarry Smith   }
56072a02f06SBarry Smith   if (isdraw) {
56172a02f06SBarry Smith     PetscDraw draw;
5629566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5639566063dSJacob Faibussowitsch     PetscCall(PetscDrawPopCurrentPoint(draw));
5647f1410a3SPeter Brune   }
5653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5669b94acceSBarry Smith }
5679b94acceSBarry Smith 
56876b2cf59SMatthew Knepley /*
56976b2cf59SMatthew Knepley   We retain a list of functions that also take SNES command
57076b2cf59SMatthew Knepley   line options. These are called at the end SNESSetFromOptions()
57176b2cf59SMatthew Knepley */
57276b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5
573a7cc72afSBarry Smith static PetscInt numberofsetfromoptions;
5746849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
57576b2cf59SMatthew Knepley 
576ac226902SBarry Smith /*@C
577f6dfbefdSBarry Smith   SNESAddOptionsChecker - Adds an additional function to check for `SNES` options.
57876b2cf59SMatthew Knepley 
57976b2cf59SMatthew Knepley   Not Collective
58076b2cf59SMatthew Knepley 
58176b2cf59SMatthew Knepley   Input Parameter:
58276b2cf59SMatthew Knepley . snescheck - function that checks for options
58376b2cf59SMatthew Knepley 
584420bcc1bSBarry Smith   Calling sequence of `snescheck`:
585420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options
586420bcc1bSBarry Smith 
58776b2cf59SMatthew Knepley   Level: developer
58876b2cf59SMatthew Knepley 
5891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`
59076b2cf59SMatthew Knepley @*/
591420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes))
592d71ae5a4SJacob Faibussowitsch {
59376b2cf59SMatthew Knepley   PetscFunctionBegin;
59463a3b9bcSJacob Faibussowitsch   PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS);
59576b2cf59SMatthew Knepley   othersetfromoptions[numberofsetfromoptions++] = snescheck;
5963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59776b2cf59SMatthew Knepley }
59876b2cf59SMatthew Knepley 
599d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
600d71ae5a4SJacob Faibussowitsch {
601aa3661deSLisandro Dalcin   Mat          J;
602895c21f2SBarry Smith   MatNullSpace nullsp;
603aa3661deSLisandro Dalcin 
604aa3661deSLisandro Dalcin   PetscFunctionBegin;
6050700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
606aa3661deSLisandro Dalcin 
60798613b67SLisandro Dalcin   if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
60898613b67SLisandro Dalcin     Mat A = snes->jacobian, B = snes->jacobian_pre;
6099566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func));
61098613b67SLisandro Dalcin   }
61198613b67SLisandro Dalcin 
6120fdf79fbSJacob Faibussowitsch   PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
613aa3661deSLisandro Dalcin   if (version == 1) {
6149566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
6159566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
6169566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
6171e2ae407SBarry Smith     /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
6180fdf79fbSJacob Faibussowitsch   } else /* if (version == 2) */ {
6195f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first");
620570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
621f6dfbefdSBarry Smith     PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J));
622aa3661deSLisandro Dalcin #else
6232479783cSJose E. Roman     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
624aa3661deSLisandro Dalcin #endif
6250fdf79fbSJacob Faibussowitsch   }
626aa3661deSLisandro Dalcin 
62701c1178eSBarry Smith   /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */
628895c21f2SBarry Smith   if (snes->jacobian) {
6299566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(snes->jacobian, &nullsp));
6301baa6e33SBarry Smith     if (nullsp) PetscCall(MatSetNullSpace(J, nullsp));
631895c21f2SBarry Smith   }
632895c21f2SBarry Smith 
63363a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version));
634d3462f78SMatthew Knepley   if (hasOperator) {
635aa3661deSLisandro Dalcin     /* This version replaces the user provided Jacobian matrix with a
6367addb90fSBarry Smith        matrix-free version but still employs the user-provided matrix used for computing the preconditioner. */
6379566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
638aa3661deSLisandro Dalcin   } else {
639aa3661deSLisandro Dalcin     /* This version replaces both the user-provided Jacobian and the user-
64001c1178eSBarry Smith      provided preconditioner Jacobian with the default matrix-free version. */
641b552625fSStefano Zampini     if (snes->npcside == PC_LEFT && snes->npc) {
6429566063dSJacob Faibussowitsch       if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
643172a4300SPeter Brune     } else {
644789d8953SBarry Smith       KSP       ksp;
645789d8953SBarry Smith       PC        pc;
646789d8953SBarry Smith       PetscBool match;
647789d8953SBarry Smith 
6489566063dSJacob Faibussowitsch       PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL));
649aa3661deSLisandro Dalcin       /* Force no preconditioner */
6509566063dSJacob Faibussowitsch       PetscCall(SNESGetKSP(snes, &ksp));
6519566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksp, &pc));
6522698c518SLisandro Dalcin       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, ""));
653aa3661deSLisandro Dalcin       if (!match) {
6549566063dSJacob Faibussowitsch         PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n"));
6559566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc, PCNONE));
656aa3661deSLisandro Dalcin       }
657aa3661deSLisandro Dalcin     }
658789d8953SBarry Smith   }
6599566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&J));
6603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
661aa3661deSLisandro Dalcin }
662aa3661deSLisandro Dalcin 
663d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx)
664d71ae5a4SJacob Faibussowitsch {
665dfe15315SJed Brown   SNES snes = (SNES)ctx;
6660298fd71SBarry Smith   Vec  Xfine, Xfine_named = NULL, Xcoarse;
667dfe15315SJed Brown 
668dfe15315SJed Brown   PetscFunctionBegin;
66916ebb321SJed Brown   if (PetscLogPrintInfo) {
67016ebb321SJed Brown     PetscInt finelevel, coarselevel, fineclevel, coarseclevel;
6719566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmfine, &finelevel));
6729566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel));
6739566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel));
6749566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel));
67563a3b9bcSJacob 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));
67616ebb321SJed Brown   }
677dfe15315SJed Brown   if (dmfine == snes->dm) Xfine = snes->vec_sol;
678dfe15315SJed Brown   else {
6799566063dSJacob Faibussowitsch     PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
680dfe15315SJed Brown     Xfine = Xfine_named;
681dfe15315SJed Brown   }
6829566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
683907f5c5aSLawrence Mitchell   if (Inject) {
6849566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Inject, Xfine, Xcoarse));
685907f5c5aSLawrence Mitchell   } else {
6869566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Restrict, Xfine, Xcoarse));
6879566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale));
688907f5c5aSLawrence Mitchell   }
6899566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
6909566063dSJacob Faibussowitsch   if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
6913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
692dfe15315SJed Brown }
693dfe15315SJed Brown 
694d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx)
695d71ae5a4SJacob Faibussowitsch {
69616ebb321SJed Brown   PetscFunctionBegin;
6979566063dSJacob Faibussowitsch   PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx));
6983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
69916ebb321SJed Brown }
70016ebb321SJed Brown 
701a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
702a6950cb2SJed Brown  * safely call SNESGetDM() in their residual evaluation routine. */
703d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx)
704d71ae5a4SJacob Faibussowitsch {
705caa4e7f2SJed Brown   SNES            snes = (SNES)ctx;
70697d931d1SStefano Zampini   DMSNES          sdm;
7070298fd71SBarry Smith   Vec             X, Xnamed = NULL;
708dfe15315SJed Brown   DM              dmsave;
7094e269d77SPeter Brune   void           *ctxsave;
7108434afd1SBarry Smith   SNESJacobianFn *jac = NULL;
711caa4e7f2SJed Brown 
712caa4e7f2SJed Brown   PetscFunctionBegin;
713dfe15315SJed Brown   dmsave = snes->dm;
7149566063dSJacob Faibussowitsch   PetscCall(KSPGetDM(ksp, &snes->dm));
715dfe15315SJed Brown   if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
71697d931d1SStefano Zampini   else {
717309d62e6SStefano Zampini     PetscBool has;
718309d62e6SStefano Zampini 
71997d931d1SStefano Zampini     /* We are on a coarser level, this vec was initialized using a DM restrict hook */
720309d62e6SStefano Zampini     PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has));
721309d62e6SStefano Zampini     PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol");
72297d931d1SStefano Zampini     PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
723dfe15315SJed Brown     X = Xnamed;
7249566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave));
7254e269d77SPeter Brune     /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
72648a46eb9SPierre Jolivet     if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL));
7274e269d77SPeter Brune   }
7284e269d77SPeter Brune 
7292b93b426SMatthew G. Knepley   /* Compute the operators */
73097d931d1SStefano Zampini   PetscCall(DMGetDMSNES(snes->dm, &sdm));
73197d931d1SStefano Zampini   if (Xnamed && sdm->ops->computefunction) {
73297d931d1SStefano Zampini     /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian.
73397d931d1SStefano Zampini        We make sure of this here. Disable affine shift since it is for the finest level */
73497d931d1SStefano Zampini     Vec F, saverhs = snes->vec_rhs;
73597d931d1SStefano Zampini 
73697d931d1SStefano Zampini     snes->vec_rhs = NULL;
73797d931d1SStefano Zampini     PetscCall(DMGetGlobalVector(snes->dm, &F));
73897d931d1SStefano Zampini     PetscCall(SNESComputeFunction(snes, X, F));
73997d931d1SStefano Zampini     PetscCall(DMRestoreGlobalVector(snes->dm, &F));
74097d931d1SStefano Zampini     snes->vec_rhs = saverhs;
74197d931d1SStefano Zampini     snes->nfuncs--; /* Do not log coarser level evaluations */
74297d931d1SStefano Zampini   }
74397d931d1SStefano Zampini   /* Make sure KSP DM has the Jacobian computation routine */
74497d931d1SStefano Zampini   if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm));
7459566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, X, A, B));
74697d931d1SStefano Zampini 
7472b93b426SMatthew G. Knepley   /* Put the previous context back */
74848a46eb9SPierre Jolivet   if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave));
7494e269d77SPeter Brune 
7509566063dSJacob Faibussowitsch   if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
751dfe15315SJed Brown   snes->dm = dmsave;
7523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
753caa4e7f2SJed Brown }
754caa4e7f2SJed Brown 
7556cab3a1bSJed Brown /*@
756dc4c0fb0SBarry Smith   SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()`
7576cab3a1bSJed Brown 
7586cab3a1bSJed Brown   Collective
7596cab3a1bSJed Brown 
7604165533cSJose E. Roman   Input Parameter:
76120f4b53cSBarry Smith . snes - `SNES` object to configure
7626cab3a1bSJed Brown 
7636cab3a1bSJed Brown   Level: developer
7646cab3a1bSJed Brown 
765dc4c0fb0SBarry Smith   Note:
766dc4c0fb0SBarry 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`
767dc4c0fb0SBarry Smith 
76873a84a35SBarry Smith   Developer Note:
76973a84a35SBarry Smith   The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by
77073a84a35SBarry Smith   `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the
77173a84a35SBarry Smith   logic that handles the matrix-free case is desirable.
77273a84a35SBarry Smith 
7731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()`
7746cab3a1bSJed Brown @*/
775d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
776d71ae5a4SJacob Faibussowitsch {
7776cab3a1bSJed Brown   DM     dm;
778942e3340SBarry Smith   DMSNES sdm;
7796cab3a1bSJed Brown 
7806cab3a1bSJed Brown   PetscFunctionBegin;
7819566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
7829566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
78373a84a35SBarry Smith   if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) {
7846cab3a1bSJed Brown     Mat   J;
7856cab3a1bSJed Brown     void *functx;
7869566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7879566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7889566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7899566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7909566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7919566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
792caa4e7f2SJed Brown   } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7936cab3a1bSJed Brown     Mat J, B;
7949566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7959566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7969566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7979566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
79806f20277SJed Brown     /* sdm->computejacobian was already set to reach here */
7999566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
8009566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
8019566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
802caa4e7f2SJed Brown   } else if (!snes->jacobian_pre) {
8031ba9b98eSMatthew G. Knepley     PetscDS   prob;
8046cab3a1bSJed Brown     Mat       J, B;
8051ba9b98eSMatthew G. Knepley     PetscBool hasPrec = PETSC_FALSE;
8061ba9b98eSMatthew G. Knepley 
8076cab3a1bSJed Brown     J = snes->jacobian;
8089566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
8099566063dSJacob Faibussowitsch     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
8109566063dSJacob Faibussowitsch     if (J) PetscCall(PetscObjectReference((PetscObject)J));
8119566063dSJacob Faibussowitsch     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
8129566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
8139566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
8149566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
8159566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
8166cab3a1bSJed Brown   }
817caa4e7f2SJed Brown   {
818caa4e7f2SJed Brown     KSP ksp;
8199566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
8209566063dSJacob Faibussowitsch     PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
8219566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
822caa4e7f2SJed Brown   }
8233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8246cab3a1bSJed Brown }
8256cab3a1bSJed Brown 
826ce78bad3SBarry Smith PETSC_EXTERN PetscErrorCode PetscMonitorPauseFinal_Internal(PetscInt, void *);
827ce78bad3SBarry Smith 
828d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
829d71ae5a4SJacob Faibussowitsch {
8305e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
8313ba16761SJacob Faibussowitsch   if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
832ce78bad3SBarry Smith   PetscCall(PetscMonitorPauseFinal_Internal(snes->numbermonitors, snes->monitorcontext));
8333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8345e7c47f3SMatthew G. Knepley }
8355e7c47f3SMatthew G. Knepley 
836fde5950dSBarry Smith /*@C
837fde5950dSBarry Smith   SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
838fde5950dSBarry Smith 
839c3339decSBarry Smith   Collective
840fde5950dSBarry Smith 
841fde5950dSBarry Smith   Input Parameters:
842dc4c0fb0SBarry Smith + snes         - `SNES` object you wish to monitor
843fde5950dSBarry Smith . name         - the monitor type one is seeking
844fde5950dSBarry Smith . help         - message indicating what monitoring is done
845fde5950dSBarry Smith . manual       - manual page for the monitor
84649abdd8aSBarry Smith . monitor      - the monitor function, this must use a `PetscViewerFormat` as its context
847f6dfbefdSBarry 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
848fde5950dSBarry Smith 
849420bcc1bSBarry Smith   Calling sequence of `monitor`:
850420bcc1bSBarry Smith + snes - the nonlinear solver context
851420bcc1bSBarry Smith . it   - the current iteration
852420bcc1bSBarry Smith . r    - the current function norm
853420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
854420bcc1bSBarry Smith 
855420bcc1bSBarry Smith   Calling sequence of `monitorsetup`:
856420bcc1bSBarry Smith + snes - the nonlinear solver context
857420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
858420bcc1bSBarry Smith 
859f6dfbefdSBarry Smith   Options Database Key:
860f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()`
861f6dfbefdSBarry Smith 
862f6dfbefdSBarry Smith   Level: advanced
863fde5950dSBarry Smith 
864648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
865db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
866e4094ef1SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
867db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
868c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
869db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
870db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
871fde5950dSBarry Smith @*/
872420bcc1bSBarry 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))
873d71ae5a4SJacob Faibussowitsch {
874fde5950dSBarry Smith   PetscViewer       viewer;
875fde5950dSBarry Smith   PetscViewerFormat format;
876fde5950dSBarry Smith   PetscBool         flg;
877fde5950dSBarry Smith 
878fde5950dSBarry Smith   PetscFunctionBegin;
879648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
880fde5950dSBarry Smith   if (flg) {
881d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8829566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
883648c30bcSBarry Smith     PetscCall(PetscViewerDestroy(&viewer));
8841baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
88549abdd8aSBarry Smith     PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
886fde5950dSBarry Smith   }
8873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
888fde5950dSBarry Smith }
889fde5950dSBarry Smith 
890a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
891d71ae5a4SJacob Faibussowitsch {
892a4598233SStefano Zampini   const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
893a4598233SStefano Zampini 
8940f0abf79SStefano Zampini   PetscFunctionBegin;
8950f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
896a4598233SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
897a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
898a4598233SStefano Zampini   kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
899a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
900a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
901a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
9020f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
903a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
9040f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
9050f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
9060f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
9070f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
9080f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
9090f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
9100f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
9110f0abf79SStefano Zampini   PetscOptionsEnd();
9123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9130f0abf79SStefano Zampini }
9140f0abf79SStefano Zampini 
9159b94acceSBarry Smith /*@
916f6dfbefdSBarry Smith   SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
9179b94acceSBarry Smith 
918c3339decSBarry Smith   Collective
919c7afd0dbSLois Curfman McInnes 
9209b94acceSBarry Smith   Input Parameter:
921f6dfbefdSBarry Smith . snes - the `SNES` context
9229b94acceSBarry Smith 
92336851e7fSLois Curfman McInnes   Options Database Keys:
924f6dfbefdSBarry Smith + -snes_type <type>                                                            - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
925b39c3a46SLois Curfman McInnes . -snes_rtol <rtol>                                                            - relative decrease in tolerance norm from initial
92677e5a1f9SBarry Smith . -snes_atol <abstol>                                                          - absolute tolerance of residual norm
92777e5a1f9SBarry Smith . -snes_stol <stol>                                                            - convergence tolerance in terms of the norm of the change in the solution between steps
928e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol>                                          - if the residual goes above divtol*rnorm0, exit with divergence
929b39c3a46SLois Curfman McInnes . -snes_max_it <max_it>                                                        - maximum number of iterations
930b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs>                                                  - maximum number of function evaluations
93177e5a1f9SBarry Smith . -snes_force_iteration <force>                                                - force `SNESSolve()` to take at least one iteration
9324839bfe8SBarry Smith . -snes_max_fail <max_fail>                                                    - maximum number of line search failures allowed before stopping, default is none
933ddf469c8SBarry Smith . -snes_max_linear_solve_fail                                                  - number of linear solver failures before SNESSolve() stops
934a8054027SBarry Smith . -snes_lag_preconditioner <lag>                                               - how often preconditioner is rebuilt (use -1 to never rebuild)
9353d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false>                               - retains the -snes_lag_preconditioner information across multiple SNESSolve()
936e35cf81dSBarry Smith . -snes_lag_jacobian <lag>                                                     - how often Jacobian is rebuilt (use -1 to never rebuild)
9373d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false>                                     - retains the -snes_lag_jacobian information across multiple SNESSolve()
938ceaaa498SBarry 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.
939fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format]                             - prints residual norm at each iteration. if no filename given prints to stdout
940fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format]        - plots solution at each iteration
941fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format]        - plots residual (not its norm) at each iteration
942fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9434619e776SBarry Smith . -snes_monitor_lg_residualnorm                                                - plots residual norm at each iteration
944459f5d12SBarry Smith . -snes_monitor_lg_range                                                       - plots residual norm at each iteration
9455e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final                                                    - Pauses all monitor drawing after the solver ends
946e24b481bSBarry Smith . -snes_fd                                                                     - use finite differences to compute Jacobian; very slow, only for testing
947e2e60de9SPeter Brune . -snes_fd_color                                                               - use finite differences with coloring to compute Jacobian
948ceaaa498SBarry Smith . -snes_mf_ksp_monitor                                                         - if using matrix-free multiply then print h at each `KSP` iteration
949b5badacbSBarry Smith . -snes_converged_reason                                                       - print the reason for convergence/divergence after each solve
950ceaaa498SBarry Smith . -npc_snes_type <type>                                                        - the `SNES` type to use as a nonlinear preconditioner
951e62ac41dSBarry 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.
952e62ac41dSBarry 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.
95382738288SBarry Smith 
954f6dfbefdSBarry Smith   Options Database Keys for Eisenstat-Walker method:
955fa9f3622SBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
9564b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
95736851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
95836851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
95936851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma>         - Sets gamma
96036851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha>         - Sets alpha
96136851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
96236851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
96382738288SBarry Smith 
964dc4c0fb0SBarry Smith   Level: beginner
965dc4c0fb0SBarry Smith 
96611ca99fdSLois Curfman McInnes   Notes:
967ec5066bdSBarry Smith   To see all options, run your program with the -help option or consult the users manual
968ec5066bdSBarry Smith 
969420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
970420bcc1bSBarry Smith   and computing explicitly with
971f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
97283e2fdc7SBarry Smith 
973420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring`
9749b94acceSBarry Smith @*/
975d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
976d71ae5a4SJacob Faibussowitsch {
9778afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
97877e5a1f9SBarry Smith   PetscInt    i, indx, lag, grids, max_its, max_funcs;
97904d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
980649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
98185385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9820f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
983c40d0f55SPeter Brune   PCSide      pcside;
984a64e098fSPeter Brune   const char *optionsprefix;
98577e5a1f9SBarry Smith   PetscReal   rtol, abstol, stol;
9869b94acceSBarry Smith 
9873a40ed3dSBarry Smith   PetscFunctionBegin;
9880700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9899566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
990d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
991639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
993d64ed03dSBarry Smith   if (flg) {
9949566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
9957adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
9969566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
997d64ed03dSBarry Smith   }
998186905e3SBarry Smith 
99977e5a1f9SBarry Smith   abstol    = snes->abstol;
100077e5a1f9SBarry Smith   rtol      = snes->rtol;
100177e5a1f9SBarry Smith   stol      = snes->stol;
100277e5a1f9SBarry Smith   max_its   = snes->max_its;
100377e5a1f9SBarry Smith   max_funcs = snes->max_funcs;
100477e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL));
100577e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL));
100677e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL));
100777e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL));
100877e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL));
100977e5a1f9SBarry Smith   PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs));
101077e5a1f9SBarry Smith 
101177e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg));
101277e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol));
101377e5a1f9SBarry Smith 
101477e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg));
101577e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures));
101677e5a1f9SBarry Smith 
101777e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg));
101877e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures));
101977e5a1f9SBarry Smith 
10209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
10219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
10229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
102385385478SLisandro Dalcin 
10249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
1025a8054027SBarry Smith   if (flg) {
10265f80ce2aSJacob 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");
10279566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
1028a8054027SBarry Smith   }
10299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
10301baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
10319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
1032e35cf81dSBarry Smith   if (flg) {
10335f80ce2aSJacob 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");
10349566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
1035e35cf81dSBarry Smith   }
10369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
10371baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
103837ec4e1aSPeter Brune 
10399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
10401baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
1041a8054027SBarry Smith 
1042400f6f02SBarry Smith   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg));
104385385478SLisandro Dalcin   if (flg) {
104485385478SLisandro Dalcin     switch (indx) {
1045d71ae5a4SJacob Faibussowitsch     case 0:
1046d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1047d71ae5a4SJacob Faibussowitsch       break;
1048d71ae5a4SJacob Faibussowitsch     case 1:
1049d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1050d71ae5a4SJacob Faibussowitsch       break;
1051d71ae5a4SJacob Faibussowitsch     case 2:
1052d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1053d71ae5a4SJacob Faibussowitsch       break;
105485385478SLisandro Dalcin     }
105585385478SLisandro Dalcin   }
105685385478SLisandro Dalcin 
10579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10589566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1059fdacfa88SPeter Brune 
10609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10619566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1062186905e3SBarry Smith 
106385385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
106485385478SLisandro Dalcin 
10659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1066186905e3SBarry Smith 
10670f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10680f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1069a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1070186905e3SBarry Smith 
107190d69ab7SBarry Smith   flg = PETSC_FALSE;
10729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10739566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1074eabae89aSBarry Smith 
10759566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10769566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10779566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1078eabae89aSBarry Smith 
10799566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10809566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10819566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10829566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10839566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10849566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10859566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10872db13446SMatthew G. Knepley 
10889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10899566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10905180491cSLisandro Dalcin 
109190d69ab7SBarry Smith   flg = PETSC_FALSE;
10929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1093459f5d12SBarry Smith   if (flg) {
1094459f5d12SBarry Smith     PetscViewer ctx;
1095e24b481bSBarry Smith 
10969566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
109749abdd8aSBarry Smith     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscCtxDestroyFn *)PetscViewerDestroy));
1098459f5d12SBarry Smith   }
10992e7541e6SPeter Brune 
1100648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
1101648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL));
110290d69ab7SBarry Smith   flg = PETSC_FALSE;
11039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
11049566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1105c4421ceaSFande Kong 
1106c4421ceaSFande Kong   flg = PETSC_FALSE;
11079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
11084b27c08aSLois Curfman McInnes   if (flg) {
11096cab3a1bSJed Brown     void *functx;
1110b1f624c7SBarry Smith     DM    dm;
11119566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1112800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11139566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
11149566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
11159566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
11169b94acceSBarry Smith   }
1117639f9d9dSBarry Smith 
111844848bc4SPeter Brune   flg = PETSC_FALSE;
11199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
11201baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
112197584545SPeter Brune 
112297584545SPeter Brune   flg = PETSC_FALSE;
11239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
112444848bc4SPeter Brune   if (flg) {
1125c52e227fSPeter Brune     DM dm;
11269566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1127800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11289566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
11299566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
113044848bc4SPeter Brune   }
113144848bc4SPeter Brune 
1132aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11337addb90fSBarry 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));
1134d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1135a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1136d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1137a8248277SBarry Smith   }
1138aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11397addb90fSBarry Smith   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1140d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
11419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1142d28543b3SPeter Brune 
1143c40d0f55SPeter Brune   flg = PETSC_FALSE;
11449566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11469566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1147c40d0f55SPeter Brune 
1148e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11498a70d858SHong Zhang   /*
11508a70d858SHong Zhang     Publish convergence information using SAWs
11518a70d858SHong Zhang   */
11528a70d858SHong Zhang   flg = PETSC_FALSE;
11539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11548a70d858SHong Zhang   if (flg) {
11558a70d858SHong Zhang     void *ctx;
11569566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11579566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11588a70d858SHong Zhang   }
11598a70d858SHong Zhang #endif
11608a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1161b90c6cbeSBarry Smith   {
1162b90c6cbeSBarry Smith     PetscBool set;
1163b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11649566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11651baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1166b90c6cbeSBarry Smith   }
1167b90c6cbeSBarry Smith #endif
1168b90c6cbeSBarry Smith 
116948a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
117076b2cf59SMatthew Knepley 
1171dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11725d973c19SBarry Smith 
11735d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1174dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1175d0609cedSBarry Smith   PetscOptionsEnd();
11764bbc92c1SBarry Smith 
1177d8d34be6SBarry Smith   if (snes->linesearch) {
11789566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11799566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1180d8d34be6SBarry Smith   }
11819e764e56SPeter Brune 
11826aa5e7e9SBarry Smith   if (snes->usesksp) {
11839566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11849566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11859566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11866aa5e7e9SBarry Smith   }
11876991f827SBarry Smith 
1188b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11899566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
119148a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11921baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1193b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1195b3cd9a81SMatthew G. Knepley }
1196b3cd9a81SMatthew G. Knepley 
1197b3cd9a81SMatthew G. Knepley /*@
1198420bcc1bSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1199b3cd9a81SMatthew G. Knepley 
1200c3339decSBarry Smith   Collective
1201b3cd9a81SMatthew G. Knepley 
1202b3cd9a81SMatthew G. Knepley   Input Parameter:
1203f6dfbefdSBarry Smith . snes - the `SNES` context
1204b3cd9a81SMatthew G. Knepley 
1205420bcc1bSBarry Smith   Level: advanced
1206b3cd9a81SMatthew G. Knepley 
12071cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1208b3cd9a81SMatthew G. Knepley @*/
1209d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1210d71ae5a4SJacob Faibussowitsch {
1211b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
12129566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
12133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12149b94acceSBarry Smith }
12159b94acceSBarry Smith 
1216bb9467b5SJed Brown /*@C
1217d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1218d25893d9SBarry Smith   the nonlinear solvers.
1219d25893d9SBarry Smith 
1220dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1221d25893d9SBarry Smith 
1222d25893d9SBarry Smith   Input Parameters:
1223f6dfbefdSBarry Smith + snes    - the `SNES` context
1224d25893d9SBarry Smith . compute - function to compute the context
122549abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence
1226d25893d9SBarry Smith 
1227420bcc1bSBarry Smith   Calling sequence of `compute`:
1228420bcc1bSBarry Smith + snes - the `SNES` context
1229420bcc1bSBarry Smith - ctx  - context to be computed
1230420bcc1bSBarry Smith 
1231d25893d9SBarry Smith   Level: intermediate
1232d25893d9SBarry Smith 
1233f6dfbefdSBarry Smith   Note:
1234f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1235f6dfbefdSBarry Smith 
1236f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1237f6dfbefdSBarry Smith 
123849abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn`
1239d25893d9SBarry Smith @*/
124049abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy)
1241d71ae5a4SJacob Faibussowitsch {
1242d25893d9SBarry Smith   PetscFunctionBegin;
1243d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1244d25893d9SBarry Smith   snes->ops->usercompute = compute;
124549abdd8aSBarry Smith   snes->ops->ctxdestroy  = destroy;
12463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1247d25893d9SBarry Smith }
1248a847f771SSatish Balay 
1249b07ff414SBarry Smith /*@
1250f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12519b94acceSBarry Smith 
1252c3339decSBarry Smith   Logically Collective
1253fee21e36SBarry Smith 
1254c7afd0dbSLois Curfman McInnes   Input Parameters:
1255f6dfbefdSBarry Smith + snes - the `SNES` context
1256ce78bad3SBarry Smith - ctx  - the user context
1257c7afd0dbSLois Curfman McInnes 
125836851e7fSLois Curfman McInnes   Level: intermediate
125936851e7fSLois Curfman McInnes 
1260f6dfbefdSBarry Smith   Notes:
1261ce78bad3SBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function
1262f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1263f6dfbefdSBarry Smith 
1264f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1265f6dfbefdSBarry Smith 
1266420bcc1bSBarry Smith   Fortran Note:
1267ce78bad3SBarry 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
1268ce78bad3SBarry Smith   function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for
1269ce78bad3SBarry Smith   an example.
1270daf670e6SBarry Smith 
12711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12729b94acceSBarry Smith @*/
127349abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx)
1274d71ae5a4SJacob Faibussowitsch {
1275b07ff414SBarry Smith   KSP ksp;
12761b2093e4SBarry Smith 
12773a40ed3dSBarry Smith   PetscFunctionBegin;
12780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12799566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
128049abdd8aSBarry Smith   PetscCall(KSPSetApplicationContext(ksp, ctx));
128149abdd8aSBarry Smith   snes->ctx = ctx;
12823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12839b94acceSBarry Smith }
128474679c65SBarry Smith 
1285b07ff414SBarry Smith /*@
12869b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1287420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12889b94acceSBarry Smith 
1289c7afd0dbSLois Curfman McInnes   Not Collective
1290c7afd0dbSLois Curfman McInnes 
12919b94acceSBarry Smith   Input Parameter:
1292f6dfbefdSBarry Smith . snes - `SNES` context
12939b94acceSBarry Smith 
12949b94acceSBarry Smith   Output Parameter:
129549abdd8aSBarry Smith . ctx - user context
12969b94acceSBarry Smith 
129736851e7fSLois Curfman McInnes   Level: intermediate
129836851e7fSLois Curfman McInnes 
1299ce78bad3SBarry Smith   Fortran Notes:
1300ce78bad3SBarry 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
1301ce78bad3SBarry Smith   function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example,
1302ce78bad3SBarry Smith .vb
1303ce78bad3SBarry Smith   Interface SNESGetApplicationContext
1304ce78bad3SBarry Smith     Subroutine SNESGetApplicationContext(snes,ctx,ierr)
1305ce78bad3SBarry Smith   #include <petsc/finclude/petscsnes.h>
1306ce78bad3SBarry Smith       use petscsnes
1307ce78bad3SBarry Smith       SNES snes
1308ce78bad3SBarry Smith       type(tUsertype), pointer :: ctx
1309ce78bad3SBarry Smith       PetscErrorCode ierr
1310ce78bad3SBarry Smith     End Subroutine
1311ce78bad3SBarry Smith   End Interface SNESGetApplicationContext
1312ce78bad3SBarry Smith .ve
1313ce78bad3SBarry Smith 
1314bfe80ac4SPierre Jolivet   The prototype for `ctx` must be
1315ce78bad3SBarry Smith .vb
1316ce78bad3SBarry Smith   type(tUsertype), pointer :: ctx
1317ce78bad3SBarry Smith .ve
1318dc4c0fb0SBarry Smith 
1319420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
13209b94acceSBarry Smith @*/
1321ce78bad3SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PeCtx ctx)
1322d71ae5a4SJacob Faibussowitsch {
13233a40ed3dSBarry Smith   PetscFunctionBegin;
13240700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
132549abdd8aSBarry Smith   *(void **)ctx = snes->ctx;
13263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13279b94acceSBarry Smith }
132874679c65SBarry Smith 
13299b94acceSBarry Smith /*@
1330420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
13313565c898SBarry Smith 
1332dc4c0fb0SBarry Smith   Logically Collective
13333565c898SBarry Smith 
13343565c898SBarry Smith   Input Parameters:
1335f6dfbefdSBarry Smith + snes        - `SNES` context
1336f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1337f6dfbefdSBarry 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
1338420bcc1bSBarry Smith                 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
13393565c898SBarry Smith 
1340f6dfbefdSBarry Smith   Options Database Keys:
134101c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1342f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1343ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1344ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
13453565c898SBarry Smith 
13463565c898SBarry Smith   Level: intermediate
13473565c898SBarry Smith 
1348f6dfbefdSBarry Smith   Note:
1349420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1350420bcc1bSBarry Smith   and computing explicitly with
1351f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1352ec5066bdSBarry Smith 
1353420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13543565c898SBarry Smith @*/
1355d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1356d71ae5a4SJacob Faibussowitsch {
13573565c898SBarry Smith   PetscFunctionBegin;
13583565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
135988b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
136088b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13614ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13623565c898SBarry Smith   snes->mf_operator = mf_operator;
13633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13643565c898SBarry Smith }
13653565c898SBarry Smith 
13663565c898SBarry Smith /*@
1367dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13683565c898SBarry Smith 
1369420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13703565c898SBarry Smith 
13713565c898SBarry Smith   Input Parameter:
1372f6dfbefdSBarry Smith . snes - `SNES` context
13733565c898SBarry Smith 
13743565c898SBarry Smith   Output Parameters:
1375f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1376f6dfbefdSBarry 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
13773565c898SBarry Smith 
13783565c898SBarry Smith   Level: intermediate
13793565c898SBarry Smith 
13801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13813565c898SBarry Smith @*/
1382d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1383d71ae5a4SJacob Faibussowitsch {
13843565c898SBarry Smith   PetscFunctionBegin;
13853565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13863565c898SBarry Smith   if (mf) *mf = snes->mf;
13873565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13893565c898SBarry Smith }
13903565c898SBarry Smith 
13913565c898SBarry Smith /*@
1392420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13939b94acceSBarry Smith 
1394c7afd0dbSLois Curfman McInnes   Not Collective
1395c7afd0dbSLois Curfman McInnes 
13969b94acceSBarry Smith   Input Parameter:
1397f6dfbefdSBarry Smith . snes - `SNES` context
13989b94acceSBarry Smith 
13999b94acceSBarry Smith   Output Parameter:
14009b94acceSBarry Smith . iter - iteration number
14019b94acceSBarry Smith 
1402dc4c0fb0SBarry Smith   Level: intermediate
1403dc4c0fb0SBarry Smith 
1404c8228a4eSBarry Smith   Notes:
1405c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1406c8228a4eSBarry Smith 
1407c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1408f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
140908405cd6SLois Curfman McInnes .vb
141008405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
141108405cd6SLois Curfman McInnes       if (!(it % 2)) {
141208405cd6SLois Curfman McInnes         [compute Jacobian here]
141308405cd6SLois Curfman McInnes       }
141408405cd6SLois Curfman McInnes .ve
1415f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1416f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1417c8228a4eSBarry Smith 
1418f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1419c04deec6SBarry Smith 
1420420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
14219b94acceSBarry Smith @*/
1422d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1423d71ae5a4SJacob Faibussowitsch {
14243a40ed3dSBarry Smith   PetscFunctionBegin;
14250700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14264f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
14279b94acceSBarry Smith   *iter = snes->iter;
14283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14299b94acceSBarry Smith }
143074679c65SBarry Smith 
1431360c497dSPeter Brune /*@
1432360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1433360c497dSPeter Brune 
1434360c497dSPeter Brune   Not Collective
1435360c497dSPeter Brune 
1436d8d19677SJose E. Roman   Input Parameters:
1437f6dfbefdSBarry Smith + snes - `SNES` context
1438a2b725a8SWilliam Gropp - iter - iteration number
1439360c497dSPeter Brune 
1440360c497dSPeter Brune   Level: developer
1441360c497dSPeter Brune 
1442420bcc1bSBarry Smith   Note:
1443420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1444420bcc1bSBarry Smith 
14451cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1446360c497dSPeter Brune @*/
1447d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1448d71ae5a4SJacob Faibussowitsch {
1449360c497dSPeter Brune   PetscFunctionBegin;
1450360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14519566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1452360c497dSPeter Brune   snes->iter = iter;
14539566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1455360c497dSPeter Brune }
1456360c497dSPeter Brune 
14579b94acceSBarry Smith /*@
1458b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1459420bcc1bSBarry Smith   attempted by the nonlinear solver in the current or most recent `SNESSolve()` .
14609b94acceSBarry Smith 
1461c7afd0dbSLois Curfman McInnes   Not Collective
1462c7afd0dbSLois Curfman McInnes 
14639b94acceSBarry Smith   Input Parameter:
1464f6dfbefdSBarry Smith . snes - `SNES` context
14659b94acceSBarry Smith 
14669b94acceSBarry Smith   Output Parameter:
14679b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14689b94acceSBarry Smith 
1469dc4c0fb0SBarry Smith   Level: intermediate
1470dc4c0fb0SBarry Smith 
1471f6dfbefdSBarry Smith   Note:
1472f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1473c96a6f78SLois Curfman McInnes 
14741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1475db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14769b94acceSBarry Smith @*/
1477d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1478d71ae5a4SJacob Faibussowitsch {
14793a40ed3dSBarry Smith   PetscFunctionBegin;
14800700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14814f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
148250ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
148450ffb88aSMatthew Knepley }
148550ffb88aSMatthew Knepley 
148650ffb88aSMatthew Knepley /*@
1487b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1488420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
148950ffb88aSMatthew Knepley 
149050ffb88aSMatthew Knepley   Not Collective
149150ffb88aSMatthew Knepley 
149250ffb88aSMatthew Knepley   Input Parameters:
1493f6dfbefdSBarry Smith + snes     - `SNES` context
149477e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures
149550ffb88aSMatthew Knepley 
1496420bcc1bSBarry Smith   Options Database Key:
1497420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1498420bcc1bSBarry Smith 
149950ffb88aSMatthew Knepley   Level: intermediate
150050ffb88aSMatthew Knepley 
1501420bcc1bSBarry Smith   Developer Note:
1502420bcc1bSBarry Smith   The options database key is wrong for this function name
1503420bcc1bSBarry Smith 
15041cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1505db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
150650ffb88aSMatthew Knepley @*/
1507d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1508d71ae5a4SJacob Faibussowitsch {
150950ffb88aSMatthew Knepley   PetscFunctionBegin;
15100700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
151177e5a1f9SBarry Smith 
151277e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
15131690c2aeSBarry Smith     snes->maxFailures = PETSC_INT_MAX;
151477e5a1f9SBarry Smith   } else {
151577e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
151650ffb88aSMatthew Knepley     snes->maxFailures = maxFails;
151777e5a1f9SBarry Smith   }
15183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
151950ffb88aSMatthew Knepley }
152050ffb88aSMatthew Knepley 
152150ffb88aSMatthew Knepley /*@
1522b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1523420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
152450ffb88aSMatthew Knepley 
152550ffb88aSMatthew Knepley   Not Collective
152650ffb88aSMatthew Knepley 
152750ffb88aSMatthew Knepley   Input Parameter:
152820f4b53cSBarry Smith . snes - `SNES` context
152950ffb88aSMatthew Knepley 
153050ffb88aSMatthew Knepley   Output Parameter:
153150ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
153250ffb88aSMatthew Knepley 
153350ffb88aSMatthew Knepley   Level: intermediate
153450ffb88aSMatthew Knepley 
15351cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1536db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
153750ffb88aSMatthew Knepley @*/
1538d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1539d71ae5a4SJacob Faibussowitsch {
154050ffb88aSMatthew Knepley   PetscFunctionBegin;
15410700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15424f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
154350ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
15443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15459b94acceSBarry Smith }
1546a847f771SSatish Balay 
15472541af92SBarry Smith /*@
15482541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1549420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
15502541af92SBarry Smith 
15512541af92SBarry Smith   Not Collective
15522541af92SBarry Smith 
15532541af92SBarry Smith   Input Parameter:
1554f6dfbefdSBarry Smith . snes - `SNES` context
15552541af92SBarry Smith 
15562541af92SBarry Smith   Output Parameter:
15572541af92SBarry Smith . nfuncs - number of evaluations
15582541af92SBarry Smith 
15592541af92SBarry Smith   Level: intermediate
15602541af92SBarry Smith 
1561f6dfbefdSBarry Smith   Note:
1562f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1563971e163fSPeter Brune 
15641cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15652541af92SBarry Smith @*/
1566d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1567d71ae5a4SJacob Faibussowitsch {
15682541af92SBarry Smith   PetscFunctionBegin;
15690700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15704f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15712541af92SBarry Smith   *nfuncs = snes->nfuncs;
15723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15732541af92SBarry Smith }
15742541af92SBarry Smith 
15753d4c4710SBarry Smith /*@
15763d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1577420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15783d4c4710SBarry Smith 
15793d4c4710SBarry Smith   Not Collective
15803d4c4710SBarry Smith 
15813d4c4710SBarry Smith   Input Parameter:
1582f6dfbefdSBarry Smith . snes - `SNES` context
15833d4c4710SBarry Smith 
15843d4c4710SBarry Smith   Output Parameter:
15853d4c4710SBarry Smith . nfails - number of failed solves
15863d4c4710SBarry Smith 
1587f6dfbefdSBarry Smith   Options Database Key:
15889d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15899d85da0cSMatthew G. Knepley 
1590f6dfbefdSBarry Smith   Level: intermediate
1591f6dfbefdSBarry Smith 
1592f6dfbefdSBarry Smith   Note:
1593f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15943d4c4710SBarry Smith 
15951cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15963d4c4710SBarry Smith @*/
1597d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1598d71ae5a4SJacob Faibussowitsch {
15993d4c4710SBarry Smith   PetscFunctionBegin;
16000700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16014f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
16023d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
16033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16043d4c4710SBarry Smith }
16053d4c4710SBarry Smith 
16063d4c4710SBarry Smith /*@
16073d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1608f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
16093d4c4710SBarry Smith 
1610c3339decSBarry Smith   Logically Collective
16113d4c4710SBarry Smith 
16123d4c4710SBarry Smith   Input Parameters:
1613f6dfbefdSBarry Smith + snes     - `SNES` context
161477e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures
16153d4c4710SBarry Smith 
1616f6dfbefdSBarry Smith   Options Database Key:
16179d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
16189d85da0cSMatthew G. Knepley 
1619dc4c0fb0SBarry Smith   Level: intermediate
1620dc4c0fb0SBarry Smith 
1621f6dfbefdSBarry Smith   Note:
1622f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
16233d4c4710SBarry Smith 
1624420bcc1bSBarry Smith   Developer Note:
1625420bcc1bSBarry Smith   The options database key is wrong for this function name
1626420bcc1bSBarry Smith 
16271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
16283d4c4710SBarry Smith @*/
1629d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1630d71ae5a4SJacob Faibussowitsch {
16313d4c4710SBarry Smith   PetscFunctionBegin;
16320700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1633c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
163477e5a1f9SBarry Smith 
163577e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
16361690c2aeSBarry Smith     snes->maxLinearSolveFailures = PETSC_INT_MAX;
163777e5a1f9SBarry Smith   } else {
163877e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
16393d4c4710SBarry Smith     snes->maxLinearSolveFailures = maxFails;
164077e5a1f9SBarry Smith   }
16413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16423d4c4710SBarry Smith }
16433d4c4710SBarry Smith 
16443d4c4710SBarry Smith /*@
16453d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1646f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
16473d4c4710SBarry Smith 
16483d4c4710SBarry Smith   Not Collective
16493d4c4710SBarry Smith 
16503d4c4710SBarry Smith   Input Parameter:
1651f6dfbefdSBarry Smith . snes - `SNES` context
16523d4c4710SBarry Smith 
16533d4c4710SBarry Smith   Output Parameter:
16543d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16553d4c4710SBarry Smith 
16563d4c4710SBarry Smith   Level: intermediate
16573d4c4710SBarry Smith 
1658f6dfbefdSBarry Smith   Note:
1659f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16603d4c4710SBarry Smith 
16611cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16623d4c4710SBarry Smith @*/
1663d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1664d71ae5a4SJacob Faibussowitsch {
16653d4c4710SBarry Smith   PetscFunctionBegin;
16660700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16674f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16683d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16703d4c4710SBarry Smith }
16713d4c4710SBarry Smith 
1672c96a6f78SLois Curfman McInnes /*@
1673b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1674420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1675c96a6f78SLois Curfman McInnes 
1676c7afd0dbSLois Curfman McInnes   Not Collective
1677c7afd0dbSLois Curfman McInnes 
1678c96a6f78SLois Curfman McInnes   Input Parameter:
1679f6dfbefdSBarry Smith . snes - `SNES` context
1680c96a6f78SLois Curfman McInnes 
1681c96a6f78SLois Curfman McInnes   Output Parameter:
1682c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1683c96a6f78SLois Curfman McInnes 
1684dc4c0fb0SBarry Smith   Level: intermediate
1685dc4c0fb0SBarry Smith 
1686c96a6f78SLois Curfman McInnes   Notes:
1687f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1688c96a6f78SLois Curfman McInnes 
1689f6dfbefdSBarry 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
1690f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1691010be392SBarry Smith 
16921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1693c96a6f78SLois Curfman McInnes @*/
1694d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1695d71ae5a4SJacob Faibussowitsch {
16963a40ed3dSBarry Smith   PetscFunctionBegin;
16970700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16984f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1699c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
17003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1701c96a6f78SLois Curfman McInnes }
1702c96a6f78SLois Curfman McInnes 
1703971e163fSPeter Brune /*@
1704971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1705f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1706971e163fSPeter Brune 
1707c3339decSBarry Smith   Logically Collective
1708971e163fSPeter Brune 
1709d8d19677SJose E. Roman   Input Parameters:
1710f6dfbefdSBarry Smith + snes  - `SNES` context
1711f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1712971e163fSPeter Brune 
1713971e163fSPeter Brune   Level: developer
1714971e163fSPeter Brune 
17151cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1716971e163fSPeter Brune @*/
1717d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1718d71ae5a4SJacob Faibussowitsch {
1719971e163fSPeter Brune   PetscFunctionBegin;
1720971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1721971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1722971e163fSPeter Brune   snes->counters_reset = reset;
17233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1724971e163fSPeter Brune }
1725971e163fSPeter Brune 
17262999313aSBarry Smith /*@
172712b1dd1aSStefano Zampini   SNESResetCounters - Reset counters for linear iterations and function evaluations.
172812b1dd1aSStefano Zampini 
172912b1dd1aSStefano Zampini   Logically Collective
173012b1dd1aSStefano Zampini 
173112b1dd1aSStefano Zampini   Input Parameters:
173212b1dd1aSStefano Zampini . snes - `SNES` context
173312b1dd1aSStefano Zampini 
173412b1dd1aSStefano Zampini   Level: developer
173512b1dd1aSStefano Zampini 
173612b1dd1aSStefano Zampini   Note:
173712b1dd1aSStefano Zampini   It honors the flag set with `SNESSetCountersReset()`
173812b1dd1aSStefano Zampini 
173912b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
174012b1dd1aSStefano Zampini @*/
174112b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes)
174212b1dd1aSStefano Zampini {
174312b1dd1aSStefano Zampini   PetscFunctionBegin;
174412b1dd1aSStefano Zampini   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
174512b1dd1aSStefano Zampini   if (snes->counters_reset) {
174612b1dd1aSStefano Zampini     snes->nfuncs      = 0;
174712b1dd1aSStefano Zampini     snes->linear_its  = 0;
174812b1dd1aSStefano Zampini     snes->numFailures = 0;
174912b1dd1aSStefano Zampini   }
175012b1dd1aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
175112b1dd1aSStefano Zampini }
175212b1dd1aSStefano Zampini 
175312b1dd1aSStefano Zampini /*@
1754f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
17552999313aSBarry Smith 
1756420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
17572999313aSBarry Smith 
17582999313aSBarry Smith   Input Parameters:
1759f6dfbefdSBarry Smith + snes - the `SNES` context
1760f6dfbefdSBarry Smith - ksp  - the `KSP` context
17612999313aSBarry Smith 
1762dc4c0fb0SBarry Smith   Level: developer
1763dc4c0fb0SBarry Smith 
17642999313aSBarry Smith   Notes:
1765f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
17662999313aSBarry Smith   so this routine is rarely needed.
17672999313aSBarry Smith 
1768f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1769420bcc1bSBarry Smith   decreased by one when this is called.
17702999313aSBarry Smith 
177142747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
17722999313aSBarry Smith @*/
1773d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1774d71ae5a4SJacob Faibussowitsch {
17752999313aSBarry Smith   PetscFunctionBegin;
17760700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17770700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
17782999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
17799566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
17809566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17812999313aSBarry Smith   snes->ksp = ksp;
17823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17832999313aSBarry Smith }
17842999313aSBarry Smith 
178552baeb72SSatish Balay /*@
178677e5a1f9SBarry Smith   SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they
178777e5a1f9SBarry Smith   currently contain default values
178877e5a1f9SBarry Smith 
178977e5a1f9SBarry Smith   Collective
179077e5a1f9SBarry Smith 
179177e5a1f9SBarry Smith   Input Parameter:
179277e5a1f9SBarry Smith . snes - the `SNES` object
179377e5a1f9SBarry Smith 
179477e5a1f9SBarry Smith   Level: developer
179577e5a1f9SBarry Smith 
179677e5a1f9SBarry Smith   Developer Note:
179777e5a1f9SBarry Smith   This is called by all the `SNESCreate_XXX()` routines.
179877e5a1f9SBarry Smith 
179977e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`,
180077e5a1f9SBarry Smith           `PetscObjectParameterSetDefault()`
180177e5a1f9SBarry Smith @*/
180277e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes)
180377e5a1f9SBarry Smith {
180477e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_its, 50);
180577e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_funcs, 10000);
180677e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
180777e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50);
180877e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
180977e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, divtol, 1.e4);
181077e5a1f9SBarry Smith   return PETSC_SUCCESS;
181177e5a1f9SBarry Smith }
181277e5a1f9SBarry Smith 
181377e5a1f9SBarry Smith /*@
1814dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
18159b94acceSBarry Smith 
1816d083f849SBarry Smith   Collective
1817c7afd0dbSLois Curfman McInnes 
1818f6dfbefdSBarry Smith   Input Parameter:
1819906ed7ccSBarry Smith . comm - MPI communicator
18209b94acceSBarry Smith 
18219b94acceSBarry Smith   Output Parameter:
182220f4b53cSBarry Smith . outsnes - the new `SNES` context
18239b94acceSBarry Smith 
1824c7afd0dbSLois Curfman McInnes   Options Database Keys:
18257addb90fSBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner
18267addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()`
1827dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1828c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1829c1f60f51SBarry Smith 
183036851e7fSLois Curfman McInnes   Level: beginner
183136851e7fSLois Curfman McInnes 
183295452b02SPatrick Sanan   Developer Notes:
1833f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1834efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1835f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1836f6dfbefdSBarry Smith   in `SNESView()`.
1837efd4aadfSBarry Smith 
1838f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1839f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1840f6dfbefdSBarry Smith 
18417addb90fSBarry Smith   `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed.
1842efd4aadfSBarry Smith 
1843e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
18449b94acceSBarry Smith @*/
1845d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1846d71ae5a4SJacob Faibussowitsch {
18479b94acceSBarry Smith   SNES       snes;
1848fa9f3622SBarry Smith   SNESKSPEW *kctx;
184937fcc0dbSBarry Smith 
18503a40ed3dSBarry Smith   PetscFunctionBegin;
18514f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
18529566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
18538ba1e511SMatthew Knepley 
18549566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
18558d359177SBarry Smith   snes->ops->converged = SNESConvergedDefault;
18562c155ee1SBarry Smith   snes->usesksp        = PETSC_TRUE;
18579b94acceSBarry Smith   snes->norm           = 0.0;
1858c1e67a49SFande Kong   snes->xnorm          = 0.0;
1859c1e67a49SFande Kong   snes->ynorm          = 0.0;
1860365a6726SPeter Brune   snes->normschedule   = SNES_NORM_ALWAYS;
18616c67d002SPeter Brune   snes->functype       = SNES_FUNCTION_DEFAULT;
1862b4874afaSBarry Smith   snes->ttol           = 0.0;
186377e5a1f9SBarry Smith 
1864e37c518bSBarry Smith   snes->rnorm0               = 0;
18659b94acceSBarry Smith   snes->nfuncs               = 0;
186650ffb88aSMatthew Knepley   snes->numFailures          = 0;
186750ffb88aSMatthew Knepley   snes->maxFailures          = 1;
18687a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1869e35cf81dSBarry Smith   snes->lagjacobian          = 1;
187037ec4e1aSPeter Brune   snes->jac_iter             = 0;
187137ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1872a8054027SBarry Smith   snes->lagpreconditioner    = 1;
187337ec4e1aSPeter Brune   snes->pre_iter             = 0;
187437ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1875639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1876c4421ceaSFande Kong   snes->numberreasonviews    = 0;
18779e5d0892SLisandro Dalcin   snes->data                 = NULL;
18784dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1879186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
18806f24a144SLois Curfman McInnes   snes->nwork                = 0;
18819e5d0892SLisandro Dalcin   snes->work                 = NULL;
188258c9b817SLisandro Dalcin   snes->nvwork               = 0;
18839e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1884758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1885758f92a0SBarry Smith   snes->conv_hist_max        = 0;
18860298fd71SBarry Smith   snes->conv_hist            = NULL;
18870298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1888758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1889971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1890e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1891184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1892efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1893b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1894c40d0f55SPeter Brune 
1895d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1896d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1897d8f46077SPeter Brune   snes->mf_version  = 1;
1898d8f46077SPeter Brune 
18993d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
19003d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
19013d4c4710SBarry Smith 
1902349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
190376bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1904349187a7SBarry Smith 
19054fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
19064fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
19074fc747eaSLawrence Mitchell 
19089b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
19094dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1910f5af7f23SKarl Rupp 
1911835f2295SStefano Zampini   snes->kspconvctx  = kctx;
19129b94acceSBarry Smith   kctx->version     = 2;
19130f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
19149b94acceSBarry Smith                              this was too large for some test cases */
191575567043SBarry Smith   kctx->rtol_last   = 0.0;
19160f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
19179b94acceSBarry Smith   kctx->gamma       = 1.0;
19180f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
191971f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
19200f0abf79SStefano Zampini   kctx->threshold   = 0.1;
192175567043SBarry Smith   kctx->lresid_last = 0.0;
192275567043SBarry Smith   kctx->norm_last   = 0.0;
19239b94acceSBarry Smith 
19240f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
19250f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
19260f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
19270f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
19280f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
19290f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
19300f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
19310f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
19320f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
19330f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
19340f0abf79SStefano Zampini 
1935b50c806fSBarry Smith   PetscCall(SNESParametersInitialize(snes));
19369b94acceSBarry Smith   *outsnes = snes;
19373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19389b94acceSBarry Smith }
19399b94acceSBarry Smith 
19409b94acceSBarry Smith /*@C
19419b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1942f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
19439b94acceSBarry Smith   equations.
19449b94acceSBarry Smith 
1945c3339decSBarry Smith   Logically Collective
1946fee21e36SBarry Smith 
1947c7afd0dbSLois Curfman McInnes   Input Parameters:
1948f6dfbefdSBarry Smith + snes - the `SNES` context
1949dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
19508434afd1SBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunctionFn`
1951c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1952dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
19539b94acceSBarry Smith 
195436851e7fSLois Curfman McInnes   Level: beginner
195536851e7fSLois Curfman McInnes 
19568434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
19579b94acceSBarry Smith @*/
19588434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx)
1959d71ae5a4SJacob Faibussowitsch {
19606cab3a1bSJed Brown   DM dm;
19616cab3a1bSJed Brown 
19623a40ed3dSBarry Smith   PetscFunctionBegin;
19630700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1964d2a683ecSLisandro Dalcin   if (r) {
1965d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1966d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
19679566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
19689566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
196985385478SLisandro Dalcin     snes->vec_func = r;
1970d2a683ecSLisandro Dalcin   }
19719566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
19729566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
197348a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
19743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19759b94acceSBarry Smith }
19769b94acceSBarry Smith 
1977e4ed7901SPeter Brune /*@C
19780b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1979e4ed7901SPeter Brune 
1980c3339decSBarry Smith   Logically Collective
1981e4ed7901SPeter Brune 
1982e4ed7901SPeter Brune   Input Parameters:
1983f6dfbefdSBarry Smith + snes - the `SNES` context
1984e4ed7901SPeter Brune - f    - vector to store function value
1985e4ed7901SPeter Brune 
1986dc4c0fb0SBarry Smith   Level: developer
1987dc4c0fb0SBarry Smith 
1988e4ed7901SPeter Brune   Notes:
1989e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1990e4ed7901SPeter Brune 
1991f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1992e4ed7901SPeter Brune 
19931cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1994e4ed7901SPeter Brune @*/
1995d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1996d71ae5a4SJacob Faibussowitsch {
1997e4ed7901SPeter Brune   Vec vec_func;
1998e4ed7901SPeter Brune 
1999e4ed7901SPeter Brune   PetscFunctionBegin;
2000e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2001e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
2002e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
2003efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
2004902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
20053ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2006902f982fSPeter Brune   }
20079566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
20089566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
2009f5af7f23SKarl Rupp 
2010217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
20113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2012e4ed7901SPeter Brune }
2013e4ed7901SPeter Brune 
2014534ebe21SPeter Brune /*@
2015f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
2016f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
2017534ebe21SPeter Brune 
2018c3339decSBarry Smith   Logically Collective
2019534ebe21SPeter Brune 
2020534ebe21SPeter Brune   Input Parameters:
2021f6dfbefdSBarry Smith + snes         - the `SNES` context
2022365a6726SPeter Brune - normschedule - the frequency of norm computation
2023534ebe21SPeter Brune 
2024517f1916SMatthew G. Knepley   Options Database Key:
202567b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
2026517f1916SMatthew G. Knepley 
2027dc4c0fb0SBarry Smith   Level: advanced
2028dc4c0fb0SBarry Smith 
2029534ebe21SPeter Brune   Notes:
2030f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
2031534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
2032534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
2033f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
2034534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
2035534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
2036534ebe21SPeter Brune   their solution.
2037534ebe21SPeter Brune 
2038e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
2039534ebe21SPeter Brune @*/
2040d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
2041d71ae5a4SJacob Faibussowitsch {
2042534ebe21SPeter Brune   PetscFunctionBegin;
2043534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2044365a6726SPeter Brune   snes->normschedule = normschedule;
20453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2046534ebe21SPeter Brune }
2047534ebe21SPeter Brune 
2048534ebe21SPeter Brune /*@
2049f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
2050f6dfbefdSBarry Smith   of the `SNES` method.
2051534ebe21SPeter Brune 
2052c3339decSBarry Smith   Logically Collective
2053534ebe21SPeter Brune 
2054534ebe21SPeter Brune   Input Parameters:
2055f6dfbefdSBarry Smith + snes         - the `SNES` context
2056365a6726SPeter Brune - normschedule - the type of the norm used
2057534ebe21SPeter Brune 
2058534ebe21SPeter Brune   Level: advanced
2059534ebe21SPeter Brune 
20601cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2061534ebe21SPeter Brune @*/
2062d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
2063d71ae5a4SJacob Faibussowitsch {
2064534ebe21SPeter Brune   PetscFunctionBegin;
2065534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2066365a6726SPeter Brune   *normschedule = snes->normschedule;
20673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2068534ebe21SPeter Brune }
2069534ebe21SPeter Brune 
2070c5ce4427SMatthew G. Knepley /*@
2071c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
2072c5ce4427SMatthew G. Knepley 
2073c3339decSBarry Smith   Logically Collective
2074c5ce4427SMatthew G. Knepley 
2075c5ce4427SMatthew G. Knepley   Input Parameters:
2076f6dfbefdSBarry Smith + snes - the `SNES` context
2077f6dfbefdSBarry Smith - norm - the value of the norm
2078c5ce4427SMatthew G. Knepley 
2079c5ce4427SMatthew G. Knepley   Level: developer
2080c5ce4427SMatthew G. Knepley 
20811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2082c5ce4427SMatthew G. Knepley @*/
2083d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
2084d71ae5a4SJacob Faibussowitsch {
2085c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2086c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2087c5ce4427SMatthew G. Knepley   snes->norm = norm;
20883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2089c5ce4427SMatthew G. Knepley }
2090c5ce4427SMatthew G. Knepley 
2091c5ce4427SMatthew G. Knepley /*@
2092c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
2093c5ce4427SMatthew G. Knepley 
2094c5ce4427SMatthew G. Knepley   Not Collective
2095c5ce4427SMatthew G. Knepley 
2096c5ce4427SMatthew G. Knepley   Input Parameter:
2097f6dfbefdSBarry Smith . snes - the `SNES` context
2098c5ce4427SMatthew G. Knepley 
2099c5ce4427SMatthew G. Knepley   Output Parameter:
2100c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2101c5ce4427SMatthew G. Knepley 
2102c5ce4427SMatthew G. Knepley   Level: developer
2103c5ce4427SMatthew G. Knepley 
21041cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2105c5ce4427SMatthew G. Knepley @*/
2106d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2107d71ae5a4SJacob Faibussowitsch {
2108c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2109c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21104f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2111c5ce4427SMatthew G. Knepley   *norm = snes->norm;
21123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2113c5ce4427SMatthew G. Knepley }
2114c5ce4427SMatthew G. Knepley 
2115c1e67a49SFande Kong /*@
2116f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2117c1e67a49SFande Kong 
2118c1e67a49SFande Kong   Not Collective
2119c1e67a49SFande Kong 
2120c1e67a49SFande Kong   Input Parameter:
2121f6dfbefdSBarry Smith . snes - the `SNES` context
2122c1e67a49SFande Kong 
2123c1e67a49SFande Kong   Output Parameter:
2124c1e67a49SFande Kong . ynorm - the last computed update norm
2125c1e67a49SFande Kong 
2126c1e67a49SFande Kong   Level: developer
2127c1e67a49SFande Kong 
2128f6dfbefdSBarry Smith   Note:
2129f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2130f6dfbefdSBarry Smith 
21311cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2132c1e67a49SFande Kong @*/
2133d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2134d71ae5a4SJacob Faibussowitsch {
2135c1e67a49SFande Kong   PetscFunctionBegin;
2136c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21374f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2138c1e67a49SFande Kong   *ynorm = snes->ynorm;
21393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2140c1e67a49SFande Kong }
2141c1e67a49SFande Kong 
2142c1e67a49SFande Kong /*@
21434591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2144c1e67a49SFande Kong 
2145c1e67a49SFande Kong   Not Collective
2146c1e67a49SFande Kong 
2147c1e67a49SFande Kong   Input Parameter:
2148f6dfbefdSBarry Smith . snes - the `SNES` context
2149c1e67a49SFande Kong 
2150c1e67a49SFande Kong   Output Parameter:
2151c1e67a49SFande Kong . xnorm - the last computed solution norm
2152c1e67a49SFande Kong 
2153c1e67a49SFande Kong   Level: developer
2154c1e67a49SFande Kong 
21551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2156c1e67a49SFande Kong @*/
2157d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2158d71ae5a4SJacob Faibussowitsch {
2159c1e67a49SFande Kong   PetscFunctionBegin;
2160c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21614f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2162c1e67a49SFande Kong   *xnorm = snes->xnorm;
21633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2164c1e67a49SFande Kong }
2165c1e67a49SFande Kong 
2166cc4c1da9SBarry Smith /*@
2167f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2168f6dfbefdSBarry Smith   of the `SNES` method.
216947073ea2SPeter Brune 
2170c3339decSBarry Smith   Logically Collective
217147073ea2SPeter Brune 
217247073ea2SPeter Brune   Input Parameters:
2173f6dfbefdSBarry Smith + snes - the `SNES` context
2174f6dfbefdSBarry Smith - type - the function type
217547073ea2SPeter Brune 
217647073ea2SPeter Brune   Level: developer
217747073ea2SPeter Brune 
2178420bcc1bSBarry Smith   Values of the function type\:
2179f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT`          - the default for the given `SNESType`
2180f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2181f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED`   - a transformation of the function provided with `SNESSetFunction()`
2182f6dfbefdSBarry Smith 
2183420bcc1bSBarry Smith   Note:
2184f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2185f6dfbefdSBarry Smith 
21861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
218747073ea2SPeter Brune @*/
2188d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2189d71ae5a4SJacob Faibussowitsch {
219047073ea2SPeter Brune   PetscFunctionBegin;
219147073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
219247073ea2SPeter Brune   snes->functype = type;
21933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
219447073ea2SPeter Brune }
219547073ea2SPeter Brune 
2196cc4c1da9SBarry Smith /*@
2197f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
219847073ea2SPeter Brune   of the SNES method.
219947073ea2SPeter Brune 
2200c3339decSBarry Smith   Logically Collective
220147073ea2SPeter Brune 
220247073ea2SPeter Brune   Input Parameters:
2203f6dfbefdSBarry Smith + snes - the `SNES` context
2204f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
220547073ea2SPeter Brune 
220647073ea2SPeter Brune   Level: advanced
220747073ea2SPeter Brune 
22081cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
220947073ea2SPeter Brune @*/
2210d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2211d71ae5a4SJacob Faibussowitsch {
221247073ea2SPeter Brune   PetscFunctionBegin;
221347073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
221447073ea2SPeter Brune   *type = snes->functype;
22153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2216534ebe21SPeter Brune }
2217534ebe21SPeter Brune 
2218c79ef259SPeter Brune /*@C
2219be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2220c79ef259SPeter Brune   use with composed nonlinear solvers.
2221c79ef259SPeter Brune 
2222c79ef259SPeter Brune   Input Parameters:
22239bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
22248434afd1SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
222577e5a1f9SBarry Smith - ctx  - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`)
2226c79ef259SPeter Brune 
2227dc4c0fb0SBarry Smith   Level: intermediate
2228dc4c0fb0SBarry Smith 
2229f6dfbefdSBarry Smith   Note:
2230f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2231f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2232c79ef259SPeter Brune 
22338434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2234c79ef259SPeter Brune @*/
22358434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx)
2236d71ae5a4SJacob Faibussowitsch {
22376cab3a1bSJed Brown   DM dm;
22386cab3a1bSJed Brown 
2239646217ecSPeter Brune   PetscFunctionBegin;
22406cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22419566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22429566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
22433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2244646217ecSPeter Brune }
2245646217ecSPeter Brune 
2246bbc1464cSBarry Smith /*
2247bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2248bbc1464cSBarry Smith    changed during the KSPSolve()
2249bbc1464cSBarry Smith */
2250d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2251d71ae5a4SJacob Faibussowitsch {
2252bbc1464cSBarry Smith   DM     dm;
2253bbc1464cSBarry Smith   DMSNES sdm;
2254bbc1464cSBarry Smith 
2255bbc1464cSBarry Smith   PetscFunctionBegin;
22569566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22579566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2258bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2259bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2260792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22619566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
22620df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2263ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2264792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22659566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2266bbc1464cSBarry Smith   } else {
2267792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22689566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2269bbc1464cSBarry Smith   }
22703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2271bbc1464cSBarry Smith }
2272bbc1464cSBarry Smith 
2273d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2274d71ae5a4SJacob Faibussowitsch {
2275e03ab78fSPeter Brune   DM     dm;
2276942e3340SBarry Smith   DMSNES sdm;
22776cab3a1bSJed Brown 
22788b0a5094SBarry Smith   PetscFunctionBegin;
22799566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22809566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22818b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2282bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2283792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22849566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2285792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22869566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2287bbc1464cSBarry Smith   } else {
2288792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22899566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2290bbc1464cSBarry Smith   }
22913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22928b0a5094SBarry Smith }
22938b0a5094SBarry Smith 
2294d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2295d71ae5a4SJacob Faibussowitsch {
22968b0a5094SBarry Smith   PetscFunctionBegin;
2297e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2298bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22999566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
23009566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
23013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23028b0a5094SBarry Smith }
23038b0a5094SBarry Smith 
23048b0a5094SBarry Smith /*@C
23051d27aa22SBarry Smith   SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
23068b0a5094SBarry Smith 
2307c3339decSBarry Smith   Logically Collective
23088b0a5094SBarry Smith 
23098b0a5094SBarry Smith   Input Parameters:
2310f6dfbefdSBarry Smith + snes - the `SNES` context
2311dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
23128434afd1SBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
231326a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed
2314dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
23158434afd1SBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2316dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2317dc4c0fb0SBarry Smith 
2318dc4c0fb0SBarry Smith   Level: intermediate
23198b0a5094SBarry Smith 
23208b0a5094SBarry Smith   Notes:
232126a11704SBarry Smith   It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use
2322f450aa47SBarry 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.
2323f450aa47SBarry Smith 
2324f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
23258b0a5094SBarry Smith 
23261d27aa22SBarry 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}$.
23271d27aa22SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
23288b0a5094SBarry Smith 
232926a11704SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner.
23308b0a5094SBarry Smith 
23310d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
23321d27aa22SBarry Smith   the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
23338b0a5094SBarry Smith 
23348b0a5094SBarry 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
23351d27aa22SBarry 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
23361d27aa22SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
23378b0a5094SBarry Smith 
23381d27aa22SBarry 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
233926a11704SBarry Smith   $A(x^{n})$ is used to build the preconditioner
23406b7fb656SBarry Smith 
234115229ffcSPierre 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.
23426b7fb656SBarry Smith 
2343dc4c0fb0SBarry 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
234426a11704SBarry 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
234526a11704SBarry 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`.
2346aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2347bbc1464cSBarry Smith 
23489bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
23498434afd1SBarry Smith           `SNESFunctionFn`, `SNESJacobianFn`
23508b0a5094SBarry Smith @*/
23518434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
2352d71ae5a4SJacob Faibussowitsch {
2353e03ab78fSPeter Brune   DM dm;
2354e03ab78fSPeter Brune 
23558b0a5094SBarry Smith   PetscFunctionBegin;
23568b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23579566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23589566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
23599566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
23609566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
23619566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
23623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23638b0a5094SBarry Smith }
23648b0a5094SBarry Smith 
23657971a8bfSPeter Brune /*@C
23667971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
23677971a8bfSPeter Brune 
2368f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
23697971a8bfSPeter Brune 
23707971a8bfSPeter Brune   Input Parameter:
2371f6dfbefdSBarry Smith . snes - the `SNES` context
23727971a8bfSPeter Brune 
2373d8d19677SJose E. Roman   Output Parameters:
2374dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
23758434afd1SBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunctionFn`
2376dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2377dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
23788434afd1SBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFn`
2379dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
23807971a8bfSPeter Brune 
23817971a8bfSPeter Brune   Level: advanced
23827971a8bfSPeter Brune 
23838434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
23847971a8bfSPeter Brune @*/
23858434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
2386d71ae5a4SJacob Faibussowitsch {
23877971a8bfSPeter Brune   DM dm;
23887971a8bfSPeter Brune 
23897971a8bfSPeter Brune   PetscFunctionBegin;
23907971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23919566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23929566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23939566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23949566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23967971a8bfSPeter Brune }
23977971a8bfSPeter Brune 
2398d25893d9SBarry Smith /*@C
2399dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2400d25893d9SBarry Smith 
2401c3339decSBarry Smith   Logically Collective
2402d25893d9SBarry Smith 
2403d25893d9SBarry Smith   Input Parameters:
2404f6dfbefdSBarry Smith + snes - the `SNES` context
24058434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2406d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2407dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2408d25893d9SBarry Smith 
2409d25893d9SBarry Smith   Level: intermediate
2410d25893d9SBarry Smith 
24118434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2412d25893d9SBarry Smith @*/
24138434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx)
2414d71ae5a4SJacob Faibussowitsch {
2415d25893d9SBarry Smith   PetscFunctionBegin;
2416d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2417d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2418d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
24193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2420d25893d9SBarry Smith }
2421d25893d9SBarry Smith 
24221096aae1SMatthew Knepley /*@C
2423dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2424dd8e379bSPierre Jolivet   it assumes a zero right-hand side.
24251096aae1SMatthew Knepley 
2426c3339decSBarry Smith   Logically Collective
24271096aae1SMatthew Knepley 
24281096aae1SMatthew Knepley   Input Parameter:
2429f6dfbefdSBarry Smith . snes - the `SNES` context
24301096aae1SMatthew Knepley 
24311096aae1SMatthew Knepley   Output Parameter:
2432dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
24331096aae1SMatthew Knepley 
24341096aae1SMatthew Knepley   Level: intermediate
24351096aae1SMatthew Knepley 
24361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
24371096aae1SMatthew Knepley @*/
2438d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2439d71ae5a4SJacob Faibussowitsch {
24401096aae1SMatthew Knepley   PetscFunctionBegin;
24410700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24424f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
244385385478SLisandro Dalcin   *rhs = snes->vec_rhs;
24443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24451096aae1SMatthew Knepley }
24461096aae1SMatthew Knepley 
24479b94acceSBarry Smith /*@
2448f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
24499b94acceSBarry Smith 
2450c3339decSBarry Smith   Collective
2451c7afd0dbSLois Curfman McInnes 
24529b94acceSBarry Smith   Input Parameters:
2453f6dfbefdSBarry Smith + snes - the `SNES` context
2454c7afd0dbSLois Curfman McInnes - x    - input vector
24559b94acceSBarry Smith 
24569b94acceSBarry Smith   Output Parameter:
2457f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
24589b94acceSBarry Smith 
2459dc4c0fb0SBarry Smith   Level: developer
2460dc4c0fb0SBarry Smith 
246100677de2SStefano Zampini   Notes:
2462f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2463bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
246436851e7fSLois Curfman McInnes 
246500677de2SStefano Zampini   When solving for $F(x) = b$, this routine computes $y = F(x) - b$.
246600677de2SStefano Zampini 
24671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
24689b94acceSBarry Smith @*/
2469d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2470d71ae5a4SJacob Faibussowitsch {
24716cab3a1bSJed Brown   DM     dm;
2472942e3340SBarry Smith   DMSNES sdm;
24739b94acceSBarry Smith 
24743a40ed3dSBarry Smith   PetscFunctionBegin;
24750700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24760700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
24770700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2478c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2479c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2480e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2481184914b5SBarry Smith 
24829566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24839566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24840fdf79fbSJacob 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().");
248532f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
248648a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24879566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24888ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24898ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2490800f99ffSJeremy L Thompson     {
2491800f99ffSJeremy L Thompson       void           *ctx;
24928434afd1SBarry Smith       SNESFunctionFn *computefunction;
2493800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2494800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2495800f99ffSJeremy L Thompson     }
24969566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
249748a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24980fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24999566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
25000fdf79fbSJacob Faibussowitsch   }
25011baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2502ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2503422a814eSBarry Smith   /*
2504422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2505422a814eSBarry Smith      propagate the value to all processes
2506422a814eSBarry Smith   */
2507f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25099b94acceSBarry Smith }
25109b94acceSBarry Smith 
2511c79ef259SPeter Brune /*@
25120b4b7b1cSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`.
2513bbc1464cSBarry Smith 
2514c3339decSBarry Smith   Collective
2515bbc1464cSBarry Smith 
2516bbc1464cSBarry Smith   Input Parameters:
2517f6dfbefdSBarry Smith + snes - the `SNES` context
2518bbc1464cSBarry Smith - x    - input vector
2519bbc1464cSBarry Smith 
2520bbc1464cSBarry Smith   Output Parameter:
25210b4b7b1cSBarry Smith . y - output vector
2522bbc1464cSBarry Smith 
2523dc4c0fb0SBarry Smith   Level: developer
2524dc4c0fb0SBarry Smith 
2525bbc1464cSBarry Smith   Notes:
2526420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2527bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2528bbc1464cSBarry Smith 
2529dd8e379bSPierre Jolivet   Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2530f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2531dd8e379bSPierre 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.
2532bbc1464cSBarry Smith 
25330b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()`
2534bbc1464cSBarry Smith @*/
2535d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2536d71ae5a4SJacob Faibussowitsch {
2537bbc1464cSBarry Smith   DM     dm;
2538bbc1464cSBarry Smith   DMSNES sdm;
2539bbc1464cSBarry Smith 
2540bbc1464cSBarry Smith   PetscFunctionBegin;
2541bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2542bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2543bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2544bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2545bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2546e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2547bbc1464cSBarry Smith 
25489566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25499566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25509566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
25519566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2552bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2553bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2554792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
25559566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
25569566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2557bbc1464cSBarry Smith   snes->nfuncs++;
2558bbc1464cSBarry Smith   /*
2559bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2560bbc1464cSBarry Smith      propagate the value to all processes
2561bbc1464cSBarry Smith   */
2562f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2564bbc1464cSBarry Smith }
2565bbc1464cSBarry Smith 
2566bbc1464cSBarry Smith /*@
2567f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2568c79ef259SPeter Brune 
2569c3339decSBarry Smith   Collective
2570c79ef259SPeter Brune 
2571c79ef259SPeter Brune   Input Parameters:
2572f6dfbefdSBarry Smith + snes - the `SNES` context
2573c79ef259SPeter Brune . x    - input vector
2574c79ef259SPeter Brune - b    - rhs vector
2575c79ef259SPeter Brune 
2576c79ef259SPeter Brune   Output Parameter:
2577c79ef259SPeter Brune . x - new solution vector
2578c79ef259SPeter Brune 
2579dc4c0fb0SBarry Smith   Level: developer
2580dc4c0fb0SBarry Smith 
2581f6dfbefdSBarry Smith   Note:
2582f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2583c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2584c79ef259SPeter Brune   themselves.
2585c79ef259SPeter Brune 
25868434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2587c79ef259SPeter Brune @*/
2588d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2589d71ae5a4SJacob Faibussowitsch {
25906cab3a1bSJed Brown   DM     dm;
2591942e3340SBarry Smith   DMSNES sdm;
2592646217ecSPeter Brune 
2593646217ecSPeter Brune   PetscFunctionBegin;
2594646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2595064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2596064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2597064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2598064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2599e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
26009566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
26019566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
26029566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
26030fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
26049566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2605792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
26069566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
26079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
26083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2609646217ecSPeter Brune }
2610646217ecSPeter Brune 
2611494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2612494a190aSStefano Zampini {
2613494a190aSStefano Zampini   Vec          X;
2614494a190aSStefano Zampini   PetscScalar *g;
2615494a190aSStefano Zampini   PetscReal    f, f2;
2616494a190aSStefano Zampini   PetscInt     low, high, N, i;
2617494a190aSStefano Zampini   PetscBool    flg;
2618494a190aSStefano Zampini   PetscReal    h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2619494a190aSStefano Zampini 
2620494a190aSStefano Zampini   PetscFunctionBegin;
2621494a190aSStefano Zampini   PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2622494a190aSStefano Zampini   PetscCall(VecDuplicate(Xin, &X));
2623494a190aSStefano Zampini   PetscCall(VecCopy(Xin, X));
2624494a190aSStefano Zampini   PetscCall(VecGetSize(X, &N));
2625494a190aSStefano Zampini   PetscCall(VecGetOwnershipRange(X, &low, &high));
2626494a190aSStefano Zampini   PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2627494a190aSStefano Zampini   PetscCall(VecGetArray(G, &g));
2628494a190aSStefano Zampini   for (i = 0; i < N; i++) {
2629494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2630494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2631494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2632494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f));
2633494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2634494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2635494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2636494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f2));
2637494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2638494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2639494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2640494a190aSStefano Zampini     if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2641494a190aSStefano Zampini   }
2642494a190aSStefano Zampini   PetscCall(VecRestoreArray(G, &g));
2643494a190aSStefano Zampini   PetscCall(VecDestroy(&X));
2644494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2645494a190aSStefano Zampini }
2646494a190aSStefano Zampini 
2647494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2648494a190aSStefano Zampini {
2649494a190aSStefano Zampini   Vec               x, g1, g2, g3;
2650494a190aSStefano Zampini   PetscBool         complete_print = PETSC_FALSE, test = PETSC_FALSE;
2651494a190aSStefano Zampini   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2652494a190aSStefano Zampini   PetscScalar       dot;
2653494a190aSStefano Zampini   MPI_Comm          comm;
2654494a190aSStefano Zampini   PetscViewer       viewer, mviewer;
2655494a190aSStefano Zampini   PetscViewerFormat format;
2656494a190aSStefano Zampini   PetscInt          tabs;
2657494a190aSStefano Zampini   static PetscBool  directionsprinted = PETSC_FALSE;
26588434afd1SBarry Smith   SNESObjectiveFn  *objective;
2659494a190aSStefano Zampini 
2660494a190aSStefano Zampini   PetscFunctionBegin;
2661494a190aSStefano Zampini   PetscCall(SNESGetObjective(snes, &objective, NULL));
2662494a190aSStefano Zampini   if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2663494a190aSStefano Zampini 
2664494a190aSStefano Zampini   PetscObjectOptionsBegin((PetscObject)snes);
2665494a190aSStefano Zampini   PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test));
2666494a190aSStefano Zampini   PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2667494a190aSStefano Zampini   PetscOptionsEnd();
2668494a190aSStefano Zampini   if (!test) {
2669494a190aSStefano Zampini     if (complete_print) PetscCall(PetscViewerDestroy(&mviewer));
2670494a190aSStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
2671494a190aSStefano Zampini   }
2672494a190aSStefano Zampini 
2673494a190aSStefano Zampini   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2674494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2675494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2676494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2677494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Function -------------\n"));
2678494a190aSStefano Zampini   if (!complete_print && !directionsprinted) {
2679494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2680494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference function entries greater than <threshold>.\n"));
2681494a190aSStefano Zampini   }
2682494a190aSStefano Zampini   if (!directionsprinted) {
2683494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2684494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Function is probably correct.\n"));
2685494a190aSStefano Zampini     directionsprinted = PETSC_TRUE;
2686494a190aSStefano Zampini   }
2687494a190aSStefano Zampini   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2688494a190aSStefano Zampini 
2689494a190aSStefano Zampini   PetscCall(SNESGetSolution(snes, &x));
2690494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g1));
2691494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g2));
2692494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g3));
2693494a190aSStefano Zampini   PetscCall(SNESComputeFunction(snes, x, g1));
2694494a190aSStefano Zampini   PetscCall(SNESComputeFunction_FD(snes, x, g2));
2695494a190aSStefano Zampini 
2696494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2697494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2698494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2699494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2700494a190aSStefano Zampini   PetscCall(VecDot(g1, g2, &dot));
2701494a190aSStefano Zampini   PetscCall(VecCopy(g1, g3));
2702494a190aSStefano Zampini   PetscCall(VecAXPY(g3, -1.0, g2));
2703494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2704494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2705494a190aSStefano 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))));
2706494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2707494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2708494a190aSStefano Zampini 
2709494a190aSStefano Zampini   if (complete_print) {
2710494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded function ----------\n"));
2711494a190aSStefano Zampini     PetscCall(VecView(g1, mviewer));
2712494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference function ----------\n"));
2713494a190aSStefano Zampini     PetscCall(VecView(g2, mviewer));
2714494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference function ----------\n"));
2715494a190aSStefano Zampini     PetscCall(VecView(g3, mviewer));
2716494a190aSStefano Zampini   }
2717494a190aSStefano Zampini   PetscCall(VecDestroy(&g1));
2718494a190aSStefano Zampini   PetscCall(VecDestroy(&g2));
2719494a190aSStefano Zampini   PetscCall(VecDestroy(&g3));
2720494a190aSStefano Zampini 
2721494a190aSStefano Zampini   if (complete_print) {
2722494a190aSStefano Zampini     PetscCall(PetscViewerPopFormat(mviewer));
2723494a190aSStefano Zampini     PetscCall(PetscViewerDestroy(&mviewer));
2724494a190aSStefano Zampini   }
2725494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2726494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2727494a190aSStefano Zampini }
2728494a190aSStefano Zampini 
2729d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2730d71ae5a4SJacob Faibussowitsch {
273112837594SBarry Smith   Mat               A, B, C, D, jacobian;
27324df93895SStefano Zampini   Vec               x = snes->vec_sol, f;
2733e885f1abSBarry Smith   PetscReal         nrm, gnorm;
273481e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
27350e276705SLisandro Dalcin   MatType           mattype;
2736e885f1abSBarry Smith   PetscInt          m, n, M, N;
2737e885f1abSBarry Smith   void             *functx;
27382cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
27393325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2740e885f1abSBarry Smith   MPI_Comm          comm;
2741e885f1abSBarry Smith   PetscInt          tabs;
274212837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
27433325ff46SBarry Smith   PetscViewerFormat format;
2744e885f1abSBarry Smith 
2745e885f1abSBarry Smith   PetscFunctionBegin;
2746d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
27479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
27489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
27499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
27504ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
27519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
27529566063dSJacob 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));
2753d0609cedSBarry Smith   PetscOptionsEnd();
27543ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2755e885f1abSBarry Smith 
27569566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
27579566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
27589566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
27599566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
27609566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
276112837594SBarry Smith   if (!complete_print && !directionsprinted) {
27629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
27639566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
276412837594SBarry Smith   }
276512837594SBarry Smith   if (!directionsprinted) {
27669566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
27679566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
276812837594SBarry Smith     directionsprinted = PETSC_TRUE;
2769e885f1abSBarry Smith   }
27701baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2771e885f1abSBarry Smith 
27729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
277312837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
277412837594SBarry Smith   else jacobian = snes->jacobian_pre;
277512837594SBarry Smith 
27764df93895SStefano Zampini   if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
27774df93895SStefano Zampini   else PetscCall(PetscObjectReference((PetscObject)x));
27789566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &f));
27794df93895SStefano Zampini 
2780a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
27819566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
27829566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
27839566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
278412837594SBarry Smith   while (jacobian) {
27852cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
27862cd624f9SStefano Zampini 
27872cd624f9SStefano Zampini     if (istranspose) {
27889566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
27892cd624f9SStefano Zampini       Jsave    = jacobian;
27902cd624f9SStefano Zampini       jacobian = JT;
27912cd624f9SStefano Zampini     }
27929566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
279312837594SBarry Smith     if (flg) {
279412837594SBarry Smith       A = jacobian;
27959566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
279612837594SBarry Smith     } else {
27979566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
279812837594SBarry Smith     }
2799e885f1abSBarry Smith 
28009566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
28019566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
28029566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
28039566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
28049566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
28059566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
28069566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
28079566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
28089566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2809e885f1abSBarry Smith 
28109566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
28119566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
281212837594SBarry Smith 
28139566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
28149566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28159566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
28169566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
28179566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
281812837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
28199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
282012837594SBarry Smith 
2821e885f1abSBarry Smith     if (complete_print) {
28229566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
28239566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
28249566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
28259566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2826e885f1abSBarry Smith     }
2827e885f1abSBarry Smith 
2828df10fb39SFande Kong     if (threshold_print || complete_print) {
2829e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2830e885f1abSBarry Smith       PetscScalar       *cvals;
2831e885f1abSBarry Smith       const PetscInt    *bcols;
2832e885f1abSBarry Smith       const PetscScalar *bvals;
2833e885f1abSBarry Smith 
28349566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
28359566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
28369566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
28379566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
28389566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
28399566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
28400e276705SLisandro Dalcin 
28419566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28429566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2843e885f1abSBarry Smith 
2844e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
28459566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
28469566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2847e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
284823a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2849e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2850e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2851e885f1abSBarry Smith             cncols += 1;
2852e885f1abSBarry Smith           }
2853e885f1abSBarry Smith         }
285448a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
28559566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
28569566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2857e885f1abSBarry Smith       }
28589566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
28599566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
28609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
28619566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
28629566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2863e885f1abSBarry Smith     }
28649566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
28659566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
28669566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
28672cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
286812837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
286912837594SBarry Smith       jacobian = snes->jacobian_pre;
28709566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
28719371c9d4SSatish Balay     } else jacobian = NULL;
287212837594SBarry Smith   }
28739566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
28741baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2875648c30bcSBarry Smith   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
28769566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
28773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2878e885f1abSBarry Smith }
2879e885f1abSBarry Smith 
288062fef451SLois Curfman McInnes /*@
2881f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
288262fef451SLois Curfman McInnes 
2883c3339decSBarry Smith   Collective
2884c7afd0dbSLois Curfman McInnes 
288562fef451SLois Curfman McInnes   Input Parameters:
2886f6dfbefdSBarry Smith + snes - the `SNES` context
2887e4094ef1SJacob Faibussowitsch - X    - input vector
288862fef451SLois Curfman McInnes 
288962fef451SLois Curfman McInnes   Output Parameters:
2890c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2891420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2892fee21e36SBarry Smith 
2893e35cf81dSBarry Smith   Options Database Keys:
289467b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
289567b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2896455a5933SJed 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.
2897455a5933SJed 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
2898693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2899693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2900693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
29017addb90fSBarry Smith . -snes_compare_operator                   - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner
290294d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2903a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2904c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2905dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2906dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2907a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2908a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2909c01495d3SJed Brown 
2910dc4c0fb0SBarry Smith   Level: developer
2911dc4c0fb0SBarry Smith 
2912f6dfbefdSBarry Smith   Note:
291362fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
291462fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
291562fef451SLois Curfman McInnes 
2916420bcc1bSBarry Smith   Developer Note:
2917dc4c0fb0SBarry 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
2918420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2919e885f1abSBarry Smith 
29201cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
292162fef451SLois Curfman McInnes @*/
2922d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2923d71ae5a4SJacob Faibussowitsch {
2924ace3abfcSBarry Smith   PetscBool flag;
29256cab3a1bSJed Brown   DM        dm;
2926942e3340SBarry Smith   DMSNES    sdm;
2927e0e3a89bSBarry Smith   KSP       ksp;
29283a40ed3dSBarry Smith 
29293a40ed3dSBarry Smith   PetscFunctionBegin;
29300700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
29310700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2932c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2933e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
29349566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
29359566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
29363232da50SPeter Brune 
293701c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2938fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2939fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2940f5af7f23SKarl Rupp 
29419566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2942fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
29439566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
29449566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2945ebd3b9afSBarry Smith     if (flag) {
29469566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29479566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2948ebd3b9afSBarry Smith     }
29493ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
295037ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
295163a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
29529566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2953ebd3b9afSBarry Smith     if (flag) {
29549566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29559566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2956ebd3b9afSBarry Smith     }
29573ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2958e35cf81dSBarry Smith   }
2959efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
29609566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29619566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
29623ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2963d728fb7dSPeter Brune   }
2964e35cf81dSBarry Smith 
29659566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
29669566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2967800f99ffSJeremy L Thompson   {
2968800f99ffSJeremy L Thompson     void           *ctx;
29698434afd1SBarry Smith     SNESJacobianFn *J;
2970800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2971800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2972800f99ffSJeremy L Thompson   }
29739566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
29749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
297528d58a37SPierre Jolivet 
29767addb90fSBarry Smith   /* attach latest linearization point to the matrix used to construct the preconditioner */
29779566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2978a8054027SBarry Smith 
2979e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
29809566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
29813b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
29829566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
29839566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
29843b4f5425SBarry Smith     snes->lagpreconditioner = -1;
29853b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
29869566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
29879566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
298837ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
298963a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
29909566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2991d1e9a80fSBarry Smith   } else {
29929566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
29939566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2994a8054027SBarry Smith   }
2995a8054027SBarry Smith 
29964df93895SStefano Zampini   /* monkey business to allow testing Jacobians in multilevel solvers.
29974df93895SStefano Zampini      This is needed because the SNESTestXXX interface does not accept vectors and matrices */
29984df93895SStefano Zampini   {
29994df93895SStefano Zampini     Vec xsave            = snes->vec_sol;
30004df93895SStefano Zampini     Mat jacobiansave     = snes->jacobian;
30014df93895SStefano Zampini     Mat jacobian_presave = snes->jacobian_pre;
30024df93895SStefano Zampini 
30034df93895SStefano Zampini     snes->vec_sol      = X;
30044df93895SStefano Zampini     snes->jacobian     = A;
30054df93895SStefano Zampini     snes->jacobian_pre = B;
3006494a190aSStefano Zampini     PetscCall(SNESTestFunction(snes));
30079566063dSJacob Faibussowitsch     PetscCall(SNESTestJacobian(snes));
3008494a190aSStefano Zampini 
30094df93895SStefano Zampini     snes->vec_sol      = xsave;
30104df93895SStefano Zampini     snes->jacobian     = jacobiansave;
30114df93895SStefano Zampini     snes->jacobian_pre = jacobian_presave;
30124df93895SStefano Zampini   }
30134df93895SStefano Zampini 
3014693365a8SJed Brown   {
3015693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
3016648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
3017648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
3018648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
3019648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
3020693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
30210298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
3022693365a8SJed Brown       PetscViewer vdraw, vstdout;
30236b3a5b13SJed Brown       PetscBool   flg;
3024693365a8SJed Brown       if (flag_operator) {
30259566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
3026693365a8SJed Brown         Bexp = Bexp_mine;
3027693365a8SJed Brown       } else {
30287addb90fSBarry Smith         /* See if the matrix used to construct the preconditioner can be viewed and added directly */
30299566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
303094ab13aaSBarry Smith         if (flg) Bexp = B;
3031693365a8SJed Brown         else {
3032693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
30339566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
3034693365a8SJed Brown           Bexp = Bexp_mine;
3035693365a8SJed Brown         }
3036693365a8SJed Brown       }
30379566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
30389566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
30399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
3040693365a8SJed Brown       if (flag_draw || flag_contour) {
30419566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30429566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30430298fd71SBarry Smith       } else vdraw = NULL;
30449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
30459566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
30469566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
30479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
30489566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
30499566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
30509566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
30519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
30529566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
3053693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
30549566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30559566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
30569566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
3057693365a8SJed Brown       }
30589566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30599566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
30609566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
30619566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
3062693365a8SJed Brown     }
3063693365a8SJed Brown   }
30644c30e9fbSJed Brown   {
30656719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
30666719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
3067648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
3068648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
3069648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
3070648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
3071648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
307227b0f280SBarry Smith     if (flag_threshold) {
30739566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
30749566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
307527b0f280SBarry Smith     }
30766719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
30774c30e9fbSJed Brown       Mat             Bfd;
30784c30e9fbSJed Brown       PetscViewer     vdraw, vstdout;
3079335efc43SPeter Brune       MatColoring     coloring;
30804c30e9fbSJed Brown       ISColoring      iscoloring;
30814c30e9fbSJed Brown       MatFDColoring   matfdcoloring;
30828434afd1SBarry Smith       SNESFunctionFn *func;
30834c30e9fbSJed Brown       void           *funcctx;
30846719d8e4SJed Brown       PetscReal       norm1, norm2, normmax;
30854c30e9fbSJed Brown 
30869566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
30879566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
30889566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
30899566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
30909566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
30919566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
30929566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
30939566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30949566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
30959566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
30964c30e9fbSJed Brown 
30974c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
30989566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
30999566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))func, funcctx));
31009566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
31019566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
31029566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
31039566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
31049566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
31054c30e9fbSJed Brown 
31069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
31074c30e9fbSJed Brown       if (flag_draw || flag_contour) {
31089566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
31099566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31100298fd71SBarry Smith       } else vdraw = NULL;
31119566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
31129566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
31139566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
31149566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
31159566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31169566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
31179566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
31189566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
31199566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
31209566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
31219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
31229566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31234c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
31249566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31259566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
31269566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
31274c30e9fbSJed Brown       }
31289566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
31296719d8e4SJed Brown 
31306719d8e4SJed Brown       if (flag_threshold) {
31316719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
31329566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
31339566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
31346719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
31356719d8e4SJed Brown           const PetscScalar *ba, *ca;
31366719d8e4SJed Brown           const PetscInt    *bj, *cj;
31376719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
31386719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
31399566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
31409566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
31415f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
31426719d8e4SJed Brown           for (j = 0; j < bn; j++) {
31436719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
31446719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
31456719d8e4SJed Brown               maxentrycol = bj[j];
31466719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
31476719d8e4SJed Brown             }
31486719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
31496719d8e4SJed Brown               maxdiffcol = bj[j];
31506719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
31516719d8e4SJed Brown             }
31526719d8e4SJed Brown             if (rdiff > maxrdiff) {
31536719d8e4SJed Brown               maxrdiffcol = bj[j];
31546719d8e4SJed Brown               maxrdiff    = rdiff;
31556719d8e4SJed Brown             }
31566719d8e4SJed Brown           }
31576719d8e4SJed Brown           if (maxrdiff > 1) {
315863a3b9bcSJacob 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));
31596719d8e4SJed Brown             for (j = 0; j < bn; j++) {
31606719d8e4SJed Brown               PetscReal rdiff;
31616719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
316248a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
31636719d8e4SJed Brown             }
316463a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
31656719d8e4SJed Brown           }
31669566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
31679566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
31686719d8e4SJed Brown         }
31696719d8e4SJed Brown       }
31709566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
31719566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
31724c30e9fbSJed Brown     }
31734c30e9fbSJed Brown   }
31743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31759b94acceSBarry Smith }
31769b94acceSBarry Smith 
31779b94acceSBarry Smith /*@C
31789b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3179044dda88SLois Curfman McInnes   location to store the matrix.
31809b94acceSBarry Smith 
3181c3339decSBarry Smith   Logically Collective
3182c7afd0dbSLois Curfman McInnes 
31839b94acceSBarry Smith   Input Parameters:
3184f6dfbefdSBarry Smith + snes - the `SNES` context
3185e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3186dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
31878434afd1SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3188c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3189dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3190dc4c0fb0SBarry Smith 
3191dc4c0fb0SBarry Smith   Level: beginner
31929b94acceSBarry Smith 
31939b94acceSBarry Smith   Notes:
3194dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
319516913363SBarry Smith   each matrix.
319616913363SBarry Smith 
3197dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3198dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3199895c21f2SBarry Smith 
3200dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3201f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3202a8a26c1eSJed Brown 
3203c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3204f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3205c3cc8fd1SJed Brown 
32061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
32078434afd1SBarry Smith           `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
32089b94acceSBarry Smith @*/
32098434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
3210d71ae5a4SJacob Faibussowitsch {
32116cab3a1bSJed Brown   DM dm;
32123a7fca6bSBarry Smith 
32133a40ed3dSBarry Smith   PetscFunctionBegin;
32140700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3215e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3216e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3217e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3218e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
32199566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32209566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3221e5d3d808SBarry Smith   if (Amat) {
32229566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
32239566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3224f5af7f23SKarl Rupp 
3225e5d3d808SBarry Smith     snes->jacobian = Amat;
32263a7fca6bSBarry Smith   }
3227e5d3d808SBarry Smith   if (Pmat) {
32289566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
32299566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3230f5af7f23SKarl Rupp 
3231e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
32323a7fca6bSBarry Smith   }
32333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32349b94acceSBarry Smith }
323562fef451SLois Curfman McInnes 
3236c2aafc4cSSatish Balay /*@C
3237b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3238b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3239b4fd4287SBarry Smith 
3240420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3241c7afd0dbSLois Curfman McInnes 
3242b4fd4287SBarry Smith   Input Parameter:
3243b4fd4287SBarry Smith . snes - the nonlinear solver context
3244b4fd4287SBarry Smith 
3245b4fd4287SBarry Smith   Output Parameters:
3246dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3247dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
32488434afd1SBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3249dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3250fee21e36SBarry Smith 
325136851e7fSLois Curfman McInnes   Level: advanced
325236851e7fSLois Curfman McInnes 
32538434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3254b4fd4287SBarry Smith @*/
32558434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
3256d71ae5a4SJacob Faibussowitsch {
32576cab3a1bSJed Brown   DM dm;
32586cab3a1bSJed Brown 
32593a40ed3dSBarry Smith   PetscFunctionBegin;
32600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3261e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3262e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
32639566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3264800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
32653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3266b4fd4287SBarry Smith }
3267b4fd4287SBarry Smith 
3268d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3269d71ae5a4SJacob Faibussowitsch {
327058b371f3SBarry Smith   DM     dm;
327158b371f3SBarry Smith   DMSNES sdm;
327258b371f3SBarry Smith 
327358b371f3SBarry Smith   PetscFunctionBegin;
32749566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32759566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
327658b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
327758b371f3SBarry Smith     DM        dm;
327858b371f3SBarry Smith     PetscBool isdense, ismf;
327958b371f3SBarry Smith 
32809566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
32819566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
32829566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
328358b371f3SBarry Smith     if (isdense) {
32849566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
328558b371f3SBarry Smith     } else if (!ismf) {
32869566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
328758b371f3SBarry Smith     }
328858b371f3SBarry Smith   }
32893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
329058b371f3SBarry Smith }
329158b371f3SBarry Smith 
32929b94acceSBarry Smith /*@
32939b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
32940b4b7b1cSBarry Smith   of a nonlinear solver `SNESSolve()`.
32959b94acceSBarry Smith 
3296c3339decSBarry Smith   Collective
3297fee21e36SBarry Smith 
32982fe279fdSBarry Smith   Input Parameter:
3299f6dfbefdSBarry Smith . snes - the `SNES` context
3300c7afd0dbSLois Curfman McInnes 
3301dc4c0fb0SBarry Smith   Level: advanced
3302dc4c0fb0SBarry Smith 
3303f6dfbefdSBarry Smith   Note:
33040b4b7b1cSBarry Smith   For basic use of the `SNES` solvers the user does not need to explicitly call
3305f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3306f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3307f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3308f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3309272ac6f2SLois Curfman McInnes 
33100b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()`
33119b94acceSBarry Smith @*/
3312d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3313d71ae5a4SJacob Faibussowitsch {
33146cab3a1bSJed Brown   DM             dm;
3315942e3340SBarry Smith   DMSNES         sdm;
3316c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
33176e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
33189b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
33199b5c1c08SStefano Zampini   Vec            f, fpc;
33209b5c1c08SStefano Zampini   void          *funcctx;
33219b5c1c08SStefano Zampini   void          *jacctx, *appctx;
33229b5c1c08SStefano Zampini   Mat            j, jpre;
33236b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
33246b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
33258434afd1SBarry Smith   SNESFunctionFn *func;
33268434afd1SBarry Smith   SNESJacobianFn *jac;
33273a40ed3dSBarry Smith 
33283a40ed3dSBarry Smith   PetscFunctionBegin;
33290700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33303ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3331fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
33329b94acceSBarry Smith 
333348a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
333485385478SLisandro Dalcin 
33359566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
333658c9b817SLisandro Dalcin 
33379566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
33389566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
33399566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
334058b371f3SBarry Smith 
334148a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3342efd51863SBarry Smith 
334348a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3344b710008aSBarry Smith 
3345d8d34be6SBarry Smith   if (snes->linesearch) {
33469566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
33479566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3348d8d34be6SBarry Smith   }
33499e764e56SPeter Brune 
33509b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3351b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3352172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3353172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3354172a4300SPeter Brune   }
3355d8f46077SPeter Brune 
3356efd4aadfSBarry Smith   if (snes->npc) {
33576e2a1849SPeter Brune     /* copy the DM over */
33589566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
33599566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
33606e2a1849SPeter Brune 
33619566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
33629566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
33639566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
33649566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
33659566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
33669566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
33679566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
33689b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
33699566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
33706e2a1849SPeter Brune 
33716e2a1849SPeter Brune     /* copy the function pointers over */
33729566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
33736e2a1849SPeter Brune 
33746e2a1849SPeter Brune     /* default to 1 iteration */
33759566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3376efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
33779566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3378a9936a0cSPeter Brune     } else {
33799566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3380a9936a0cSPeter Brune     }
33819566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
33826e2a1849SPeter Brune 
33836e2a1849SPeter Brune     /* copy the line search context over */
3384d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
33859566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
33869566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
33879566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
33889566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
33899566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
33909566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
33919566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
33926e2a1849SPeter Brune     }
3393d8d34be6SBarry Smith   }
33941baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
3395835f2295SStefano Zampini   if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx));
33966e2a1849SPeter Brune 
339737ec4e1aSPeter Brune   snes->jac_iter = 0;
339837ec4e1aSPeter Brune   snes->pre_iter = 0;
339937ec4e1aSPeter Brune 
3400dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
340158c9b817SLisandro Dalcin 
34029566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
340358b371f3SBarry Smith 
3404b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
34056c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3406d8d34be6SBarry Smith       if (snes->linesearch) {
34079566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
34089566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
34096c67d002SPeter Brune       }
34106c67d002SPeter Brune     }
3411d8d34be6SBarry Smith   }
3412fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
34137aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
34143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34159b94acceSBarry Smith }
34169b94acceSBarry Smith 
341737596af1SLisandro Dalcin /*@
34180b4b7b1cSBarry 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
341937596af1SLisandro Dalcin 
3420c3339decSBarry Smith   Collective
342137596af1SLisandro Dalcin 
342237596af1SLisandro Dalcin   Input Parameter:
34230b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
342437596af1SLisandro Dalcin 
3425d25893d9SBarry Smith   Level: intermediate
3426d25893d9SBarry Smith 
342795452b02SPatrick Sanan   Notes:
34280b4b7b1cSBarry Smith   Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain.
34290b4b7b1cSBarry Smith 
3430f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
343137596af1SLisandro Dalcin 
3432f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3433f6dfbefdSBarry Smith 
34341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
343537596af1SLisandro Dalcin @*/
3436d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3437d71ae5a4SJacob Faibussowitsch {
343837596af1SLisandro Dalcin   PetscFunctionBegin;
343937596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
344049abdd8aSBarry Smith   if (snes->ops->ctxdestroy && snes->ctx) {
3441835f2295SStefano Zampini     PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx));
344249abdd8aSBarry Smith     snes->ctx = NULL;
3443d25893d9SBarry Smith   }
34441baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
34458a23116dSBarry Smith 
3446dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
34471baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
34489e764e56SPeter Brune 
34491baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
34509e764e56SPeter Brune 
34519566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
34529566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
34539566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
34549566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
34559566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
34569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
34579566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
34589566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
34599566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3460f5af7f23SKarl Rupp 
346140fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
346240fdac6aSLawrence Mitchell 
346337596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
346437596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
34653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
346637596af1SLisandro Dalcin }
346737596af1SLisandro Dalcin 
346852baeb72SSatish Balay /*@
346936d43d94SBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also
347036d43d94SBarry Smith   removes the default viewer.
3471c4421ceaSFande Kong 
3472c3339decSBarry Smith   Collective
3473c4421ceaSFande Kong 
3474c4421ceaSFande Kong   Input Parameter:
34750b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
3476c4421ceaSFande Kong 
3477c4421ceaSFande Kong   Level: intermediate
3478c4421ceaSFande Kong 
3479420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3480c4421ceaSFande Kong @*/
3481d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3482d71ae5a4SJacob Faibussowitsch {
3483c4421ceaSFande Kong   PetscInt i;
3484c4421ceaSFande Kong 
3485c4421ceaSFande Kong   PetscFunctionBegin;
3486c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3487c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
348848a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3489c4421ceaSFande Kong   }
3490c4421ceaSFande Kong   snes->numberreasonviews = 0;
3491648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
34923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3493c4421ceaSFande Kong }
3494c4421ceaSFande Kong 
34950764c050SBarry Smith /*@
34969b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3497f6dfbefdSBarry Smith   with `SNESCreate()`.
34989b94acceSBarry Smith 
3499c3339decSBarry Smith   Collective
3500c7afd0dbSLois Curfman McInnes 
35019b94acceSBarry Smith   Input Parameter:
3502f6dfbefdSBarry Smith . snes - the `SNES` context
35039b94acceSBarry Smith 
350436851e7fSLois Curfman McInnes   Level: beginner
350536851e7fSLois Curfman McInnes 
35061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
35079b94acceSBarry Smith @*/
3508d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3509d71ae5a4SJacob Faibussowitsch {
351092e852f7SPablo Brubeck   DM dm;
351192e852f7SPablo Brubeck 
35123a40ed3dSBarry Smith   PetscFunctionBegin;
35133ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3514f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3515f4f49eeaSPierre Jolivet   if (--((PetscObject)*snes)->refct > 0) {
35169371c9d4SSatish Balay     *snes = NULL;
35173ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
35189371c9d4SSatish Balay   }
3519d4bb536fSBarry Smith 
3520f4f49eeaSPierre Jolivet   PetscCall(SNESReset(*snes));
35219566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
35226b8b9a38SLisandro Dalcin 
3523e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
35249566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3525f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*snes, destroy);
35266d4c513bSLisandro Dalcin 
352792e852f7SPablo Brubeck   dm = (*snes)->dm;
352892e852f7SPablo Brubeck   while (dm) {
352992e852f7SPablo Brubeck     PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
353092e852f7SPablo Brubeck     PetscCall(DMGetCoarseDM(dm, &dm));
353192e852f7SPablo Brubeck   }
353292e852f7SPablo Brubeck 
35339566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
35349566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
35359566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
35366b8b9a38SLisandro Dalcin 
35379566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
353848a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
353948a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3540f4f49eeaSPierre Jolivet   PetscCall(SNESMonitorCancel(*snes));
3541f4f49eeaSPierre Jolivet   PetscCall(SNESConvergedReasonViewCancel(*snes));
35429566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
35433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35449b94acceSBarry Smith }
35459b94acceSBarry Smith 
35469b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
35479b94acceSBarry Smith 
3548a8054027SBarry Smith /*@
35490b4b7b1cSBarry Smith   SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`.
3550a8054027SBarry Smith 
3551c3339decSBarry Smith   Logically Collective
3552a8054027SBarry Smith 
3553a8054027SBarry Smith   Input Parameters:
3554f6dfbefdSBarry Smith + snes - the `SNES` context
3555d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
35563b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3557a8054027SBarry Smith 
3558a8054027SBarry Smith   Options Database Keys:
3559420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
35603d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3561420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
35623d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3563a8054027SBarry Smith 
3564dc4c0fb0SBarry Smith   Level: intermediate
3565dc4c0fb0SBarry Smith 
3566420bcc1bSBarry Smith   Notes:
3567a8054027SBarry Smith   The default is 1
3568420bcc1bSBarry Smith 
3569f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3570d8e291bfSBarry Smith 
3571f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3572a8054027SBarry Smith 
35733201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3574f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3575a8054027SBarry Smith @*/
3576d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3577d71ae5a4SJacob Faibussowitsch {
3578a8054027SBarry Smith   PetscFunctionBegin;
35790700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35805f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
35815f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3582c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3583a8054027SBarry Smith   snes->lagpreconditioner = lag;
35843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3585a8054027SBarry Smith }
3586a8054027SBarry Smith 
3587efd51863SBarry Smith /*@
3588f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3589efd51863SBarry Smith 
3590c3339decSBarry Smith   Logically Collective
3591efd51863SBarry Smith 
3592efd51863SBarry Smith   Input Parameters:
3593f6dfbefdSBarry Smith + snes  - the `SNES` context
3594efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3595efd51863SBarry Smith 
3596f6dfbefdSBarry Smith   Options Database Key:
359767b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3598efd51863SBarry Smith 
3599efd51863SBarry Smith   Level: intermediate
3600efd51863SBarry Smith 
36010b4b7b1cSBarry Smith   Notes:
36020b4b7b1cSBarry Smith   Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement.
36030b4b7b1cSBarry Smith 
3604f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3605c0df2a02SJed Brown 
36063201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
360754c05997SPierre Jolivet           `SNESSetDM()`, `SNESSolve()`
3608efd51863SBarry Smith @*/
3609d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3610d71ae5a4SJacob Faibussowitsch {
3611efd51863SBarry Smith   PetscFunctionBegin;
3612efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3613efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3614efd51863SBarry Smith   snes->gridsequence = steps;
36153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3616efd51863SBarry Smith }
3617efd51863SBarry Smith 
3618fa19ca70SBarry Smith /*@
3619f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3620fa19ca70SBarry Smith 
3621c3339decSBarry Smith   Logically Collective
3622fa19ca70SBarry Smith 
3623fa19ca70SBarry Smith   Input Parameter:
3624f6dfbefdSBarry Smith . snes - the `SNES` context
3625fa19ca70SBarry Smith 
3626fa19ca70SBarry Smith   Output Parameter:
3627fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3628fa19ca70SBarry Smith 
3629fa19ca70SBarry Smith   Level: intermediate
3630fa19ca70SBarry Smith 
36313201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3632fa19ca70SBarry Smith @*/
3633d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3634d71ae5a4SJacob Faibussowitsch {
3635fa19ca70SBarry Smith   PetscFunctionBegin;
3636fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3637fa19ca70SBarry Smith   *steps = snes->gridsequence;
36383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3639fa19ca70SBarry Smith }
3640fa19ca70SBarry Smith 
3641a8054027SBarry Smith /*@
3642f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3643a8054027SBarry Smith 
36443f9fe445SBarry Smith   Not Collective
3645a8054027SBarry Smith 
3646a8054027SBarry Smith   Input Parameter:
3647f6dfbefdSBarry Smith . snes - the `SNES` context
3648a8054027SBarry Smith 
3649a8054027SBarry Smith   Output Parameter:
3650a8054027SBarry 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
36513b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3652a8054027SBarry Smith 
3653dc4c0fb0SBarry Smith   Level: intermediate
3654dc4c0fb0SBarry Smith 
3655a8054027SBarry Smith   Notes:
3656a8054027SBarry Smith   The default is 1
3657f6dfbefdSBarry Smith 
3658a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3659a8054027SBarry Smith 
36603201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3661a8054027SBarry Smith @*/
3662d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3663d71ae5a4SJacob Faibussowitsch {
3664a8054027SBarry Smith   PetscFunctionBegin;
36650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3666a8054027SBarry Smith   *lag = snes->lagpreconditioner;
36673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3668a8054027SBarry Smith }
3669a8054027SBarry Smith 
3670e35cf81dSBarry Smith /*@
3671f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3672e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3673e35cf81dSBarry Smith 
3674c3339decSBarry Smith   Logically Collective
3675e35cf81dSBarry Smith 
3676e35cf81dSBarry Smith   Input Parameters:
3677f6dfbefdSBarry Smith + snes - the `SNES` context
3678e35cf81dSBarry 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
3679fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3680e35cf81dSBarry Smith 
3681e35cf81dSBarry Smith   Options Database Keys:
368279a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
36833d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
368479a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
36853d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3686e35cf81dSBarry Smith 
3687dc4c0fb0SBarry Smith   Level: intermediate
3688dc4c0fb0SBarry Smith 
3689e35cf81dSBarry Smith   Notes:
3690e35cf81dSBarry Smith   The default is 1
3691f6dfbefdSBarry Smith 
3692e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3693f6dfbefdSBarry Smith 
3694fe3ffe1eSBarry 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
3695fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3696e35cf81dSBarry Smith 
36973201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3698e35cf81dSBarry Smith @*/
3699d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3700d71ae5a4SJacob Faibussowitsch {
3701e35cf81dSBarry Smith   PetscFunctionBegin;
37020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
37035f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
37045f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3705c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3706e35cf81dSBarry Smith   snes->lagjacobian = lag;
37073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3708e35cf81dSBarry Smith }
3709e35cf81dSBarry Smith 
3710e35cf81dSBarry Smith /*@
3711f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3712e35cf81dSBarry Smith 
37133f9fe445SBarry Smith   Not Collective
3714e35cf81dSBarry Smith 
3715e35cf81dSBarry Smith   Input Parameter:
3716f6dfbefdSBarry Smith . snes - the `SNES` context
3717e35cf81dSBarry Smith 
3718e35cf81dSBarry Smith   Output Parameter:
3719e35cf81dSBarry 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
3720e35cf81dSBarry Smith          the Jacobian is built etc.
3721e35cf81dSBarry Smith 
3722dc4c0fb0SBarry Smith   Level: intermediate
3723dc4c0fb0SBarry Smith 
3724e35cf81dSBarry Smith   Notes:
3725e35cf81dSBarry Smith   The default is 1
3726f6dfbefdSBarry Smith 
3727f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3728e35cf81dSBarry Smith 
37293201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3730e35cf81dSBarry Smith 
3731e35cf81dSBarry Smith @*/
3732d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3733d71ae5a4SJacob Faibussowitsch {
3734e35cf81dSBarry Smith   PetscFunctionBegin;
37350700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3736e35cf81dSBarry Smith   *lag = snes->lagjacobian;
37373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3738e35cf81dSBarry Smith }
3739e35cf81dSBarry Smith 
374037ec4e1aSPeter Brune /*@
3741f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
374237ec4e1aSPeter Brune 
3743c3339decSBarry Smith   Logically collective
374437ec4e1aSPeter Brune 
3745d8d19677SJose E. Roman   Input Parameters:
3746f6dfbefdSBarry Smith + snes - the `SNES` context
37479d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
374837ec4e1aSPeter Brune 
374937ec4e1aSPeter Brune   Options Database Keys:
375079a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37513d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
375279a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37533d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
37543d5a8a6aSBarry Smith 
3755dc4c0fb0SBarry Smith   Level: advanced
3756dc4c0fb0SBarry Smith 
375795452b02SPatrick Sanan   Notes:
3758420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3759f6dfbefdSBarry Smith 
376095452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
376137ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
376237ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
376337ec4e1aSPeter Brune 
376442747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
376537ec4e1aSPeter Brune @*/
3766d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3767d71ae5a4SJacob Faibussowitsch {
376837ec4e1aSPeter Brune   PetscFunctionBegin;
376937ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
377037ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
377137ec4e1aSPeter Brune   snes->lagjac_persist = flg;
37723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
377337ec4e1aSPeter Brune }
377437ec4e1aSPeter Brune 
377537ec4e1aSPeter Brune /*@
3776d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
377737ec4e1aSPeter Brune 
3778c3339decSBarry Smith   Logically Collective
377937ec4e1aSPeter Brune 
3780d8d19677SJose E. Roman   Input Parameters:
3781f6dfbefdSBarry Smith + snes - the `SNES` context
37829d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
378337ec4e1aSPeter Brune 
378437ec4e1aSPeter Brune   Options Database Keys:
378579a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37863d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
378779a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37883d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
378937ec4e1aSPeter Brune 
3790dc4c0fb0SBarry Smith   Level: developer
3791dc4c0fb0SBarry Smith 
379295452b02SPatrick Sanan   Notes:
3793420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3794f6dfbefdSBarry Smith 
379595452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
379637ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
379737ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
379837ec4e1aSPeter Brune 
37991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
380037ec4e1aSPeter Brune @*/
3801d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3802d71ae5a4SJacob Faibussowitsch {
380337ec4e1aSPeter Brune   PetscFunctionBegin;
380437ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
380537ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
380637ec4e1aSPeter Brune   snes->lagpre_persist = flg;
38073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
380837ec4e1aSPeter Brune }
380937ec4e1aSPeter Brune 
38109b94acceSBarry Smith /*@
3811f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3812be5caee7SBarry Smith 
3813c3339decSBarry Smith   Logically Collective
3814be5caee7SBarry Smith 
3815be5caee7SBarry Smith   Input Parameters:
3816f6dfbefdSBarry Smith + snes  - the `SNES` context
3817f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3818be5caee7SBarry Smith 
3819f6dfbefdSBarry Smith   Options Database Key:
3820be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3821be5caee7SBarry Smith 
3822dc4c0fb0SBarry Smith   Level: intermediate
3823dc4c0fb0SBarry Smith 
3824f6dfbefdSBarry Smith   Note:
3825f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3826be5caee7SBarry Smith 
38273201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()`
3828be5caee7SBarry Smith @*/
3829d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3830d71ae5a4SJacob Faibussowitsch {
3831be5caee7SBarry Smith   PetscFunctionBegin;
3832be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3833be5caee7SBarry Smith   snes->forceiteration = force;
38343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3835be5caee7SBarry Smith }
3836be5caee7SBarry Smith 
383785216dc7SFande Kong /*@
3838f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
383985216dc7SFande Kong 
3840c3339decSBarry Smith   Logically Collective
384185216dc7SFande Kong 
38422fe279fdSBarry Smith   Input Parameter:
3843f6dfbefdSBarry Smith . snes - the `SNES` context
384485216dc7SFande Kong 
384585216dc7SFande Kong   Output Parameter:
3846dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
384785216dc7SFande Kong 
384806dd6b0eSSatish Balay   Level: intermediate
384906dd6b0eSSatish Balay 
38503201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()`
385185216dc7SFande Kong @*/
3852d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3853d71ae5a4SJacob Faibussowitsch {
385485216dc7SFande Kong   PetscFunctionBegin;
385585216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
385685216dc7SFande Kong   *force = snes->forceiteration;
38573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
385885216dc7SFande Kong }
3859be5caee7SBarry Smith 
3860be5caee7SBarry Smith /*@
38610b4b7b1cSBarry Smith   SNESSetTolerances - Sets various parameters used in `SNES` convergence tests.
38629b94acceSBarry Smith 
3863c3339decSBarry Smith   Logically Collective
3864c7afd0dbSLois Curfman McInnes 
38659b94acceSBarry Smith   Input Parameters:
3866f6dfbefdSBarry Smith + snes   - the `SNES` context
38670b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $
38680b4b7b1cSBarry Smith . rtol   - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $
38695358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
38700b4b7b1cSBarry Smith . maxit  - the maximum number of iterations allowed in the solver, default 50.
38710b4b7b1cSBarry Smith - maxf   - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000
3872fee21e36SBarry Smith 
387333174efeSLois Curfman McInnes   Options Database Keys:
387477e5a1f9SBarry Smith + -snes_atol <abstol>    - Sets `abstol`
387577e5a1f9SBarry Smith . -snes_rtol <rtol>      - Sets `rtol`
387677e5a1f9SBarry Smith . -snes_stol <stol>      - Sets `stol`
387777e5a1f9SBarry Smith . -snes_max_it <maxit>   - Sets `maxit`
387877e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum)
38799b94acceSBarry Smith 
388036851e7fSLois Curfman McInnes   Level: intermediate
388136851e7fSLois Curfman McInnes 
388277e5a1f9SBarry Smith   Note:
388377e5a1f9SBarry Smith   All parameters must be non-negative
388477e5a1f9SBarry Smith 
388577e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`.
388677e5a1f9SBarry Smith   The default value is the value in the object when its type is set.
388777e5a1f9SBarry Smith 
388877e5a1f9SBarry Smith   Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations.
388977e5a1f9SBarry Smith 
389077e5a1f9SBarry Smith   Fortran Note:
389177e5a1f9SBarry Smith   Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL`
389277e5a1f9SBarry Smith 
38933201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
38949b94acceSBarry Smith @*/
3895d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3896d71ae5a4SJacob Faibussowitsch {
38973a40ed3dSBarry Smith   PetscFunctionBegin;
38980700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3899c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3900c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3901c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3902c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3903c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3904c5eb9154SBarry Smith 
390577e5a1f9SBarry Smith   if (abstol == (PetscReal)PETSC_DETERMINE) {
390677e5a1f9SBarry Smith     snes->abstol = snes->default_abstol;
390777e5a1f9SBarry Smith   } else if (abstol != (PetscReal)PETSC_CURRENT) {
39085f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3909ab54825eSJed Brown     snes->abstol = abstol;
3910ab54825eSJed Brown   }
391177e5a1f9SBarry Smith 
391277e5a1f9SBarry Smith   if (rtol == (PetscReal)PETSC_DETERMINE) {
391377e5a1f9SBarry Smith     snes->rtol = snes->default_rtol;
391477e5a1f9SBarry Smith   } else if (rtol != (PetscReal)PETSC_CURRENT) {
39155f80ce2aSJacob 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);
3916ab54825eSJed Brown     snes->rtol = rtol;
3917ab54825eSJed Brown   }
391877e5a1f9SBarry Smith 
391977e5a1f9SBarry Smith   if (stol == (PetscReal)PETSC_DETERMINE) {
392077e5a1f9SBarry Smith     snes->stol = snes->default_stol;
392177e5a1f9SBarry Smith   } else if (stol != (PetscReal)PETSC_CURRENT) {
39225f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3923c60f73f4SPeter Brune     snes->stol = stol;
3924ab54825eSJed Brown   }
392577e5a1f9SBarry Smith 
3926835f2295SStefano Zampini   if (maxit == PETSC_DETERMINE) {
392777e5a1f9SBarry Smith     snes->max_its = snes->default_max_its;
3928835f2295SStefano Zampini   } else if (maxit == PETSC_UNLIMITED) {
392977e5a1f9SBarry Smith     snes->max_its = PETSC_INT_MAX;
393077e5a1f9SBarry Smith   } else if (maxit != PETSC_CURRENT) {
393163a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3932ab54825eSJed Brown     snes->max_its = maxit;
3933ab54825eSJed Brown   }
393477e5a1f9SBarry Smith 
3935835f2295SStefano Zampini   if (maxf == PETSC_DETERMINE) {
393677e5a1f9SBarry Smith     snes->max_funcs = snes->default_max_funcs;
3937835f2295SStefano Zampini   } else if (maxf == PETSC_UNLIMITED || maxf == -1) {
393877e5a1f9SBarry Smith     snes->max_funcs = PETSC_UNLIMITED;
393977e5a1f9SBarry Smith   } else if (maxf != PETSC_CURRENT) {
394077e5a1f9SBarry Smith     PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf);
3941ab54825eSJed Brown     snes->max_funcs = maxf;
3942ab54825eSJed Brown   }
39433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39449b94acceSBarry Smith }
39459b94acceSBarry Smith 
3946e4d06f11SPatrick Farrell /*@
3947f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3948e4d06f11SPatrick Farrell 
3949c3339decSBarry Smith   Logically Collective
3950e4d06f11SPatrick Farrell 
3951e4d06f11SPatrick Farrell   Input Parameters:
3952f6dfbefdSBarry Smith + snes   - the `SNES` context
39530b4b7b1cSBarry 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
39540b4b7b1cSBarry Smith            is stopped due to divergence.
3955e4d06f11SPatrick Farrell 
3956f6dfbefdSBarry Smith   Options Database Key:
3957dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3958e4d06f11SPatrick Farrell 
3959e4d06f11SPatrick Farrell   Level: intermediate
3960e4d06f11SPatrick Farrell 
396177e5a1f9SBarry Smith   Notes:
396277e5a1f9SBarry Smith   Use `PETSC_DETERMINE` to use the default value from when the object's type was set.
3963e5cd489fSStefano Zampini 
396477e5a1f9SBarry Smith   Fortran Note:
396577e5a1f9SBarry Smith   Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL`
396677e5a1f9SBarry Smith 
396777e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()`
3968e4d06f11SPatrick Farrell @*/
3969d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3970d71ae5a4SJacob Faibussowitsch {
3971e4d06f11SPatrick Farrell   PetscFunctionBegin;
3972e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3973e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
397477e5a1f9SBarry Smith 
397577e5a1f9SBarry Smith   if (divtol == (PetscReal)PETSC_DETERMINE) {
397677e5a1f9SBarry Smith     snes->divtol = snes->default_divtol;
397777e5a1f9SBarry Smith   } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) {
397877e5a1f9SBarry Smith     snes->divtol = PETSC_UNLIMITED;
397977e5a1f9SBarry Smith   } else if (divtol != (PetscReal)PETSC_CURRENT) {
398077e5a1f9SBarry Smith     PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol);
398177e5a1f9SBarry Smith     snes->divtol = divtol;
398277e5a1f9SBarry Smith   }
39833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3984e4d06f11SPatrick Farrell }
3985e4d06f11SPatrick Farrell 
39869b94acceSBarry Smith /*@
39870b4b7b1cSBarry Smith   SNESGetTolerances - Gets various parameters used in `SNES` convergence tests.
398833174efeSLois Curfman McInnes 
3989c7afd0dbSLois Curfman McInnes   Not Collective
3990c7afd0dbSLois Curfman McInnes 
399177e5a1f9SBarry Smith   Input Parameter:
399277e5a1f9SBarry Smith . snes - the `SNES` context
399377e5a1f9SBarry Smith 
399477e5a1f9SBarry Smith   Output Parameters:
39950b4b7b1cSBarry Smith + atol  - the absolute convergence tolerance
39960b4b7b1cSBarry Smith . rtol  - the relative convergence tolerance
399777e5a1f9SBarry Smith . stol  - convergence tolerance in terms of the norm of the change in the solution between steps
39980b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed
39990b4b7b1cSBarry Smith - maxf  - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound
4000fee21e36SBarry Smith 
400136851e7fSLois Curfman McInnes   Level: intermediate
400236851e7fSLois Curfman McInnes 
40030b4b7b1cSBarry Smith   Notes:
40040b4b7b1cSBarry Smith   See `SNESSetTolerances()` for details on the parameters.
40050b4b7b1cSBarry Smith 
4006dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
4007dc4c0fb0SBarry Smith 
40081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
400933174efeSLois Curfman McInnes @*/
4010d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
4011d71ae5a4SJacob Faibussowitsch {
40123a40ed3dSBarry Smith   PetscFunctionBegin;
40130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
401485385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
401533174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
4016c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
401733174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
401833174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
40193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
402033174efeSLois Curfman McInnes }
402133174efeSLois Curfman McInnes 
4022e4d06f11SPatrick Farrell /*@
4023e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
4024e4d06f11SPatrick Farrell 
4025e4d06f11SPatrick Farrell   Not Collective
4026e4d06f11SPatrick Farrell 
4027e4d06f11SPatrick Farrell   Input Parameters:
4028f6dfbefdSBarry Smith + snes   - the `SNES` context
4029e4d06f11SPatrick Farrell - divtol - divergence tolerance
4030e4d06f11SPatrick Farrell 
4031e4d06f11SPatrick Farrell   Level: intermediate
4032e4d06f11SPatrick Farrell 
40331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
4034e4d06f11SPatrick Farrell @*/
4035d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
4036d71ae5a4SJacob Faibussowitsch {
4037e4d06f11SPatrick Farrell   PetscFunctionBegin;
4038e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4039e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
40403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4041e4d06f11SPatrick Farrell }
4042e4d06f11SPatrick Farrell 
40436ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
40446ba87a44SLisandro Dalcin 
4045d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
4046d71ae5a4SJacob Faibussowitsch {
4047b271bb04SBarry Smith   PetscDrawLG      lg;
4048b271bb04SBarry Smith   PetscReal        x, y, per;
4049b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
4050b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
4051b271bb04SBarry Smith   PetscDraw        draw;
4052b271bb04SBarry Smith 
4053459f5d12SBarry Smith   PetscFunctionBegin;
40544d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
40559566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
40569566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40579566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40589566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
4059b271bb04SBarry Smith   x = (PetscReal)n;
406077b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
406194c9c6d3SKarl Rupp   else y = -15.0;
40629566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40636934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40649566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40659566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4066b271bb04SBarry Smith   }
4067b271bb04SBarry Smith 
40689566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
40699566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40709566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4071aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
40729566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
4073b271bb04SBarry Smith   x = (PetscReal)n;
4074b271bb04SBarry Smith   y = 100.0 * per;
40759566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40766934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40779566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40789566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4079b271bb04SBarry Smith   }
4080b271bb04SBarry Smith 
40819566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
40829371c9d4SSatish Balay   if (!n) {
40839371c9d4SSatish Balay     prev = rnorm;
40849371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
40859371c9d4SSatish Balay   }
40869566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40879566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
4088b271bb04SBarry Smith   x = (PetscReal)n;
4089b271bb04SBarry Smith   y = (prev - rnorm) / prev;
40909566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40916934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40929566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40939566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4094b271bb04SBarry Smith   }
4095b271bb04SBarry Smith 
40969566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
40979566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40989566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40999566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
4100b271bb04SBarry Smith   x = (PetscReal)n;
4101b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
4102b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
41039566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4104b271bb04SBarry Smith   }
41056934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41069566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41079566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4108b271bb04SBarry Smith   }
4109b271bb04SBarry Smith   prev = rnorm;
41103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4111b271bb04SBarry Smith }
4112b271bb04SBarry Smith 
4113228d79bcSJed Brown /*@
41142d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
41152d157150SStefano Zampini 
41162d157150SStefano Zampini   Collective
41172d157150SStefano Zampini 
41182d157150SStefano Zampini   Input Parameters:
41192d157150SStefano Zampini + snes  - the `SNES` context
41202d157150SStefano Zampini . it    - current iteration
41212d157150SStefano Zampini . xnorm - 2-norm of current iterate
41222d157150SStefano Zampini . snorm - 2-norm of current step
41232d157150SStefano Zampini - fnorm - 2-norm of function
41242d157150SStefano Zampini 
41252d157150SStefano Zampini   Level: developer
41262d157150SStefano Zampini 
41272d157150SStefano Zampini   Note:
4128420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
41292d157150SStefano Zampini   It does not typically need to be called by the user.
41302d157150SStefano Zampini 
4131c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
41322d157150SStefano Zampini @*/
41332d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
41342d157150SStefano Zampini {
41352d157150SStefano Zampini   PetscFunctionBegin;
41362d157150SStefano Zampini   if (!snes->reason) {
41372d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
41382d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
41392d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
41402d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
41412d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
41422d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
41432d157150SStefano Zampini     }
41442d157150SStefano Zampini   }
41452d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
41462d157150SStefano Zampini }
41472d157150SStefano Zampini 
41482d157150SStefano Zampini /*@
41490b4b7b1cSBarry Smith   SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database
4150228d79bcSJed Brown 
4151c3339decSBarry Smith   Collective
4152228d79bcSJed Brown 
4153228d79bcSJed Brown   Input Parameters:
4154f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
41550b4b7b1cSBarry Smith . iter  - current iteration number
41560b4b7b1cSBarry Smith - rnorm - current relative norm of the residual
4157228d79bcSJed Brown 
4158dc4c0fb0SBarry Smith   Level: developer
4159dc4c0fb0SBarry Smith 
4160f6dfbefdSBarry Smith   Note:
4161420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
4162228d79bcSJed Brown   It does not typically need to be called by the user.
4163228d79bcSJed Brown 
41641cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4165228d79bcSJed Brown @*/
4166d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4167d71ae5a4SJacob Faibussowitsch {
41687a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
41697a03ce2fSLisandro Dalcin 
41707a03ce2fSLisandro Dalcin   PetscFunctionBegin;
41715f3c5e7aSBarry Smith   if (n > 0) SNESCheckFunctionNorm(snes, rnorm);
41729566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
417348a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
41749566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
41753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41767a03ce2fSLisandro Dalcin }
41777a03ce2fSLisandro Dalcin 
41789b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
41799b94acceSBarry Smith 
4180bf388a1fSBarry Smith /*MC
4181f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4182bf388a1fSBarry Smith 
4183bf388a1fSBarry Smith      Synopsis:
4184aaa7dc30SBarry Smith      #include <petscsnes.h>
418537fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4186bf388a1fSBarry Smith 
4187c3339decSBarry Smith      Collective
41881843f636SBarry Smith 
41891843f636SBarry Smith     Input Parameters:
4190f6dfbefdSBarry Smith +    snes - the `SNES` context
4191bf388a1fSBarry Smith .    its - iteration number
4192bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
4193bf388a1fSBarry Smith -    mctx - [optional] monitoring context
4194bf388a1fSBarry Smith 
4195878cb397SSatish Balay    Level: advanced
4196878cb397SSatish Balay 
41971cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
4198bf388a1fSBarry Smith M*/
4199bf388a1fSBarry Smith 
42009b94acceSBarry Smith /*@C
4201a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
42020b4b7b1cSBarry Smith   iteration of the `SNES` nonlinear solver to display the iteration's
42039b94acceSBarry Smith   progress.
42049b94acceSBarry Smith 
4205c3339decSBarry Smith   Logically Collective
4206fee21e36SBarry Smith 
4207c7afd0dbSLois Curfman McInnes   Input Parameters:
4208f6dfbefdSBarry Smith + snes           - the `SNES` context
420920f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4210420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
421149abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
42129b94acceSBarry Smith 
42139665c990SLois Curfman McInnes   Options Database Keys:
4214f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4215798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4216dc4c0fb0SBarry 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
4217c7afd0dbSLois Curfman McInnes                                 the options database.
42189665c990SLois Curfman McInnes 
4219dc4c0fb0SBarry Smith   Level: intermediate
4220dc4c0fb0SBarry Smith 
4221f6dfbefdSBarry Smith   Note:
42226bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4223f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
42246bc08f3fSLois Curfman McInnes   order in which they were set.
4225639f9d9dSBarry Smith 
4226420bcc1bSBarry Smith   Fortran Note:
4227f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4228025f1a04SBarry Smith 
422949abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn`
42309b94acceSBarry Smith @*/
423149abdd8aSBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy)
4232d71ae5a4SJacob Faibussowitsch {
4233b90d0a6eSBarry Smith   PetscInt  i;
423478064530SBarry Smith   PetscBool identical;
4235b90d0a6eSBarry Smith 
42363a40ed3dSBarry Smith   PetscFunctionBegin;
42370700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4238b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
42399566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
42403ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4241649052a6SBarry Smith   }
42425f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
42436e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4244b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4245835f2295SStefano Zampini   snes->monitorcontext[snes->numbermonitors++] = mctx;
42463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42479b94acceSBarry Smith }
42489b94acceSBarry Smith 
4249a278d85bSSatish Balay /*@
4250f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
42515cd90555SBarry Smith 
4252c3339decSBarry Smith   Logically Collective
4253c7afd0dbSLois Curfman McInnes 
42542fe279fdSBarry Smith   Input Parameter:
4255f6dfbefdSBarry Smith . snes - the `SNES` context
42565cd90555SBarry Smith 
42571a480d89SAdministrator   Options Database Key:
4258a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4259dc4c0fb0SBarry Smith                          into a code by calls to `SNESMonitorSet()`, but does not cancel those
4260c7afd0dbSLois Curfman McInnes                          set via the options database
42615cd90555SBarry Smith 
4262dc4c0fb0SBarry Smith   Level: intermediate
4263dc4c0fb0SBarry Smith 
4264f6dfbefdSBarry Smith   Note:
4265f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
42665cd90555SBarry Smith 
42671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
42685cd90555SBarry Smith @*/
4269d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4270d71ae5a4SJacob Faibussowitsch {
4271d952e501SBarry Smith   PetscInt i;
4272d952e501SBarry Smith 
42735cd90555SBarry Smith   PetscFunctionBegin;
42740700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4275d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
427648a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4277d952e501SBarry Smith   }
42785cd90555SBarry Smith   snes->numbermonitors = 0;
42793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42805cd90555SBarry Smith }
42815cd90555SBarry Smith 
4282bf388a1fSBarry Smith /*MC
4283bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4284bf388a1fSBarry Smith 
4285bf388a1fSBarry Smith      Synopsis:
4286aaa7dc30SBarry Smith      #include <petscsnes.h>
428737fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4288bf388a1fSBarry Smith 
4289c3339decSBarry Smith      Collective
42901843f636SBarry Smith 
42911843f636SBarry Smith     Input Parameters:
4292f6dfbefdSBarry Smith +    snes - the `SNES` context
4293bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4294bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4295bf388a1fSBarry Smith .    gnorm - 2-norm of current step
42961843f636SBarry Smith .    f - 2-norm of function
42971843f636SBarry Smith -    cctx - [optional] convergence context
42981843f636SBarry Smith 
42991843f636SBarry Smith     Output Parameter:
43001843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4301bf388a1fSBarry Smith 
4302878cb397SSatish Balay    Level: intermediate
4303bf388a1fSBarry Smith 
4304c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
4305bf388a1fSBarry Smith M*/
4306bf388a1fSBarry Smith 
43079b94acceSBarry Smith /*@C
43089b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
43099b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
43109b94acceSBarry Smith 
4311c3339decSBarry Smith   Logically Collective
4312fee21e36SBarry Smith 
4313c7afd0dbSLois Curfman McInnes   Input Parameters:
4314f6dfbefdSBarry Smith + snes                        - the `SNES` context
4315e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4316dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4317dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
43189b94acceSBarry Smith 
431936851e7fSLois Curfman McInnes   Level: advanced
432036851e7fSLois Curfman McInnes 
43211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
43229b94acceSBarry Smith @*/
4323d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4324d71ae5a4SJacob Faibussowitsch {
43253a40ed3dSBarry Smith   PetscFunctionBegin;
43260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4327e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
43281baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4329bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
43307f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
433185385478SLisandro Dalcin   snes->cnvP                  = cctx;
43323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43339b94acceSBarry Smith }
43349b94acceSBarry Smith 
433552baeb72SSatish Balay /*@
43360b4b7b1cSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation
4337184914b5SBarry Smith 
4338184914b5SBarry Smith   Not Collective
4339184914b5SBarry Smith 
4340184914b5SBarry Smith   Input Parameter:
4341f6dfbefdSBarry Smith . snes - the `SNES` context
4342184914b5SBarry Smith 
4343184914b5SBarry Smith   Output Parameter:
4344f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4345184914b5SBarry Smith 
4346f6dfbefdSBarry Smith   Options Database Key:
43476a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
43486a4d7782SBarry Smith 
4349184914b5SBarry Smith   Level: intermediate
4350184914b5SBarry Smith 
4351f6dfbefdSBarry Smith   Note:
4352f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4353184914b5SBarry Smith 
43541cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4355184914b5SBarry Smith @*/
4356d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4357d71ae5a4SJacob Faibussowitsch {
4358184914b5SBarry Smith   PetscFunctionBegin;
43590700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43604f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4361184914b5SBarry Smith   *reason = snes->reason;
43623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4363184914b5SBarry Smith }
4364184914b5SBarry Smith 
4365c4421ceaSFande Kong /*@C
4366f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4367c4421ceaSFande Kong 
4368c4421ceaSFande Kong   Not Collective
4369c4421ceaSFande Kong 
4370c4421ceaSFande Kong   Input Parameter:
4371f6dfbefdSBarry Smith . snes - the `SNES` context
4372c4421ceaSFande Kong 
4373c4421ceaSFande Kong   Output Parameter:
4374dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4375c4421ceaSFande Kong 
437699c90e12SSatish Balay   Level: beginner
4377c4421ceaSFande Kong 
43781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4379c4421ceaSFande Kong @*/
4380d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4381d71ae5a4SJacob Faibussowitsch {
4382c4421ceaSFande Kong   PetscFunctionBegin;
4383c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43844f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4385c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
43863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4387c4421ceaSFande Kong }
4388c4421ceaSFande Kong 
438933866048SMatthew G. Knepley /*@
4390f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
439133866048SMatthew G. Knepley 
439233866048SMatthew G. Knepley   Not Collective
439333866048SMatthew G. Knepley 
439433866048SMatthew G. Knepley   Input Parameters:
4395f6dfbefdSBarry Smith + snes   - the `SNES` context
4396f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
439733866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
439833866048SMatthew G. Knepley 
4399f6dfbefdSBarry Smith   Level: developer
4400f6dfbefdSBarry Smith 
4401420bcc1bSBarry Smith   Developer Note:
4402f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
440333866048SMatthew G. Knepley 
44041cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
440533866048SMatthew G. Knepley @*/
4406d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4407d71ae5a4SJacob Faibussowitsch {
440833866048SMatthew G. Knepley   PetscFunctionBegin;
440933866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44105f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
441133866048SMatthew G. Knepley   snes->reason = reason;
44123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
441333866048SMatthew G. Knepley }
441433866048SMatthew G. Knepley 
4415c9005455SLois Curfman McInnes /*@
4416420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4417c9005455SLois Curfman McInnes 
4418c3339decSBarry Smith   Logically Collective
4419fee21e36SBarry Smith 
4420c7afd0dbSLois Curfman McInnes   Input Parameters:
4421f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
44228c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4423cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4424420bcc1bSBarry Smith . na    - size of `a` and `its`
4425f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4426758f92a0SBarry Smith           else it continues storing new values for new nonlinear solves after the old ones
4427c7afd0dbSLois Curfman McInnes 
4428dc4c0fb0SBarry Smith   Level: intermediate
4429dc4c0fb0SBarry Smith 
4430308dcc3eSBarry Smith   Notes:
4431ce78bad3SBarry 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
443277e5a1f9SBarry Smith   default array of length 1,000 is allocated.
4433308dcc3eSBarry Smith 
4434c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4435c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4436c9005455SLois Curfman McInnes   during the section of code that is being timed.
4437c9005455SLois Curfman McInnes 
4438420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4439420bcc1bSBarry Smith 
44401cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4441c9005455SLois Curfman McInnes @*/
4442d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4443d71ae5a4SJacob Faibussowitsch {
44443a40ed3dSBarry Smith   PetscFunctionBegin;
44450700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44464f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
44474f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
44487a1ec6d4SBarry Smith   if (!a) {
444977e5a1f9SBarry Smith     if (na == PETSC_DECIDE) na = 1000;
44509566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4451071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4452308dcc3eSBarry Smith   }
4453c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4454758f92a0SBarry Smith   snes->conv_hist_its   = its;
4455115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4456a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4457758f92a0SBarry Smith   snes->conv_hist_reset = reset;
44583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4459758f92a0SBarry Smith }
4460758f92a0SBarry Smith 
4461d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4462c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4463c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
446499e0435eSBarry Smith 
4465d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4466d71ae5a4SJacob Faibussowitsch {
4467308dcc3eSBarry Smith   mxArray   *mat;
4468308dcc3eSBarry Smith   PetscInt   i;
4469308dcc3eSBarry Smith   PetscReal *ar;
4470308dcc3eSBarry Smith 
4471308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4472308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4473f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
447411cc89d2SBarry Smith   return mat;
4475308dcc3eSBarry Smith }
4476308dcc3eSBarry Smith #endif
4477308dcc3eSBarry Smith 
44780c4c9dddSBarry Smith /*@C
4479420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4480758f92a0SBarry Smith 
44813f9fe445SBarry Smith   Not Collective
4482758f92a0SBarry Smith 
4483758f92a0SBarry Smith   Input Parameter:
4484f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4485758f92a0SBarry Smith 
4486758f92a0SBarry Smith   Output Parameters:
4487f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4488758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4489758f92a0SBarry Smith          negative if not converged) for each solve.
449020f4b53cSBarry Smith - na  - size of `a` and `its`
4491758f92a0SBarry Smith 
4492dc4c0fb0SBarry Smith   Level: intermediate
4493dc4c0fb0SBarry Smith 
449420f4b53cSBarry Smith   Note:
449520f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
449620f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
449720f4b53cSBarry Smith   during the section of code that is being timed.
449820f4b53cSBarry Smith 
4499ce78bad3SBarry Smith   Fortran Notes:
4500ce78bad3SBarry Smith   Return the arrays with ``SNESRestoreConvergenceHistory()`
4501ce78bad3SBarry Smith 
4502ce78bad3SBarry Smith   Use the arguments
4503dc4c0fb0SBarry Smith .vb
4504ce78bad3SBarry Smith   PetscReal, pointer :: a(:)
4505ce78bad3SBarry Smith   PetscInt, pointer :: its(:)
4506dc4c0fb0SBarry Smith .ve
4507758f92a0SBarry Smith 
45081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4509758f92a0SBarry Smith @*/
4510d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4511d71ae5a4SJacob Faibussowitsch {
4512758f92a0SBarry Smith   PetscFunctionBegin;
45130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4514758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4515758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4516115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
45173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4518c9005455SLois Curfman McInnes }
4519c9005455SLois Curfman McInnes 
4520ac226902SBarry Smith /*@C
452176b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4522eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
452353e5d35bSStefano Zampini   it is called just before the Jacobian is "evaluated" and after the function
452453e5d35bSStefano Zampini   evaluation.
452576b2cf59SMatthew Knepley 
4526c3339decSBarry Smith   Logically Collective
452776b2cf59SMatthew Knepley 
452876b2cf59SMatthew Knepley   Input Parameters:
4529a2b725a8SWilliam Gropp + snes - The nonlinear solver context
453053e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn`
453176b2cf59SMatthew Knepley 
4532fe97e370SBarry Smith   Level: advanced
4533fe97e370SBarry Smith 
4534420bcc1bSBarry Smith   Notes:
4535f6dfbefdSBarry 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
4536f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
453753e5d35bSStefano Zampini   This is not used by most users, and it is intended to provide a general hook that is run
453853e5d35bSStefano Zampini   right before the direction step is computed.
4539ce78bad3SBarry Smith 
454053e5d35bSStefano Zampini   Users are free to modify the current residual vector,
454153e5d35bSStefano Zampini   the current linearization point, or any other vector associated to the specific solver used.
454253e5d35bSStefano Zampini   If such modifications take place, it is the user responsibility to update all the relevant
4543ce78bad3SBarry Smith   vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like
4544ce78bad3SBarry Smith .vb
4545ce78bad3SBarry Smith   PetscErrorCode update(SNES snes, PetscInt iteration)
4546ce78bad3SBarry Smith   {
4547ce78bad3SBarry Smith     PetscFunctionBeginUser;
4548ce78bad3SBarry Smith     if (iteration > 0) {
4549ce78bad3SBarry Smith       // update the model parameters here
4550ce78bad3SBarry Smith       Vec x,f;
4551ce78bad3SBarry Smith       PetscCall(SNESGetSolution(snes,&x));
4552ce78bad3SBarry Smith       PetcCall(SNESGetFunction(snes,&f,NULL,NULL));
4553ce78bad3SBarry Smith       PetscCall(SNESComputeFunction(snes,x,f));
4554ce78bad3SBarry Smith     }
4555ce78bad3SBarry Smith     PetscFunctionReturn(PETSC_SUCCESS);
4556ce78bad3SBarry Smith   }
4557ce78bad3SBarry Smith .ve
455876b2cf59SMatthew Knepley 
4559aaa8cc7dSPierre 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.
45606b7fb656SBarry Smith 
4561e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
456253e5d35bSStefano Zampini          `SNESMonitorSet()`
456376b2cf59SMatthew Knepley @*/
456453e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4565d71ae5a4SJacob Faibussowitsch {
456676b2cf59SMatthew Knepley   PetscFunctionBegin;
45670700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4568e7788613SBarry Smith   snes->ops->update = func;
45693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
457076b2cf59SMatthew Knepley }
457176b2cf59SMatthew Knepley 
4572ffeef943SBarry Smith /*@
4573f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
45742a359c20SBarry Smith 
4575c3339decSBarry Smith   Collective
45762a359c20SBarry Smith 
4577e4094ef1SJacob Faibussowitsch   Input Parameters:
4578f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
45792a359c20SBarry Smith - viewer - the viewer to display the reason
45802a359c20SBarry Smith 
45812a359c20SBarry Smith   Options Database Keys:
4582ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4583ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4584eafd5ff0SAlex Lindsay 
4585420bcc1bSBarry Smith   Level: beginner
4586420bcc1bSBarry Smith 
4587f6dfbefdSBarry Smith   Note:
4588f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4589f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
45902a359c20SBarry Smith 
45911cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4592f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4593f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4594db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
45952a359c20SBarry Smith @*/
4596d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4597d71ae5a4SJacob Faibussowitsch {
459875cca76cSMatthew G. Knepley   PetscViewerFormat format;
45992a359c20SBarry Smith   PetscBool         isAscii;
46002a359c20SBarry Smith 
46012a359c20SBarry Smith   PetscFunctionBegin;
460219a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
46039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
46042a359c20SBarry Smith   if (isAscii) {
46059566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
460665bf60d2SBarry Smith     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
460775cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
460875cca76cSMatthew G. Knepley       DM       dm;
460975cca76cSMatthew G. Knepley       Vec      u;
461075cca76cSMatthew G. Knepley       PetscDS  prob;
461175cca76cSMatthew G. Knepley       PetscInt Nf, f;
461295cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
461395cbbfd3SMatthew G. Knepley       void    **exactCtx;
461475cca76cSMatthew G. Knepley       PetscReal error;
461575cca76cSMatthew G. Knepley 
46169566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
46179566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
46189566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
46199566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
46209566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
46219566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
46229566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
46239566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
46249566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
462563a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
462675cca76cSMatthew G. Knepley     }
4627eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
46282a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
462963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
46302a359c20SBarry Smith       } else {
463163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46322a359c20SBarry Smith       }
4633eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
46342a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
463563a3b9bcSJacob 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));
46362a359c20SBarry Smith       } else {
463763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46382a359c20SBarry Smith       }
46392a359c20SBarry Smith     }
464065bf60d2SBarry Smith     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
46412a359c20SBarry Smith   }
46423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46432a359c20SBarry Smith }
46442a359c20SBarry Smith 
4645c4421ceaSFande Kong /*@C
4646c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4647aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4648c4421ceaSFande Kong 
4649c3339decSBarry Smith   Logically Collective
4650c4421ceaSFande Kong 
4651c4421ceaSFande Kong   Input Parameters:
4652f6dfbefdSBarry Smith + snes              - the `SNES` context
4653420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4654420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
465549abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
4656420bcc1bSBarry Smith 
4657420bcc1bSBarry Smith   Calling sequence of `f`:
4658420bcc1bSBarry Smith + snes - the `SNES` context
465949abdd8aSBarry Smith - vctx - [optional] context for private data for the function
4660c4421ceaSFande Kong 
4661c4421ceaSFande Kong   Options Database Keys:
4662f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4663420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4664420bcc1bSBarry Smith                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4665c4421ceaSFande Kong 
4666dc4c0fb0SBarry Smith   Level: intermediate
4667dc4c0fb0SBarry Smith 
4668f6dfbefdSBarry Smith   Note:
4669c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4670f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4671c4421ceaSFande Kong   order in which they were set.
4672c4421ceaSFande Kong 
467349abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`,
467449abdd8aSBarry Smith           `PetscCtxDestroyFn`
4675c4421ceaSFande Kong @*/
467649abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy)
4677d71ae5a4SJacob Faibussowitsch {
4678c4421ceaSFande Kong   PetscInt  i;
4679c4421ceaSFande Kong   PetscBool identical;
4680c4421ceaSFande Kong 
4681c4421ceaSFande Kong   PetscFunctionBegin;
4682c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4683c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
46849566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
46853ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4686c4421ceaSFande Kong   }
46875f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4688c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4689c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4690835f2295SStefano Zampini   snes->reasonviewcontext[snes->numberreasonviews++] = vctx;
46913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4692c4421ceaSFande Kong }
4693c4421ceaSFande Kong 
469491f3e32bSBarry Smith /*@
4695420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
46960b4b7b1cSBarry Smith   All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist.
46972a359c20SBarry Smith 
4698c3339decSBarry Smith   Collective
46992a359c20SBarry Smith 
47002fe279fdSBarry Smith   Input Parameter:
4701f6dfbefdSBarry Smith . snes - the `SNES` object
47022a359c20SBarry Smith 
4703f6dfbefdSBarry Smith   Level: advanced
47042a359c20SBarry Smith 
47051cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4706f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
47072a359c20SBarry Smith @*/
4708d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4709d71ae5a4SJacob Faibussowitsch {
47102a359c20SBarry Smith   static PetscBool incall = PETSC_FALSE;
47112a359c20SBarry Smith 
47122a359c20SBarry Smith   PetscFunctionBegin;
47133ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
47142a359c20SBarry Smith   incall = PETSC_TRUE;
4715c4421ceaSFande Kong 
4716c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
471736d43d94SBarry Smith   for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4718c4421ceaSFande Kong 
4719c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
472036d43d94SBarry Smith   if (snes->convergedreasonviewer) {
472136d43d94SBarry Smith     PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
472236d43d94SBarry Smith     PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
472336d43d94SBarry Smith     PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
47242a359c20SBarry Smith   }
47252a359c20SBarry Smith   incall = PETSC_FALSE;
47263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47272a359c20SBarry Smith }
47282a359c20SBarry Smith 
4729487a658cSBarry Smith /*@
47300b4b7b1cSBarry Smith   SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object
47319b94acceSBarry Smith 
4732c3339decSBarry Smith   Collective
4733c7afd0dbSLois Curfman McInnes 
4734b2002411SLois Curfman McInnes   Input Parameters:
4735f6dfbefdSBarry Smith + snes - the `SNES` context
47360b4b7b1cSBarry Smith . b    - the constant part of the equation $F(x) = b$, or `NULL` to use zero.
473785385478SLisandro Dalcin - x    - the solution vector.
47389b94acceSBarry Smith 
4739dc4c0fb0SBarry Smith   Level: beginner
4740dc4c0fb0SBarry Smith 
4741f6dfbefdSBarry Smith   Note:
4742420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4743a9b45538SStefano Zampini   for the nonlinear solve prior to calling `SNESSolve()` .
47448ddd3da0SLois Curfman McInnes 
47451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4746db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4747a9b45538SStefano Zampini           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
47489b94acceSBarry Smith @*/
4749d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4750d71ae5a4SJacob Faibussowitsch {
4751ace3abfcSBarry Smith   PetscBool flg;
4752efd51863SBarry Smith   PetscInt  grid;
47530298fd71SBarry Smith   Vec       xcreated = NULL;
4754caa4e7f2SJed Brown   DM        dm;
4755052efed2SBarry Smith 
47563a40ed3dSBarry Smith   PetscFunctionBegin;
47570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4758a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4759a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
47600700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
476185385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
476285385478SLisandro Dalcin 
476334b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
476406fc46c8SMatthew G. Knepley   {
476506fc46c8SMatthew G. Knepley     PetscViewer       viewer;
476606fc46c8SMatthew G. Knepley     PetscViewerFormat format;
47677c88af5aSMatthew G. Knepley     PetscInt          num;
476806fc46c8SMatthew G. Knepley     PetscBool         flg;
476906fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
477006fc46c8SMatthew G. Knepley 
477106fc46c8SMatthew G. Knepley     if (!incall) {
477234b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
4773648c30bcSBarry Smith       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
477406fc46c8SMatthew G. Knepley       if (flg) {
477506fc46c8SMatthew G. Knepley         PetscConvEst conv;
477646079b62SMatthew G. Knepley         DM           dm;
477746079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
477846079b62SMatthew G. Knepley         PetscInt     Nf;
477906fc46c8SMatthew G. Knepley 
478006fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
47819566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
47829566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
47839566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
47849566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
47859566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
47869566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
47879566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
47889566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
47899566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
47909566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
47919566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4792648c30bcSBarry Smith         PetscCall(PetscViewerDestroy(&viewer));
47939566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
47949566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
479506fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
479606fc46c8SMatthew G. Knepley       }
479734b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4798b2588ea6SMatthew G. Knepley       num = 1;
47999566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
480034b4d3a8SMatthew G. Knepley       if (flg) {
480134b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
480234b4d3a8SMatthew G. Knepley 
480334b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
48049566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
48059566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48069566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48079566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48089566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
48099566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
48109566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
481134b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
481234b4d3a8SMatthew G. Knepley       }
48137c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
48147c88af5aSMatthew G. Knepley       num = 0;
48159566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
48167c88af5aSMatthew G. Knepley       if (num) {
48177c88af5aSMatthew G. Knepley         DMAdaptor   adaptor;
4818e03fd340SMatthew G. Knepley         const char *prefix;
48197c88af5aSMatthew G. Knepley 
48207c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
48219566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4822e03fd340SMatthew G. Knepley         PetscCall(SNESGetOptionsPrefix(snes, &prefix));
4823e03fd340SMatthew G. Knepley         PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix));
48249566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48259566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48269566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48279566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
4828e5148a0bSMatthew G. Knepley         PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
48299566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
48309566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
48317c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
48327c88af5aSMatthew G. Knepley       }
483306fc46c8SMatthew G. Knepley     }
483406fc46c8SMatthew G. Knepley   }
4835ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4836caa4e7f2SJed Brown   if (!x) {
48379566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
48389566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4839a69afd8bSBarry Smith     x = xcreated;
4840a69afd8bSBarry Smith   }
48419566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4842f05ece33SBarry Smith 
48439566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4844efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
484585385478SLisandro Dalcin     /* set solution vector */
48469566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
48479566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
484885385478SLisandro Dalcin     snes->vec_sol = x;
48499566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4850caa4e7f2SJed Brown 
4851caa4e7f2SJed Brown     /* set affine vector if provided */
48529566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
48539566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
485485385478SLisandro Dalcin     snes->vec_rhs = b;
485585385478SLisandro Dalcin 
48565f80ce2aSJacob 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");
48575f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4858dd8e379bSPierre Jolivet     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4859aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
48609566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
48619566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
48623f149594SLisandro Dalcin 
48637eee914bSBarry Smith     if (!grid) {
48649927e4dfSBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4865dd568438SSatish Balay     }
4866d25893d9SBarry Smith 
4867abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
486812b1dd1aSStefano Zampini     PetscCall(SNESResetCounters(snes));
48692d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
48709566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4871dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
48729566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
48732d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4874422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
48753f149594SLisandro Dalcin 
487637ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
487737ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
487837ec4e1aSPeter Brune 
4879648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
48809566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4881c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
48829566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
48835968eb51SBarry Smith 
48845f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
48859c8e83a9SBarry Smith     if (snes->reason < 0) break;
4886efd51863SBarry Smith     if (grid < snes->gridsequence) {
4887efd51863SBarry Smith       DM  fine;
4888efd51863SBarry Smith       Vec xnew;
4889efd51863SBarry Smith       Mat interp;
4890efd51863SBarry Smith 
48919566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
48925f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
48932eace19aSMatthew G. Knepley       PetscCall(DMGetCoordinatesLocalSetUp(fine));
48949566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
48959566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
48969566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
48979566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
48989566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4899efd51863SBarry Smith       x = xnew;
4900efd51863SBarry Smith 
49019566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
49029566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
49039566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
49049566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
49059566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4906efd51863SBarry Smith     }
4907efd51863SBarry Smith   }
49089566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
49099566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
49109566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
49119566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
49123f7e2da0SPeter Brune 
49139566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
49149566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
49153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49169b94acceSBarry Smith }
49179b94acceSBarry Smith 
49189b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
49199b94acceSBarry Smith 
4920cc4c1da9SBarry Smith /*@
49210b4b7b1cSBarry Smith   SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES`
49229b94acceSBarry Smith 
4923c3339decSBarry Smith   Collective
4924fee21e36SBarry Smith 
4925c7afd0dbSLois Curfman McInnes   Input Parameters:
4926f6dfbefdSBarry Smith + snes - the `SNES` context
4927454a90a3SBarry Smith - type - a known method
4928c7afd0dbSLois Curfman McInnes 
4929c7afd0dbSLois Curfman McInnes   Options Database Key:
4930454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
493104d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4932ae12b187SLois Curfman McInnes 
4933dc4c0fb0SBarry Smith   Level: intermediate
4934dc4c0fb0SBarry Smith 
49359b94acceSBarry Smith   Notes:
49360b4b7b1cSBarry Smith   See `SNESType` for available methods (for instance)
4937f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4938c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49394a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4940c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49419b94acceSBarry Smith 
4942f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4943f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4944ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4945ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4946f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4947ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4948ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4949ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4950ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4951b0a32e0cSBarry Smith   appropriate method.
495236851e7fSLois Curfman McInnes 
4953420bcc1bSBarry Smith   Developer Note:
4954f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4955f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
49568f6c3df8SBarry Smith 
49571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
49589b94acceSBarry Smith @*/
4959d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4960d71ae5a4SJacob Faibussowitsch {
4961ace3abfcSBarry Smith   PetscBool match;
49625f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
49633a40ed3dSBarry Smith 
49643a40ed3dSBarry Smith   PetscFunctionBegin;
49650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49664f572ea9SToby Isaac   PetscAssertPointer(type, 2);
496782bf6240SBarry Smith 
49689566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
49693ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
497092ff6ae8SBarry Smith 
49719566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
49726adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
497375396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4974dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
497543547594SStefano Zampini   /* Reinitialize type-specific function pointers in SNESOps structure */
497643547594SStefano Zampini   snes->ops->reset          = NULL;
49779e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
49789e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
49799e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
49809e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
49819e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
49827fe760d5SStefano Zampini 
49837fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
49849566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
49857fe760d5SStefano Zampini 
498675396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
498775396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4988f5af7f23SKarl Rupp 
49899566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
49909566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
49913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49929b94acceSBarry Smith }
49939b94acceSBarry Smith 
4994cc4c1da9SBarry Smith /*@
4995f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
49969b94acceSBarry Smith 
4997c7afd0dbSLois Curfman McInnes   Not Collective
4998c7afd0dbSLois Curfman McInnes 
49999b94acceSBarry Smith   Input Parameter:
50004b0e389bSBarry Smith . snes - nonlinear solver context
50019b94acceSBarry Smith 
50029b94acceSBarry Smith   Output Parameter:
5003f6dfbefdSBarry Smith . type - `SNES` method (a character string)
50049b94acceSBarry Smith 
500536851e7fSLois Curfman McInnes   Level: intermediate
500636851e7fSLois Curfman McInnes 
50071cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
50089b94acceSBarry Smith @*/
5009d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
5010d71ae5a4SJacob Faibussowitsch {
50113a40ed3dSBarry Smith   PetscFunctionBegin;
50120700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50134f572ea9SToby Isaac   PetscAssertPointer(type, 2);
50147adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
50153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50169b94acceSBarry Smith }
50179b94acceSBarry Smith 
50183cd8a7caSMatthew G. Knepley /*@
5019f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
50203cd8a7caSMatthew G. Knepley 
5021c3339decSBarry Smith   Logically Collective
50223cd8a7caSMatthew G. Knepley 
50233cd8a7caSMatthew G. Knepley   Input Parameters:
5024f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
50253cd8a7caSMatthew G. Knepley - u    - the solution vector
50263cd8a7caSMatthew G. Knepley 
50273cd8a7caSMatthew G. Knepley   Level: beginner
50283cd8a7caSMatthew G. Knepley 
50291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
50303cd8a7caSMatthew G. Knepley @*/
5031d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
5032d71ae5a4SJacob Faibussowitsch {
50333cd8a7caSMatthew G. Knepley   DM dm;
50343cd8a7caSMatthew G. Knepley 
50353cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
50363cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50373cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
50389566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
50399566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
50403cd8a7caSMatthew G. Knepley 
50413cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
50423cd8a7caSMatthew G. Knepley 
50439566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50449566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
50453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50463cd8a7caSMatthew G. Knepley }
50473cd8a7caSMatthew G. Knepley 
504852baeb72SSatish Balay /*@
50499b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
5050f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
50519b94acceSBarry Smith 
5052420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5053c7afd0dbSLois Curfman McInnes 
50549b94acceSBarry Smith   Input Parameter:
5055f6dfbefdSBarry Smith . snes - the `SNES` context
50569b94acceSBarry Smith 
50579b94acceSBarry Smith   Output Parameter:
50589b94acceSBarry Smith . x - the solution
50599b94acceSBarry Smith 
506070e92668SMatthew Knepley   Level: intermediate
506136851e7fSLois Curfman McInnes 
50621cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
50639b94acceSBarry Smith @*/
5064d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
5065d71ae5a4SJacob Faibussowitsch {
50663a40ed3dSBarry Smith   PetscFunctionBegin;
50670700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50684f572ea9SToby Isaac   PetscAssertPointer(x, 2);
506985385478SLisandro Dalcin   *x = snes->vec_sol;
50703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
507170e92668SMatthew Knepley }
507270e92668SMatthew Knepley 
507352baeb72SSatish Balay /*@
50749b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
50759b94acceSBarry Smith   stored.
50769b94acceSBarry Smith 
5077420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5078c7afd0dbSLois Curfman McInnes 
50799b94acceSBarry Smith   Input Parameter:
5080f6dfbefdSBarry Smith . snes - the `SNES` context
50819b94acceSBarry Smith 
50829b94acceSBarry Smith   Output Parameter:
50839b94acceSBarry Smith . x - the solution update
50849b94acceSBarry Smith 
508536851e7fSLois Curfman McInnes   Level: advanced
508636851e7fSLois Curfman McInnes 
50871cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
50889b94acceSBarry Smith @*/
5089d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
5090d71ae5a4SJacob Faibussowitsch {
50913a40ed3dSBarry Smith   PetscFunctionBegin;
50920700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50934f572ea9SToby Isaac   PetscAssertPointer(x, 2);
509485385478SLisandro Dalcin   *x = snes->vec_sol_update;
50953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50969b94acceSBarry Smith }
50979b94acceSBarry Smith 
50989b94acceSBarry Smith /*@C
5099f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
51009b94acceSBarry Smith 
5101420bcc1bSBarry Smith   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
5102c7afd0dbSLois Curfman McInnes 
51039b94acceSBarry Smith   Input Parameter:
5104f6dfbefdSBarry Smith . snes - the `SNES` context
51059b94acceSBarry Smith 
5106d8d19677SJose E. Roman   Output Parameters:
5107dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
51088434afd1SBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
5109dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
51109b94acceSBarry Smith 
511136851e7fSLois Curfman McInnes   Level: advanced
511236851e7fSLois Curfman McInnes 
5113f6dfbefdSBarry Smith   Note:
5114dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
511504edfde5SBarry Smith 
51168434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
51179b94acceSBarry Smith @*/
51188434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
5119d71ae5a4SJacob Faibussowitsch {
51206cab3a1bSJed Brown   DM dm;
5121a63bb30eSJed Brown 
51223a40ed3dSBarry Smith   PetscFunctionBegin;
51230700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5124a63bb30eSJed Brown   if (r) {
5125a63bb30eSJed Brown     if (!snes->vec_func) {
5126a63bb30eSJed Brown       if (snes->vec_rhs) {
51279566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5128a63bb30eSJed Brown       } else if (snes->vec_sol) {
51299566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5130a63bb30eSJed Brown       } else if (snes->dm) {
51319566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5132a63bb30eSJed Brown       }
5133a63bb30eSJed Brown     }
5134a63bb30eSJed Brown     *r = snes->vec_func;
5135a63bb30eSJed Brown   }
51369566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51379566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
51383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51399b94acceSBarry Smith }
51409b94acceSBarry Smith 
5141c79ef259SPeter Brune /*@C
514237fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5143c79ef259SPeter Brune 
5144c79ef259SPeter Brune   Input Parameter:
5145f6dfbefdSBarry Smith . snes - the `SNES` context
5146c79ef259SPeter Brune 
5147d8d19677SJose E. Roman   Output Parameters:
51488434afd1SBarry Smith + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5149dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
5150c79ef259SPeter Brune 
5151c79ef259SPeter Brune   Level: advanced
5152c79ef259SPeter Brune 
51538434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5154c79ef259SPeter Brune @*/
51558434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5156d71ae5a4SJacob Faibussowitsch {
51576cab3a1bSJed Brown   DM dm;
51586cab3a1bSJed Brown 
5159646217ecSPeter Brune   PetscFunctionBegin;
5160646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51619566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51629566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
51633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5164646217ecSPeter Brune }
5165646217ecSPeter Brune 
5166cc4c1da9SBarry Smith /*@
51673c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5168f6dfbefdSBarry Smith   `SNES` options in the database.
51693c7409f5SSatish Balay 
5170c3339decSBarry Smith   Logically Collective
5171fee21e36SBarry Smith 
5172d8d19677SJose E. Roman   Input Parameters:
5173f6dfbefdSBarry Smith + snes   - the `SNES` context
5174c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5175c7afd0dbSLois Curfman McInnes 
5176dc4c0fb0SBarry Smith   Level: advanced
5177dc4c0fb0SBarry Smith 
5178f6dfbefdSBarry Smith   Note:
5179a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5180c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5181d850072dSLois Curfman McInnes 
51821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
51833c7409f5SSatish Balay @*/
5184d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5185d71ae5a4SJacob Faibussowitsch {
51863a40ed3dSBarry Smith   PetscFunctionBegin;
51870700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51889566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
51899566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
519035f5d045SPeter Brune   if (snes->linesearch) {
51919566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
51929566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
519335f5d045SPeter Brune   }
51949566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
51953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51963c7409f5SSatish Balay }
51973c7409f5SSatish Balay 
5198cc4c1da9SBarry Smith /*@
5199f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5200f6dfbefdSBarry Smith   `SNES` options in the database.
52013c7409f5SSatish Balay 
5202c3339decSBarry Smith   Logically Collective
5203fee21e36SBarry Smith 
5204c7afd0dbSLois Curfman McInnes   Input Parameters:
5205f6dfbefdSBarry Smith + snes   - the `SNES` context
5206c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5207c7afd0dbSLois Curfman McInnes 
5208dc4c0fb0SBarry Smith   Level: advanced
5209dc4c0fb0SBarry Smith 
5210f6dfbefdSBarry Smith   Note:
5211a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5212c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5213d850072dSLois Curfman McInnes 
52141cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
52153c7409f5SSatish Balay @*/
5216d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5217d71ae5a4SJacob Faibussowitsch {
52183a40ed3dSBarry Smith   PetscFunctionBegin;
52190700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52209566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
52219566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
522235f5d045SPeter Brune   if (snes->linesearch) {
52239566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
52249566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
522535f5d045SPeter Brune   }
52269566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
52273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52283c7409f5SSatish Balay }
52293c7409f5SSatish Balay 
5230cc4c1da9SBarry Smith /*@
5231f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5232f6dfbefdSBarry Smith   `SNES` options in the database.
52333c7409f5SSatish Balay 
5234c7afd0dbSLois Curfman McInnes   Not Collective
5235c7afd0dbSLois Curfman McInnes 
52363c7409f5SSatish Balay   Input Parameter:
5237f6dfbefdSBarry Smith . snes - the `SNES` context
52383c7409f5SSatish Balay 
52393c7409f5SSatish Balay   Output Parameter:
52403c7409f5SSatish Balay . prefix - pointer to the prefix string used
52413c7409f5SSatish Balay 
524236851e7fSLois Curfman McInnes   Level: advanced
524336851e7fSLois Curfman McInnes 
52441cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
52453c7409f5SSatish Balay @*/
5246d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5247d71ae5a4SJacob Faibussowitsch {
52483a40ed3dSBarry Smith   PetscFunctionBegin;
52490700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52509566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
52513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52523c7409f5SSatish Balay }
52533c7409f5SSatish Balay 
52543cea93caSBarry Smith /*@C
52551c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
52561c84c290SBarry Smith 
525720f4b53cSBarry Smith   Not Collective
52581c84c290SBarry Smith 
52591c84c290SBarry Smith   Input Parameters:
526020f4b53cSBarry Smith + sname    - name of a new user-defined solver
526120f4b53cSBarry Smith - function - routine to create method context
52621c84c290SBarry Smith 
5263dc4c0fb0SBarry Smith   Level: advanced
5264dc4c0fb0SBarry Smith 
5265f6dfbefdSBarry Smith   Note:
5266f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
52671c84c290SBarry Smith 
5268e4094ef1SJacob Faibussowitsch   Example Usage:
52691c84c290SBarry Smith .vb
5270bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
52711c84c290SBarry Smith .ve
52721c84c290SBarry Smith 
52731c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
5274b44f4de4SBarry Smith .vb
5275b44f4de4SBarry Smith   SNESSetType(snes, "my_solver")
5276b44f4de4SBarry Smith .ve
52771c84c290SBarry Smith   or at runtime via the option
5278b44f4de4SBarry Smith .vb
5279b44f4de4SBarry Smith   -snes_type my_solver
5280b44f4de4SBarry Smith .ve
52811c84c290SBarry Smith 
52821cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
52833cea93caSBarry Smith @*/
5284d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5285d71ae5a4SJacob Faibussowitsch {
5286b2002411SLois Curfman McInnes   PetscFunctionBegin;
52879566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
52889566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
52893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5290b2002411SLois Curfman McInnes }
5291da9b6338SBarry Smith 
5292d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5293d71ae5a4SJacob Faibussowitsch {
529477431f27SBarry Smith   PetscInt    N, i, j;
5295da9b6338SBarry Smith   Vec         u, uh, fh;
5296da9b6338SBarry Smith   PetscScalar value;
5297da9b6338SBarry Smith   PetscReal   norm;
5298da9b6338SBarry Smith 
5299da9b6338SBarry Smith   PetscFunctionBegin;
53009566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
53019566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
53029566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5303da9b6338SBarry Smith 
5304da9b6338SBarry Smith   /* currently only works for sequential */
53059566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
53069566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5307da9b6338SBarry Smith   for (i = 0; i < N; i++) {
53089566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
530963a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5310da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
53118b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
53129566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
53139566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
53149566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
531563a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5316da9b6338SBarry Smith       value = -value;
53179566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5318da9b6338SBarry Smith     }
5319da9b6338SBarry Smith   }
53209566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
53219566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
53223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5323da9b6338SBarry Smith }
532471f87433Sdalcinl 
532571f87433Sdalcinl /*@
5326f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
532771f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
532871f87433Sdalcinl   Newton method.
532971f87433Sdalcinl 
5330c3339decSBarry Smith   Logically Collective
533171f87433Sdalcinl 
533271f87433Sdalcinl   Input Parameters:
5333f6dfbefdSBarry Smith + snes - `SNES` context
5334f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
533571f87433Sdalcinl 
5336f6dfbefdSBarry Smith   Options Database Keys:
533764ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
533864ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
533964ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
534064ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
534164ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
534264ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
534364ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
534464ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
534564ba62caSBarry Smith 
5346dc4c0fb0SBarry Smith   Level: advanced
5347dc4c0fb0SBarry Smith 
5348f6dfbefdSBarry Smith   Note:
5349f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
535071f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
53511d27aa22SBarry Smith   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
535271f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
535371f87433Sdalcinl   solver.
535471f87433Sdalcinl 
53551cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
535671f87433Sdalcinl @*/
5357d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5358d71ae5a4SJacob Faibussowitsch {
535971f87433Sdalcinl   PetscFunctionBegin;
53600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5361acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
536271f87433Sdalcinl   snes->ksp_ewconv = flag;
53633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
536471f87433Sdalcinl }
536571f87433Sdalcinl 
536671f87433Sdalcinl /*@
5367f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
536871f87433Sdalcinl   for computing relative tolerance for linear solvers within an
536971f87433Sdalcinl   inexact Newton method.
537071f87433Sdalcinl 
537171f87433Sdalcinl   Not Collective
537271f87433Sdalcinl 
537371f87433Sdalcinl   Input Parameter:
5374f6dfbefdSBarry Smith . snes - `SNES` context
537571f87433Sdalcinl 
537671f87433Sdalcinl   Output Parameter:
5377f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
537871f87433Sdalcinl 
537971f87433Sdalcinl   Level: advanced
538071f87433Sdalcinl 
53811cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
538271f87433Sdalcinl @*/
5383d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5384d71ae5a4SJacob Faibussowitsch {
538571f87433Sdalcinl   PetscFunctionBegin;
53860700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
53874f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
538871f87433Sdalcinl   *flag = snes->ksp_ewconv;
53893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
539071f87433Sdalcinl }
539171f87433Sdalcinl 
539271f87433Sdalcinl /*@
5393fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
539471f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
539571f87433Sdalcinl   Newton method.
539671f87433Sdalcinl 
5397c3339decSBarry Smith   Logically Collective
539871f87433Sdalcinl 
539971f87433Sdalcinl   Input Parameters:
5400f6dfbefdSBarry Smith + snes      - `SNES` context
54010f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
540271f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
540371f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
540471f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
540571f87433Sdalcinl              (0 <= gamma2 <= 1)
540671f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
540771f87433Sdalcinl . alpha2    - power for safeguard
540871f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
540971f87433Sdalcinl 
5410dc4c0fb0SBarry Smith   Level: advanced
5411dc4c0fb0SBarry Smith 
5412f6dfbefdSBarry Smith   Notes:
541371f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
541471f87433Sdalcinl 
541577e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the default for any of the parameters.
541671f87433Sdalcinl 
54171cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
541871f87433Sdalcinl @*/
5419d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5420d71ae5a4SJacob Faibussowitsch {
5421fa9f3622SBarry Smith   SNESKSPEW *kctx;
54225fd66863SKarl Rupp 
542371f87433Sdalcinl   PetscFunctionBegin;
54240700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5425fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
54265f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5427c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5428c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5429c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5430c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5431c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5432c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5433c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
543471f87433Sdalcinl 
543577e5a1f9SBarry Smith   if (version != PETSC_CURRENT) kctx->version = version;
543677e5a1f9SBarry Smith   if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0;
543777e5a1f9SBarry Smith   if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max;
543877e5a1f9SBarry Smith   if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma;
543977e5a1f9SBarry Smith   if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha;
544077e5a1f9SBarry Smith   if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2;
544177e5a1f9SBarry Smith   if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold;
544271f87433Sdalcinl 
54430f0abf79SStefano 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);
54440b121fc5SBarry 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);
54450b121fc5SBarry 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);
54460b121fc5SBarry 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);
54470b121fc5SBarry 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);
54480b121fc5SBarry 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);
54493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
545071f87433Sdalcinl }
545171f87433Sdalcinl 
545271f87433Sdalcinl /*@
5453fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
545471f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
545571f87433Sdalcinl   Newton method.
545671f87433Sdalcinl 
545771f87433Sdalcinl   Not Collective
545871f87433Sdalcinl 
545997bb3fdcSJose E. Roman   Input Parameter:
5460f6dfbefdSBarry Smith . snes - `SNES` context
546171f87433Sdalcinl 
546271f87433Sdalcinl   Output Parameters:
54630f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
546471f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
546571f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5466bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
546771f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
546871f87433Sdalcinl . alpha2    - power for safeguard
546971f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
547071f87433Sdalcinl 
547171f87433Sdalcinl   Level: advanced
547271f87433Sdalcinl 
54731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
547471f87433Sdalcinl @*/
5475d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5476d71ae5a4SJacob Faibussowitsch {
5477fa9f3622SBarry Smith   SNESKSPEW *kctx;
54785fd66863SKarl Rupp 
547971f87433Sdalcinl   PetscFunctionBegin;
54800700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5481fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
54825f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
548371f87433Sdalcinl   if (version) *version = kctx->version;
548471f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
548571f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
548671f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
548771f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
548871f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
548971f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
54903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
549171f87433Sdalcinl }
549271f87433Sdalcinl 
54935c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5494d71ae5a4SJacob Faibussowitsch {
54955c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5496fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
549777e5a1f9SBarry Smith   PetscReal  rtol = PETSC_CURRENT, stol;
549871f87433Sdalcinl 
549971f87433Sdalcinl   PetscFunctionBegin;
55003ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
550130058271SDmitry Karpeev   if (!snes->iter) {
550230058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
55039566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
55040f0abf79SStefano Zampini   } else {
55050fdf79fbSJacob 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);
550671f87433Sdalcinl     if (kctx->version == 1) {
55070f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
550885ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
550971f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
551071f87433Sdalcinl     } else if (kctx->version == 2) {
551185ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
551285ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
551371f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
551471f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
551585ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
551671f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
551785ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
551871f87433Sdalcinl       stol = PetscMax(rtol, stol);
551971f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
552071f87433Sdalcinl       /* safeguard: avoid oversolving */
552130058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
552271f87433Sdalcinl       stol = PetscMax(rtol, stol);
552371f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
55240fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
55250fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
55260f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
55270f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
55280f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
55290f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
55300f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
55310f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
55320f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
55330f0abf79SStefano Zampini 
5534a4598233SStefano 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;
55350f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
55360f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
55370f0abf79SStefano Zampini       kctx->rk_last     = rk;
55380fdf79fbSJacob Faibussowitsch     }
55390f0abf79SStefano Zampini   }
55400f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
554171f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
554277e5a1f9SBarry Smith   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT));
554363a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
55443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
554571f87433Sdalcinl }
554671f87433Sdalcinl 
55475c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5548d71ae5a4SJacob Faibussowitsch {
55495c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5550fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
555171f87433Sdalcinl   PCSide     pcside;
555271f87433Sdalcinl   Vec        lres;
555371f87433Sdalcinl 
555471f87433Sdalcinl   PetscFunctionBegin;
55553ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
55569566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
555771dbe336SPeter Brune   kctx->norm_last = snes->norm;
55580f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
55594f00ce20SMatthew G. Knepley     PC        pc;
55600f0abf79SStefano Zampini     PetscBool getRes;
55614f00ce20SMatthew G. Knepley 
55629566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
55630f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
55640f0abf79SStefano Zampini     if (!getRes) {
55650f0abf79SStefano Zampini       KSPNormType normtype;
55660f0abf79SStefano Zampini 
55670f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
55680f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
55690f0abf79SStefano Zampini     }
55709566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
55710f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
55729566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
557371f87433Sdalcinl     } else {
557471f87433Sdalcinl       /* KSP residual is preconditioned residual */
557571f87433Sdalcinl       /* compute true linear residual norm */
55760f0abf79SStefano Zampini       Mat J;
55770f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
55789566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
55790f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
55809566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
55819566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
55829566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
558371f87433Sdalcinl     }
558471f87433Sdalcinl   }
55853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
558671f87433Sdalcinl }
558771f87433Sdalcinl 
5588d4211eb9SBarry Smith /*@
5589f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5590d4211eb9SBarry Smith 
5591420bcc1bSBarry Smith   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5592d4211eb9SBarry Smith 
5593d4211eb9SBarry Smith   Input Parameter:
5594f6dfbefdSBarry Smith . snes - the `SNES` context
5595d4211eb9SBarry Smith 
5596d4211eb9SBarry Smith   Output Parameter:
5597f6dfbefdSBarry Smith . ksp - the `KSP` context
5598d4211eb9SBarry Smith 
5599dc4c0fb0SBarry Smith   Level: beginner
5600dc4c0fb0SBarry Smith 
5601d4211eb9SBarry Smith   Notes:
5602f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5603d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5604f6dfbefdSBarry Smith   `PC` contexts as well.
5605f6dfbefdSBarry Smith 
56060b4b7b1cSBarry 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.
5607d4211eb9SBarry Smith 
56081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5609d4211eb9SBarry Smith @*/
5610d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5611d71ae5a4SJacob Faibussowitsch {
561271f87433Sdalcinl   PetscFunctionBegin;
5613d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56144f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5615d4211eb9SBarry Smith 
5616d4211eb9SBarry Smith   if (!snes->ksp) {
56179566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
56189566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5619d4211eb9SBarry Smith 
56205c0db29aSPierre Jolivet     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
56215c0db29aSPierre Jolivet     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5622a5c2985bSBarry Smith 
56239566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
56249566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5625d4211eb9SBarry Smith   }
5626d4211eb9SBarry Smith   *ksp = snes->ksp;
56273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
562871f87433Sdalcinl }
56296c699258SBarry Smith 
5630af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
56316c699258SBarry Smith /*@
56320b4b7b1cSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners
56336c699258SBarry Smith 
5634c3339decSBarry Smith   Logically Collective
56356c699258SBarry Smith 
56366c699258SBarry Smith   Input Parameters:
56372a808120SBarry Smith + snes - the nonlinear solver context
5638420bcc1bSBarry Smith - dm   - the `DM`, cannot be `NULL`
5639dc4c0fb0SBarry Smith 
5640dc4c0fb0SBarry Smith   Level: intermediate
56416c699258SBarry Smith 
5642f6dfbefdSBarry Smith   Note:
5643f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5644f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5645e03a659cSJed Brown   problems using the same function space.
5646e03a659cSJed Brown 
5647420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
56486c699258SBarry Smith @*/
5649d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5650d71ae5a4SJacob Faibussowitsch {
5651345fed2cSBarry Smith   KSP    ksp;
5652942e3340SBarry Smith   DMSNES sdm;
56536c699258SBarry Smith 
56546c699258SBarry Smith   PetscFunctionBegin;
56550700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56562a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
56579566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5658942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
565951f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
56609566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
56619566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5662f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
56636cab3a1bSJed Brown     }
56649566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
56659566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
56666cab3a1bSJed Brown   }
56676c699258SBarry Smith   snes->dm     = dm;
5668116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5669f5af7f23SKarl Rupp 
56709566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
56719566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
56729566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5673efd4aadfSBarry Smith   if (snes->npc) {
56749566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
56759566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
56762c155ee1SBarry Smith   }
56773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56786c699258SBarry Smith }
56796c699258SBarry Smith 
56806c699258SBarry Smith /*@
56810b4b7b1cSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners
56826c699258SBarry Smith 
56830b4b7b1cSBarry Smith   Not Collective but `dm` obtained is parallel on `snes`
56846c699258SBarry Smith 
56856c699258SBarry Smith   Input Parameter:
5686420bcc1bSBarry Smith . snes - the `SNES` context
56876c699258SBarry Smith 
56886c699258SBarry Smith   Output Parameter:
5689420bcc1bSBarry Smith . dm - the `DM`
56906c699258SBarry Smith 
56916c699258SBarry Smith   Level: intermediate
56926c699258SBarry Smith 
5693420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
56946c699258SBarry Smith @*/
5695d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5696d71ae5a4SJacob Faibussowitsch {
56976c699258SBarry Smith   PetscFunctionBegin;
56980700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56996cab3a1bSJed Brown   if (!snes->dm) {
57009566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5701116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
57026cab3a1bSJed Brown   }
57036c699258SBarry Smith   *dm = snes->dm;
57043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57056c699258SBarry Smith }
57060807856dSBarry Smith 
570731823bd8SMatthew G Knepley /*@
5708be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
570931823bd8SMatthew G Knepley 
5710c3339decSBarry Smith   Collective
571131823bd8SMatthew G Knepley 
571231823bd8SMatthew G Knepley   Input Parameters:
5713f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
571462842358SBarry Smith - npc  - the `SNES` nonlinear preconditioner object
571562842358SBarry Smith 
571662842358SBarry Smith   Options Database Key:
571762842358SBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
571831823bd8SMatthew G Knepley 
5719dc4c0fb0SBarry Smith   Level: developer
5720dc4c0fb0SBarry Smith 
572131823bd8SMatthew G Knepley   Notes:
572262842358SBarry Smith   This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API.
572331823bd8SMatthew G Knepley 
5724f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5725f6dfbefdSBarry Smith 
5726420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
572731823bd8SMatthew G Knepley @*/
5728d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5729d71ae5a4SJacob Faibussowitsch {
573031823bd8SMatthew G Knepley   PetscFunctionBegin;
573131823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5732f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5733f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5734f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
57359566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5736f6dfbefdSBarry Smith   snes->npc = npc;
57373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
573831823bd8SMatthew G Knepley }
573931823bd8SMatthew G Knepley 
574031823bd8SMatthew G Knepley /*@
5741f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
574231823bd8SMatthew G Knepley 
57430b4b7b1cSBarry Smith   Not Collective; but any changes to the obtained the `pc` object must be applied collectively
574431823bd8SMatthew G Knepley 
574531823bd8SMatthew G Knepley   Input Parameter:
5746f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
574731823bd8SMatthew G Knepley 
574831823bd8SMatthew G Knepley   Output Parameter:
574962842358SBarry Smith . pc - the `SNES` preconditioner context
575031823bd8SMatthew G Knepley 
5751f6dfbefdSBarry Smith   Options Database Key:
5752f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5753b5badacbSBarry Smith 
57540b4b7b1cSBarry Smith   Level: advanced
5755dc4c0fb0SBarry Smith 
575695452b02SPatrick Sanan   Notes:
57570b4b7b1cSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will
57580b4b7b1cSBarry Smith   be used as the nonlinear preconditioner for the current `SNES`.
5759be95d8f1SBarry Smith 
5760f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
576162842358SBarry Smith   `SNES`. These may be overwritten if needed.
576262842358SBarry Smith 
576362842358SBarry Smith   Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner
5764951fe5abSBarry Smith 
57651cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
576631823bd8SMatthew G Knepley @*/
5767d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5768d71ae5a4SJacob Faibussowitsch {
5769a64e098fSPeter Brune   const char *optionsprefix;
577031823bd8SMatthew G Knepley 
577131823bd8SMatthew G Knepley   PetscFunctionBegin;
577231823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57734f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5774efd4aadfSBarry Smith   if (!snes->npc) {
5775ec785e5bSStefano Zampini     void *ctx;
5776ec785e5bSStefano Zampini 
57779566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
57789566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
57799566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
57809566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
57819566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5782fb87a551SStefano Zampini     if (snes->ops->usercompute) {
578349abdd8aSBarry Smith       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy));
5784fb87a551SStefano Zampini     } else {
5785ec785e5bSStefano Zampini       PetscCall(SNESGetApplicationContext(snes, &ctx));
5786ec785e5bSStefano Zampini       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5787fb87a551SStefano Zampini     }
57889566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
578931823bd8SMatthew G Knepley   }
5790efd4aadfSBarry Smith   *pc = snes->npc;
57913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
579231823bd8SMatthew G Knepley }
579331823bd8SMatthew G Knepley 
57943ad1a0b9SPatrick Farrell /*@
57950b4b7b1cSBarry Smith   SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES`
57963ad1a0b9SPatrick Farrell 
57973ad1a0b9SPatrick Farrell   Not Collective
57983ad1a0b9SPatrick Farrell 
57993ad1a0b9SPatrick Farrell   Input Parameter:
5800f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
58013ad1a0b9SPatrick Farrell 
58023ad1a0b9SPatrick Farrell   Output Parameter:
5803420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
58043ad1a0b9SPatrick Farrell 
58053ad1a0b9SPatrick Farrell   Level: developer
58063ad1a0b9SPatrick Farrell 
58071cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
58083ad1a0b9SPatrick Farrell @*/
5809d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5810d71ae5a4SJacob Faibussowitsch {
58113ad1a0b9SPatrick Farrell   PetscFunctionBegin;
58123ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5813835f2295SStefano Zampini   PetscAssertPointer(has_npc, 2);
5814835f2295SStefano Zampini   *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE;
58153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58163ad1a0b9SPatrick Farrell }
58173ad1a0b9SPatrick Farrell 
5818c40d0f55SPeter Brune /*@
581962842358SBarry Smith   SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`.
5820c40d0f55SPeter Brune 
5821c3339decSBarry Smith   Logically Collective
5822c40d0f55SPeter Brune 
5823c40d0f55SPeter Brune   Input Parameter:
5824f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5825c40d0f55SPeter Brune 
5826c40d0f55SPeter Brune   Output Parameter:
5827c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5828c40d0f55SPeter Brune .vb
58292d547940SBarry Smith       PC_LEFT  - left preconditioning
58302d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5831c40d0f55SPeter Brune .ve
5832c40d0f55SPeter Brune 
5833f6dfbefdSBarry Smith   Options Database Key:
583467b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5835c40d0f55SPeter Brune 
5836dc4c0fb0SBarry Smith   Level: intermediate
5837dc4c0fb0SBarry Smith 
5838f6dfbefdSBarry Smith   Note:
5839f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
58402d547940SBarry Smith 
584162842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5842c40d0f55SPeter Brune @*/
5843d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5844d71ae5a4SJacob Faibussowitsch {
5845c40d0f55SPeter Brune   PetscFunctionBegin;
5846c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5847c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5848b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
584954c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5850efd4aadfSBarry Smith   snes->npcside = side;
58513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5852c40d0f55SPeter Brune }
5853c40d0f55SPeter Brune 
5854c40d0f55SPeter Brune /*@
585562842358SBarry Smith   SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`.
5856c40d0f55SPeter Brune 
5857c40d0f55SPeter Brune   Not Collective
5858c40d0f55SPeter Brune 
5859c40d0f55SPeter Brune   Input Parameter:
5860f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5861c40d0f55SPeter Brune 
5862c40d0f55SPeter Brune   Output Parameter:
5863c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5864c40d0f55SPeter Brune .vb
5865f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5866f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5867c40d0f55SPeter Brune .ve
5868c40d0f55SPeter Brune 
5869c40d0f55SPeter Brune   Level: intermediate
5870c40d0f55SPeter Brune 
587162842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5872c40d0f55SPeter Brune @*/
5873d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5874d71ae5a4SJacob Faibussowitsch {
5875c40d0f55SPeter Brune   PetscFunctionBegin;
5876c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58774f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5878efd4aadfSBarry Smith   *side = snes->npcside;
58793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5880c40d0f55SPeter Brune }
5881c40d0f55SPeter Brune 
58829e764e56SPeter Brune /*@
58830b4b7b1cSBarry Smith   SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES`
58849e764e56SPeter Brune 
5885c3339decSBarry Smith   Collective
58869e764e56SPeter Brune 
58879e764e56SPeter Brune   Input Parameters:
5888f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
58899e764e56SPeter Brune - linesearch - the linesearch object
58909e764e56SPeter Brune 
5891dc4c0fb0SBarry Smith   Level: developer
5892dc4c0fb0SBarry Smith 
5893f6dfbefdSBarry Smith   Note:
5894420bcc1bSBarry Smith   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
58959e764e56SPeter Brune   to configure it using the API).
58969e764e56SPeter Brune 
5897420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
58989e764e56SPeter Brune @*/
5899d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5900d71ae5a4SJacob Faibussowitsch {
59019e764e56SPeter Brune   PetscFunctionBegin;
59029e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5903f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
59049e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
59059566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
59069566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5907f5af7f23SKarl Rupp 
59089e764e56SPeter Brune   snes->linesearch = linesearch;
59093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59109e764e56SPeter Brune }
59119e764e56SPeter Brune 
5912a34ceb2aSJed Brown /*@
591362842358SBarry Smith   SNESGetLineSearch - Returns the line search associated with the `SNES`.
59149e764e56SPeter Brune 
59159e764e56SPeter Brune   Not Collective
59169e764e56SPeter Brune 
59179e764e56SPeter Brune   Input Parameter:
5918f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
59199e764e56SPeter Brune 
59209e764e56SPeter Brune   Output Parameter:
59219e764e56SPeter Brune . linesearch - linesearch context
59229e764e56SPeter Brune 
5923162e0bf5SPeter Brune   Level: beginner
59249e764e56SPeter Brune 
592562842358SBarry Smith   Notes:
592662842358SBarry Smith   It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`.
592762842358SBarry Smith 
592862842358SBarry Smith   You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options.
592962842358SBarry Smith 
593062842358SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`
59319e764e56SPeter Brune @*/
5932d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5933d71ae5a4SJacob Faibussowitsch {
59349e764e56SPeter Brune   const char *optionsprefix;
59359e764e56SPeter Brune 
59369e764e56SPeter Brune   PetscFunctionBegin;
59379e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
59384f572ea9SToby Isaac   PetscAssertPointer(linesearch, 2);
59399e764e56SPeter Brune   if (!snes->linesearch) {
59409566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
59419566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
59429566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
59439566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
59449566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
59459e764e56SPeter Brune   }
59469e764e56SPeter Brune   *linesearch = snes->linesearch;
59473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59489e764e56SPeter Brune }
5949