xref: /petsc/src/snes/interface/snes.c (revision 56296ac476a31e7af9f50f16bc583419343e72e5)
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 
1206b1535e8SBarry 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:
1286b1535e8SBarry Smith   This does not need to be called by all processes in the `SNES` MPI communicator.
1296b1535e8SBarry 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 
1376b1535e8SBarry Smith   You can call `SNESSetJacobianDomainError()` during a Jacobian computation to indicate the proposed solution is not in the domain.
1386b1535e8SBarry Smith 
1396b1535e8SBarry Smith   Developer Note:
1406b1535e8SBarry Smith   This value is used by `SNESCheckFunctionNorm()` to determine if the `SNESConvergedReason` is set to `SNES_DIVERGED_FUNCTION_DOMAIN`
1416b1535e8SBarry Smith 
1428434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`,
1436b1535e8SBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`,
1446b1535e8SBarry 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 
2376b1535e8SBarry 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 
2476b1535e8SBarry Smith   Notes:
2486b1535e8SBarry Smith   The value will only be true on those MPI processes that called `SNESSetFunctionDomainError()`
2496b1535e8SBarry Smith 
2506b1535e8SBarry Smith   The value is reset to `PETSC_FALSE` when `SNESCheckFunctionNorm()` is called.
2516b1535e8SBarry 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 
2666b1535e8SBarry 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 
2766b1535e8SBarry Smith   Notes:
2776b1535e8SBarry Smith   The value will only be true on those MPI processes that called `SNESSetJacobianDomainError()`
2786b1535e8SBarry Smith 
2796b1535e8SBarry Smith   The value is reset to `PETSC_FALSE` when `SNESCheckJacobianDomainerror()` is called but only `SNESSetCheckJacobianDomainError()` was called
2806b1535e8SBarry 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;
4049f196a02SMartin Diehl   PetscBool      isascii, 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 
4169f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
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
4239f196a02SMartin Diehl   if (isascii) {
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 
826d6acfc2dSPierre Jolivet PETSC_SINGLE_LIBRARY_INTERN 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 
11431dfd7622SMatthew Knepley   PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference functions", "None", &snes->testFunc));
11441dfd7622SMatthew Knepley   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &snes->testJac));
11451dfd7622SMatthew Knepley 
1146c40d0f55SPeter Brune   flg = PETSC_FALSE;
11479566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11499566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1150c40d0f55SPeter Brune 
1151e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11528a70d858SHong Zhang   /*
11538a70d858SHong Zhang     Publish convergence information using SAWs
11548a70d858SHong Zhang   */
11558a70d858SHong Zhang   flg = PETSC_FALSE;
11569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11578a70d858SHong Zhang   if (flg) {
11588a70d858SHong Zhang     void *ctx;
11599566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11609566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11618a70d858SHong Zhang   }
11628a70d858SHong Zhang #endif
11638a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1164b90c6cbeSBarry Smith   {
1165b90c6cbeSBarry Smith     PetscBool set;
1166b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11679566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11681baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1169b90c6cbeSBarry Smith   }
1170b90c6cbeSBarry Smith #endif
1171b90c6cbeSBarry Smith 
117248a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
117376b2cf59SMatthew Knepley 
1174dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11755d973c19SBarry Smith 
11765d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1177dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1178d0609cedSBarry Smith   PetscOptionsEnd();
11794bbc92c1SBarry Smith 
1180d8d34be6SBarry Smith   if (snes->linesearch) {
11819566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11829566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1183d8d34be6SBarry Smith   }
11849e764e56SPeter Brune 
11856aa5e7e9SBarry Smith   if (snes->usesksp) {
11869566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11879566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11889566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11896aa5e7e9SBarry Smith   }
11906991f827SBarry Smith 
1191b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11929566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
119448a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11951baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1196b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1198b3cd9a81SMatthew G. Knepley }
1199b3cd9a81SMatthew G. Knepley 
1200b3cd9a81SMatthew G. Knepley /*@
1201420bcc1bSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1202b3cd9a81SMatthew G. Knepley 
1203c3339decSBarry Smith   Collective
1204b3cd9a81SMatthew G. Knepley 
1205b3cd9a81SMatthew G. Knepley   Input Parameter:
1206f6dfbefdSBarry Smith . snes - the `SNES` context
1207b3cd9a81SMatthew G. Knepley 
1208420bcc1bSBarry Smith   Level: advanced
1209b3cd9a81SMatthew G. Knepley 
12101cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1211b3cd9a81SMatthew G. Knepley @*/
1212d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1213d71ae5a4SJacob Faibussowitsch {
1214b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
12159566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
12163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12179b94acceSBarry Smith }
12189b94acceSBarry Smith 
1219bb9467b5SJed Brown /*@C
1220d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1221d25893d9SBarry Smith   the nonlinear solvers.
1222d25893d9SBarry Smith 
1223dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1224d25893d9SBarry Smith 
1225d25893d9SBarry Smith   Input Parameters:
1226f6dfbefdSBarry Smith + snes    - the `SNES` context
1227d25893d9SBarry Smith . compute - function to compute the context
122849abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence
1229d25893d9SBarry Smith 
1230420bcc1bSBarry Smith   Calling sequence of `compute`:
1231420bcc1bSBarry Smith + snes - the `SNES` context
1232420bcc1bSBarry Smith - ctx  - context to be computed
1233420bcc1bSBarry Smith 
1234d25893d9SBarry Smith   Level: intermediate
1235d25893d9SBarry Smith 
1236f6dfbefdSBarry Smith   Note:
1237f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1238f6dfbefdSBarry Smith 
1239f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1240f6dfbefdSBarry Smith 
124149abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn`
1242d25893d9SBarry Smith @*/
124349abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy)
1244d71ae5a4SJacob Faibussowitsch {
1245d25893d9SBarry Smith   PetscFunctionBegin;
1246d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1247d25893d9SBarry Smith   snes->ops->usercompute = compute;
124849abdd8aSBarry Smith   snes->ops->ctxdestroy  = destroy;
12493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1250d25893d9SBarry Smith }
1251a847f771SSatish Balay 
1252b07ff414SBarry Smith /*@
1253f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12549b94acceSBarry Smith 
1255c3339decSBarry Smith   Logically Collective
1256fee21e36SBarry Smith 
1257c7afd0dbSLois Curfman McInnes   Input Parameters:
1258f6dfbefdSBarry Smith + snes - the `SNES` context
1259ce78bad3SBarry Smith - ctx  - the user context
1260c7afd0dbSLois Curfman McInnes 
126136851e7fSLois Curfman McInnes   Level: intermediate
126236851e7fSLois Curfman McInnes 
1263f6dfbefdSBarry Smith   Notes:
1264ce78bad3SBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function
1265f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1266f6dfbefdSBarry Smith 
1267f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1268f6dfbefdSBarry Smith 
1269420bcc1bSBarry Smith   Fortran Note:
1270ce78bad3SBarry 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
1271ce78bad3SBarry Smith   function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for
1272ce78bad3SBarry Smith   an example.
1273daf670e6SBarry Smith 
12741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12759b94acceSBarry Smith @*/
127649abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx)
1277d71ae5a4SJacob Faibussowitsch {
1278b07ff414SBarry Smith   KSP ksp;
12791b2093e4SBarry Smith 
12803a40ed3dSBarry Smith   PetscFunctionBegin;
12810700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12829566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
128349abdd8aSBarry Smith   PetscCall(KSPSetApplicationContext(ksp, ctx));
128449abdd8aSBarry Smith   snes->ctx = ctx;
12853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12869b94acceSBarry Smith }
128774679c65SBarry Smith 
1288b07ff414SBarry Smith /*@
12899b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1290420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12919b94acceSBarry Smith 
1292c7afd0dbSLois Curfman McInnes   Not Collective
1293c7afd0dbSLois Curfman McInnes 
12949b94acceSBarry Smith   Input Parameter:
1295f6dfbefdSBarry Smith . snes - `SNES` context
12969b94acceSBarry Smith 
12979b94acceSBarry Smith   Output Parameter:
129849abdd8aSBarry Smith . ctx - user context
12999b94acceSBarry Smith 
130036851e7fSLois Curfman McInnes   Level: intermediate
130136851e7fSLois Curfman McInnes 
1302ce78bad3SBarry Smith   Fortran Notes:
1303ce78bad3SBarry 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
1304ce78bad3SBarry Smith   function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example,
1305ce78bad3SBarry Smith .vb
1306ce78bad3SBarry Smith   Interface SNESGetApplicationContext
1307ce78bad3SBarry Smith     Subroutine SNESGetApplicationContext(snes,ctx,ierr)
1308ce78bad3SBarry Smith   #include <petsc/finclude/petscsnes.h>
1309ce78bad3SBarry Smith       use petscsnes
1310ce78bad3SBarry Smith       SNES snes
1311ce78bad3SBarry Smith       type(tUsertype), pointer :: ctx
1312ce78bad3SBarry Smith       PetscErrorCode ierr
1313ce78bad3SBarry Smith     End Subroutine
1314ce78bad3SBarry Smith   End Interface SNESGetApplicationContext
1315ce78bad3SBarry Smith .ve
1316ce78bad3SBarry Smith 
1317bfe80ac4SPierre Jolivet   The prototype for `ctx` must be
1318ce78bad3SBarry Smith .vb
1319ce78bad3SBarry Smith   type(tUsertype), pointer :: ctx
1320ce78bad3SBarry Smith .ve
1321dc4c0fb0SBarry Smith 
1322420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
13239b94acceSBarry Smith @*/
1324ce78bad3SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PeCtx ctx)
1325d71ae5a4SJacob Faibussowitsch {
13263a40ed3dSBarry Smith   PetscFunctionBegin;
13270700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
132849abdd8aSBarry Smith   *(void **)ctx = snes->ctx;
13293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13309b94acceSBarry Smith }
133174679c65SBarry Smith 
13329b94acceSBarry Smith /*@
1333420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
13343565c898SBarry Smith 
1335dc4c0fb0SBarry Smith   Logically Collective
13363565c898SBarry Smith 
13373565c898SBarry Smith   Input Parameters:
1338f6dfbefdSBarry Smith + snes        - `SNES` context
1339f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1340f6dfbefdSBarry 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
1341420bcc1bSBarry Smith                 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
13423565c898SBarry Smith 
1343f6dfbefdSBarry Smith   Options Database Keys:
134401c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1345f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1346ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1347ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
13483565c898SBarry Smith 
13493565c898SBarry Smith   Level: intermediate
13503565c898SBarry Smith 
1351f6dfbefdSBarry Smith   Note:
1352420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1353420bcc1bSBarry Smith   and computing explicitly with
1354f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1355ec5066bdSBarry Smith 
1356420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13573565c898SBarry Smith @*/
1358d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1359d71ae5a4SJacob Faibussowitsch {
13603565c898SBarry Smith   PetscFunctionBegin;
13613565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
136288b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
136388b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13644ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13653565c898SBarry Smith   snes->mf_operator = mf_operator;
13663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13673565c898SBarry Smith }
13683565c898SBarry Smith 
13693565c898SBarry Smith /*@
1370dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13713565c898SBarry Smith 
1372420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13733565c898SBarry Smith 
13743565c898SBarry Smith   Input Parameter:
1375f6dfbefdSBarry Smith . snes - `SNES` context
13763565c898SBarry Smith 
13773565c898SBarry Smith   Output Parameters:
1378f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1379f6dfbefdSBarry 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
13803565c898SBarry Smith 
13813565c898SBarry Smith   Level: intermediate
13823565c898SBarry Smith 
13831cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13843565c898SBarry Smith @*/
1385d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1386d71ae5a4SJacob Faibussowitsch {
13873565c898SBarry Smith   PetscFunctionBegin;
13883565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13893565c898SBarry Smith   if (mf) *mf = snes->mf;
13903565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13923565c898SBarry Smith }
13933565c898SBarry Smith 
13943565c898SBarry Smith /*@
1395420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13969b94acceSBarry Smith 
1397c7afd0dbSLois Curfman McInnes   Not Collective
1398c7afd0dbSLois Curfman McInnes 
13999b94acceSBarry Smith   Input Parameter:
1400f6dfbefdSBarry Smith . snes - `SNES` context
14019b94acceSBarry Smith 
14029b94acceSBarry Smith   Output Parameter:
14039b94acceSBarry Smith . iter - iteration number
14049b94acceSBarry Smith 
1405dc4c0fb0SBarry Smith   Level: intermediate
1406dc4c0fb0SBarry Smith 
1407c8228a4eSBarry Smith   Notes:
1408c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1409c8228a4eSBarry Smith 
1410c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1411f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
141208405cd6SLois Curfman McInnes .vb
141308405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
141408405cd6SLois Curfman McInnes       if (!(it % 2)) {
141508405cd6SLois Curfman McInnes         [compute Jacobian here]
141608405cd6SLois Curfman McInnes       }
141708405cd6SLois Curfman McInnes .ve
1418f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1419f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1420c8228a4eSBarry Smith 
1421f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1422c04deec6SBarry Smith 
1423420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
14249b94acceSBarry Smith @*/
1425d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1426d71ae5a4SJacob Faibussowitsch {
14273a40ed3dSBarry Smith   PetscFunctionBegin;
14280700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14294f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
14309b94acceSBarry Smith   *iter = snes->iter;
14313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14329b94acceSBarry Smith }
143374679c65SBarry Smith 
1434360c497dSPeter Brune /*@
1435360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1436360c497dSPeter Brune 
1437360c497dSPeter Brune   Not Collective
1438360c497dSPeter Brune 
1439d8d19677SJose E. Roman   Input Parameters:
1440f6dfbefdSBarry Smith + snes - `SNES` context
1441a2b725a8SWilliam Gropp - iter - iteration number
1442360c497dSPeter Brune 
1443360c497dSPeter Brune   Level: developer
1444360c497dSPeter Brune 
1445420bcc1bSBarry Smith   Note:
1446420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1447420bcc1bSBarry Smith 
14481cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1449360c497dSPeter Brune @*/
1450d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1451d71ae5a4SJacob Faibussowitsch {
1452360c497dSPeter Brune   PetscFunctionBegin;
1453360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14549566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1455360c497dSPeter Brune   snes->iter = iter;
14569566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1458360c497dSPeter Brune }
1459360c497dSPeter Brune 
14609b94acceSBarry Smith /*@
1461b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1462420bcc1bSBarry Smith   attempted by the nonlinear solver in the current or most recent `SNESSolve()` .
14639b94acceSBarry Smith 
1464c7afd0dbSLois Curfman McInnes   Not Collective
1465c7afd0dbSLois Curfman McInnes 
14669b94acceSBarry Smith   Input Parameter:
1467f6dfbefdSBarry Smith . snes - `SNES` context
14689b94acceSBarry Smith 
14699b94acceSBarry Smith   Output Parameter:
14709b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14719b94acceSBarry Smith 
1472dc4c0fb0SBarry Smith   Level: intermediate
1473dc4c0fb0SBarry Smith 
1474f6dfbefdSBarry Smith   Note:
1475f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1476c96a6f78SLois Curfman McInnes 
14771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1478db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14799b94acceSBarry Smith @*/
1480d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1481d71ae5a4SJacob Faibussowitsch {
14823a40ed3dSBarry Smith   PetscFunctionBegin;
14830700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14844f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
148550ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
148750ffb88aSMatthew Knepley }
148850ffb88aSMatthew Knepley 
148950ffb88aSMatthew Knepley /*@
1490b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1491420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
149250ffb88aSMatthew Knepley 
149350ffb88aSMatthew Knepley   Not Collective
149450ffb88aSMatthew Knepley 
149550ffb88aSMatthew Knepley   Input Parameters:
1496f6dfbefdSBarry Smith + snes     - `SNES` context
149777e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures
149850ffb88aSMatthew Knepley 
1499420bcc1bSBarry Smith   Options Database Key:
1500420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1501420bcc1bSBarry Smith 
150250ffb88aSMatthew Knepley   Level: intermediate
150350ffb88aSMatthew Knepley 
1504420bcc1bSBarry Smith   Developer Note:
1505420bcc1bSBarry Smith   The options database key is wrong for this function name
1506420bcc1bSBarry Smith 
15071cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1508db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
150950ffb88aSMatthew Knepley @*/
1510d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1511d71ae5a4SJacob Faibussowitsch {
151250ffb88aSMatthew Knepley   PetscFunctionBegin;
15130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
151477e5a1f9SBarry Smith 
151577e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
15161690c2aeSBarry Smith     snes->maxFailures = PETSC_INT_MAX;
151777e5a1f9SBarry Smith   } else {
151877e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
151950ffb88aSMatthew Knepley     snes->maxFailures = maxFails;
152077e5a1f9SBarry Smith   }
15213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
152250ffb88aSMatthew Knepley }
152350ffb88aSMatthew Knepley 
152450ffb88aSMatthew Knepley /*@
1525b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1526420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
152750ffb88aSMatthew Knepley 
152850ffb88aSMatthew Knepley   Not Collective
152950ffb88aSMatthew Knepley 
153050ffb88aSMatthew Knepley   Input Parameter:
153120f4b53cSBarry Smith . snes - `SNES` context
153250ffb88aSMatthew Knepley 
153350ffb88aSMatthew Knepley   Output Parameter:
153450ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
153550ffb88aSMatthew Knepley 
153650ffb88aSMatthew Knepley   Level: intermediate
153750ffb88aSMatthew Knepley 
15381cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1539db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
154050ffb88aSMatthew Knepley @*/
1541d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1542d71ae5a4SJacob Faibussowitsch {
154350ffb88aSMatthew Knepley   PetscFunctionBegin;
15440700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15454f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
154650ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
15473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15489b94acceSBarry Smith }
1549a847f771SSatish Balay 
15502541af92SBarry Smith /*@
15512541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1552420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
15532541af92SBarry Smith 
15542541af92SBarry Smith   Not Collective
15552541af92SBarry Smith 
15562541af92SBarry Smith   Input Parameter:
1557f6dfbefdSBarry Smith . snes - `SNES` context
15582541af92SBarry Smith 
15592541af92SBarry Smith   Output Parameter:
15602541af92SBarry Smith . nfuncs - number of evaluations
15612541af92SBarry Smith 
15622541af92SBarry Smith   Level: intermediate
15632541af92SBarry Smith 
1564f6dfbefdSBarry Smith   Note:
1565f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1566971e163fSPeter Brune 
15671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15682541af92SBarry Smith @*/
1569d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1570d71ae5a4SJacob Faibussowitsch {
15712541af92SBarry Smith   PetscFunctionBegin;
15720700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15734f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15742541af92SBarry Smith   *nfuncs = snes->nfuncs;
15753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15762541af92SBarry Smith }
15772541af92SBarry Smith 
15783d4c4710SBarry Smith /*@
15793d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1580420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15813d4c4710SBarry Smith 
15823d4c4710SBarry Smith   Not Collective
15833d4c4710SBarry Smith 
15843d4c4710SBarry Smith   Input Parameter:
1585f6dfbefdSBarry Smith . snes - `SNES` context
15863d4c4710SBarry Smith 
15873d4c4710SBarry Smith   Output Parameter:
15883d4c4710SBarry Smith . nfails - number of failed solves
15893d4c4710SBarry Smith 
1590f6dfbefdSBarry Smith   Options Database Key:
15919d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15929d85da0cSMatthew G. Knepley 
1593f6dfbefdSBarry Smith   Level: intermediate
1594f6dfbefdSBarry Smith 
1595f6dfbefdSBarry Smith   Note:
1596f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15973d4c4710SBarry Smith 
15981cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15993d4c4710SBarry Smith @*/
1600d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1601d71ae5a4SJacob Faibussowitsch {
16023d4c4710SBarry Smith   PetscFunctionBegin;
16030700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16044f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
16053d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
16063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16073d4c4710SBarry Smith }
16083d4c4710SBarry Smith 
16093d4c4710SBarry Smith /*@
16103d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1611f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
16123d4c4710SBarry Smith 
1613c3339decSBarry Smith   Logically Collective
16143d4c4710SBarry Smith 
16153d4c4710SBarry Smith   Input Parameters:
1616f6dfbefdSBarry Smith + snes     - `SNES` context
161777e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures
16183d4c4710SBarry Smith 
1619f6dfbefdSBarry Smith   Options Database Key:
16209d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
16219d85da0cSMatthew G. Knepley 
1622dc4c0fb0SBarry Smith   Level: intermediate
1623dc4c0fb0SBarry Smith 
1624f6dfbefdSBarry Smith   Note:
1625f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
16263d4c4710SBarry Smith 
1627420bcc1bSBarry Smith   Developer Note:
1628420bcc1bSBarry Smith   The options database key is wrong for this function name
1629420bcc1bSBarry Smith 
16301cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
16313d4c4710SBarry Smith @*/
1632d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1633d71ae5a4SJacob Faibussowitsch {
16343d4c4710SBarry Smith   PetscFunctionBegin;
16350700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1636c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
163777e5a1f9SBarry Smith 
163877e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
16391690c2aeSBarry Smith     snes->maxLinearSolveFailures = PETSC_INT_MAX;
164077e5a1f9SBarry Smith   } else {
164177e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
16423d4c4710SBarry Smith     snes->maxLinearSolveFailures = maxFails;
164377e5a1f9SBarry Smith   }
16443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16453d4c4710SBarry Smith }
16463d4c4710SBarry Smith 
16473d4c4710SBarry Smith /*@
16483d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1649f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
16503d4c4710SBarry Smith 
16513d4c4710SBarry Smith   Not Collective
16523d4c4710SBarry Smith 
16533d4c4710SBarry Smith   Input Parameter:
1654f6dfbefdSBarry Smith . snes - `SNES` context
16553d4c4710SBarry Smith 
16563d4c4710SBarry Smith   Output Parameter:
16573d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16583d4c4710SBarry Smith 
16593d4c4710SBarry Smith   Level: intermediate
16603d4c4710SBarry Smith 
1661f6dfbefdSBarry Smith   Note:
1662f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16633d4c4710SBarry Smith 
16641cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16653d4c4710SBarry Smith @*/
1666d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1667d71ae5a4SJacob Faibussowitsch {
16683d4c4710SBarry Smith   PetscFunctionBegin;
16690700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16704f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16713d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16733d4c4710SBarry Smith }
16743d4c4710SBarry Smith 
1675c96a6f78SLois Curfman McInnes /*@
1676b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1677420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1678c96a6f78SLois Curfman McInnes 
1679c7afd0dbSLois Curfman McInnes   Not Collective
1680c7afd0dbSLois Curfman McInnes 
1681c96a6f78SLois Curfman McInnes   Input Parameter:
1682f6dfbefdSBarry Smith . snes - `SNES` context
1683c96a6f78SLois Curfman McInnes 
1684c96a6f78SLois Curfman McInnes   Output Parameter:
1685c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1686c96a6f78SLois Curfman McInnes 
1687dc4c0fb0SBarry Smith   Level: intermediate
1688dc4c0fb0SBarry Smith 
1689c96a6f78SLois Curfman McInnes   Notes:
1690f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1691c96a6f78SLois Curfman McInnes 
1692f6dfbefdSBarry 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
1693f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1694010be392SBarry Smith 
16951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1696c96a6f78SLois Curfman McInnes @*/
1697d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1698d71ae5a4SJacob Faibussowitsch {
16993a40ed3dSBarry Smith   PetscFunctionBegin;
17000700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17014f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1702c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
17033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1704c96a6f78SLois Curfman McInnes }
1705c96a6f78SLois Curfman McInnes 
1706971e163fSPeter Brune /*@
1707971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1708f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1709971e163fSPeter Brune 
1710c3339decSBarry Smith   Logically Collective
1711971e163fSPeter Brune 
1712d8d19677SJose E. Roman   Input Parameters:
1713f6dfbefdSBarry Smith + snes  - `SNES` context
1714f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1715971e163fSPeter Brune 
1716971e163fSPeter Brune   Level: developer
1717971e163fSPeter Brune 
17181cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1719971e163fSPeter Brune @*/
1720d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1721d71ae5a4SJacob Faibussowitsch {
1722971e163fSPeter Brune   PetscFunctionBegin;
1723971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1724971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1725971e163fSPeter Brune   snes->counters_reset = reset;
17263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1727971e163fSPeter Brune }
1728971e163fSPeter Brune 
17292999313aSBarry Smith /*@
173012b1dd1aSStefano Zampini   SNESResetCounters - Reset counters for linear iterations and function evaluations.
173112b1dd1aSStefano Zampini 
173212b1dd1aSStefano Zampini   Logically Collective
173312b1dd1aSStefano Zampini 
173412b1dd1aSStefano Zampini   Input Parameters:
173512b1dd1aSStefano Zampini . snes - `SNES` context
173612b1dd1aSStefano Zampini 
173712b1dd1aSStefano Zampini   Level: developer
173812b1dd1aSStefano Zampini 
173912b1dd1aSStefano Zampini   Note:
174012b1dd1aSStefano Zampini   It honors the flag set with `SNESSetCountersReset()`
174112b1dd1aSStefano Zampini 
174212b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
174312b1dd1aSStefano Zampini @*/
174412b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes)
174512b1dd1aSStefano Zampini {
174612b1dd1aSStefano Zampini   PetscFunctionBegin;
174712b1dd1aSStefano Zampini   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
174812b1dd1aSStefano Zampini   if (snes->counters_reset) {
174912b1dd1aSStefano Zampini     snes->nfuncs      = 0;
175012b1dd1aSStefano Zampini     snes->linear_its  = 0;
175112b1dd1aSStefano Zampini     snes->numFailures = 0;
175212b1dd1aSStefano Zampini   }
175312b1dd1aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
175412b1dd1aSStefano Zampini }
175512b1dd1aSStefano Zampini 
175612b1dd1aSStefano Zampini /*@
1757f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
17582999313aSBarry Smith 
1759420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
17602999313aSBarry Smith 
17612999313aSBarry Smith   Input Parameters:
1762f6dfbefdSBarry Smith + snes - the `SNES` context
1763f6dfbefdSBarry Smith - ksp  - the `KSP` context
17642999313aSBarry Smith 
1765dc4c0fb0SBarry Smith   Level: developer
1766dc4c0fb0SBarry Smith 
17672999313aSBarry Smith   Notes:
1768f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
17692999313aSBarry Smith   so this routine is rarely needed.
17702999313aSBarry Smith 
1771f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1772420bcc1bSBarry Smith   decreased by one when this is called.
17732999313aSBarry Smith 
177442747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
17752999313aSBarry Smith @*/
1776d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1777d71ae5a4SJacob Faibussowitsch {
17782999313aSBarry Smith   PetscFunctionBegin;
17790700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17800700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
17812999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
17829566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
17839566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17842999313aSBarry Smith   snes->ksp = ksp;
17853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17862999313aSBarry Smith }
17872999313aSBarry Smith 
178852baeb72SSatish Balay /*@
178977e5a1f9SBarry Smith   SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they
179077e5a1f9SBarry Smith   currently contain default values
179177e5a1f9SBarry Smith 
179277e5a1f9SBarry Smith   Collective
179377e5a1f9SBarry Smith 
179477e5a1f9SBarry Smith   Input Parameter:
179577e5a1f9SBarry Smith . snes - the `SNES` object
179677e5a1f9SBarry Smith 
179777e5a1f9SBarry Smith   Level: developer
179877e5a1f9SBarry Smith 
179977e5a1f9SBarry Smith   Developer Note:
180077e5a1f9SBarry Smith   This is called by all the `SNESCreate_XXX()` routines.
180177e5a1f9SBarry Smith 
180277e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`,
180377e5a1f9SBarry Smith           `PetscObjectParameterSetDefault()`
180477e5a1f9SBarry Smith @*/
180577e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes)
180677e5a1f9SBarry Smith {
180777e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_its, 50);
180877e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_funcs, 10000);
180977e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
181077e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50);
181177e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
181277e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, divtol, 1.e4);
181377e5a1f9SBarry Smith   return PETSC_SUCCESS;
181477e5a1f9SBarry Smith }
181577e5a1f9SBarry Smith 
181677e5a1f9SBarry Smith /*@
1817dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
18189b94acceSBarry Smith 
1819d083f849SBarry Smith   Collective
1820c7afd0dbSLois Curfman McInnes 
1821f6dfbefdSBarry Smith   Input Parameter:
1822906ed7ccSBarry Smith . comm - MPI communicator
18239b94acceSBarry Smith 
18249b94acceSBarry Smith   Output Parameter:
182520f4b53cSBarry Smith . outsnes - the new `SNES` context
18269b94acceSBarry Smith 
1827c7afd0dbSLois Curfman McInnes   Options Database Keys:
18287addb90fSBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner
18297addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()`
1830dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1831c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1832c1f60f51SBarry Smith 
183336851e7fSLois Curfman McInnes   Level: beginner
183436851e7fSLois Curfman McInnes 
183595452b02SPatrick Sanan   Developer Notes:
1836f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1837efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1838f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1839f6dfbefdSBarry Smith   in `SNESView()`.
1840efd4aadfSBarry Smith 
1841f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1842f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1843f6dfbefdSBarry Smith 
18447addb90fSBarry Smith   `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed.
1845efd4aadfSBarry Smith 
1846e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
18479b94acceSBarry Smith @*/
1848d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1849d71ae5a4SJacob Faibussowitsch {
18509b94acceSBarry Smith   SNES       snes;
1851fa9f3622SBarry Smith   SNESKSPEW *kctx;
185237fcc0dbSBarry Smith 
18533a40ed3dSBarry Smith   PetscFunctionBegin;
18544f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
18559566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
18568ba1e511SMatthew Knepley 
18579566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
18588d359177SBarry Smith   snes->ops->converged = SNESConvergedDefault;
18592c155ee1SBarry Smith   snes->usesksp        = PETSC_TRUE;
18609b94acceSBarry Smith   snes->norm           = 0.0;
1861c1e67a49SFande Kong   snes->xnorm          = 0.0;
1862c1e67a49SFande Kong   snes->ynorm          = 0.0;
1863365a6726SPeter Brune   snes->normschedule   = SNES_NORM_ALWAYS;
18646c67d002SPeter Brune   snes->functype       = SNES_FUNCTION_DEFAULT;
1865b4874afaSBarry Smith   snes->ttol           = 0.0;
186677e5a1f9SBarry Smith 
1867e37c518bSBarry Smith   snes->rnorm0               = 0;
18689b94acceSBarry Smith   snes->nfuncs               = 0;
186950ffb88aSMatthew Knepley   snes->numFailures          = 0;
187050ffb88aSMatthew Knepley   snes->maxFailures          = 1;
18717a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1872e35cf81dSBarry Smith   snes->lagjacobian          = 1;
187337ec4e1aSPeter Brune   snes->jac_iter             = 0;
187437ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1875a8054027SBarry Smith   snes->lagpreconditioner    = 1;
187637ec4e1aSPeter Brune   snes->pre_iter             = 0;
187737ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1878639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1879c4421ceaSFande Kong   snes->numberreasonviews    = 0;
18809e5d0892SLisandro Dalcin   snes->data                 = NULL;
18814dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1882186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
18836f24a144SLois Curfman McInnes   snes->nwork                = 0;
18849e5d0892SLisandro Dalcin   snes->work                 = NULL;
188558c9b817SLisandro Dalcin   snes->nvwork               = 0;
18869e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1887758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1888758f92a0SBarry Smith   snes->conv_hist_max        = 0;
18890298fd71SBarry Smith   snes->conv_hist            = NULL;
18900298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1891758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1892971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1893e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1894184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1895efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1896b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1897c40d0f55SPeter Brune 
1898d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1899d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1900d8f46077SPeter Brune   snes->mf_version  = 1;
1901d8f46077SPeter Brune 
19023d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
19033d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
19043d4c4710SBarry Smith 
1905349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
190676bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1907349187a7SBarry Smith 
19084fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
19094fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
19104fc747eaSLawrence Mitchell 
19119b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
19124dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1913f5af7f23SKarl Rupp 
1914835f2295SStefano Zampini   snes->kspconvctx  = kctx;
19159b94acceSBarry Smith   kctx->version     = 2;
19160f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
19179b94acceSBarry Smith                              this was too large for some test cases */
191875567043SBarry Smith   kctx->rtol_last   = 0.0;
19190f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
19209b94acceSBarry Smith   kctx->gamma       = 1.0;
19210f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
192271f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
19230f0abf79SStefano Zampini   kctx->threshold   = 0.1;
192475567043SBarry Smith   kctx->lresid_last = 0.0;
192575567043SBarry Smith   kctx->norm_last   = 0.0;
19269b94acceSBarry Smith 
19270f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
19280f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
19290f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
19300f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
19310f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
19320f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
19330f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
19340f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
19350f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
19360f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
19370f0abf79SStefano Zampini 
1938b50c806fSBarry Smith   PetscCall(SNESParametersInitialize(snes));
19399b94acceSBarry Smith   *outsnes = snes;
19403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19419b94acceSBarry Smith }
19429b94acceSBarry Smith 
19439b94acceSBarry Smith /*@C
19449b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1945f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
19469b94acceSBarry Smith   equations.
19479b94acceSBarry Smith 
1948c3339decSBarry Smith   Logically Collective
1949fee21e36SBarry Smith 
1950c7afd0dbSLois Curfman McInnes   Input Parameters:
1951f6dfbefdSBarry Smith + snes - the `SNES` context
1952dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
19538434afd1SBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunctionFn`
1954c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1955dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
19569b94acceSBarry Smith 
195736851e7fSLois Curfman McInnes   Level: beginner
195836851e7fSLois Curfman McInnes 
19598434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
19609b94acceSBarry Smith @*/
19618434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx)
1962d71ae5a4SJacob Faibussowitsch {
19636cab3a1bSJed Brown   DM dm;
19646cab3a1bSJed Brown 
19653a40ed3dSBarry Smith   PetscFunctionBegin;
19660700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1967d2a683ecSLisandro Dalcin   if (r) {
1968d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1969d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
19709566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
19719566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
197285385478SLisandro Dalcin     snes->vec_func = r;
1973d2a683ecSLisandro Dalcin   }
19749566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
19759566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
197648a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
19773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19789b94acceSBarry Smith }
19799b94acceSBarry Smith 
1980e4ed7901SPeter Brune /*@C
19810b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1982e4ed7901SPeter Brune 
1983c3339decSBarry Smith   Logically Collective
1984e4ed7901SPeter Brune 
1985e4ed7901SPeter Brune   Input Parameters:
1986f6dfbefdSBarry Smith + snes - the `SNES` context
1987e4ed7901SPeter Brune - f    - vector to store function value
1988e4ed7901SPeter Brune 
1989dc4c0fb0SBarry Smith   Level: developer
1990dc4c0fb0SBarry Smith 
1991e4ed7901SPeter Brune   Notes:
1992e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1993e4ed7901SPeter Brune 
1994f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1995e4ed7901SPeter Brune 
19961cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1997e4ed7901SPeter Brune @*/
1998d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1999d71ae5a4SJacob Faibussowitsch {
2000e4ed7901SPeter Brune   Vec vec_func;
2001e4ed7901SPeter Brune 
2002e4ed7901SPeter Brune   PetscFunctionBegin;
2003e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2004e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
2005e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
2006efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
2007902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
20083ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2009902f982fSPeter Brune   }
20109566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
20119566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
2012f5af7f23SKarl Rupp 
2013217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
20143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2015e4ed7901SPeter Brune }
2016e4ed7901SPeter Brune 
2017534ebe21SPeter Brune /*@
2018f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
2019f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
2020534ebe21SPeter Brune 
2021c3339decSBarry Smith   Logically Collective
2022534ebe21SPeter Brune 
2023534ebe21SPeter Brune   Input Parameters:
2024f6dfbefdSBarry Smith + snes         - the `SNES` context
2025365a6726SPeter Brune - normschedule - the frequency of norm computation
2026534ebe21SPeter Brune 
2027517f1916SMatthew G. Knepley   Options Database Key:
202867b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
2029517f1916SMatthew G. Knepley 
2030dc4c0fb0SBarry Smith   Level: advanced
2031dc4c0fb0SBarry Smith 
2032534ebe21SPeter Brune   Notes:
2033f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
2034534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
2035534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
2036f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
2037534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
2038534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
2039534ebe21SPeter Brune   their solution.
2040534ebe21SPeter Brune 
2041e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
2042534ebe21SPeter Brune @*/
2043d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
2044d71ae5a4SJacob Faibussowitsch {
2045534ebe21SPeter Brune   PetscFunctionBegin;
2046534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2047365a6726SPeter Brune   snes->normschedule = normschedule;
20483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2049534ebe21SPeter Brune }
2050534ebe21SPeter Brune 
2051534ebe21SPeter Brune /*@
2052f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
2053f6dfbefdSBarry Smith   of the `SNES` method.
2054534ebe21SPeter Brune 
2055c3339decSBarry Smith   Logically Collective
2056534ebe21SPeter Brune 
2057534ebe21SPeter Brune   Input Parameters:
2058f6dfbefdSBarry Smith + snes         - the `SNES` context
2059365a6726SPeter Brune - normschedule - the type of the norm used
2060534ebe21SPeter Brune 
2061534ebe21SPeter Brune   Level: advanced
2062534ebe21SPeter Brune 
20631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2064534ebe21SPeter Brune @*/
2065d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
2066d71ae5a4SJacob Faibussowitsch {
2067534ebe21SPeter Brune   PetscFunctionBegin;
2068534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2069365a6726SPeter Brune   *normschedule = snes->normschedule;
20703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2071534ebe21SPeter Brune }
2072534ebe21SPeter Brune 
2073c5ce4427SMatthew G. Knepley /*@
2074c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
2075c5ce4427SMatthew G. Knepley 
2076c3339decSBarry Smith   Logically Collective
2077c5ce4427SMatthew G. Knepley 
2078c5ce4427SMatthew G. Knepley   Input Parameters:
2079f6dfbefdSBarry Smith + snes - the `SNES` context
2080f6dfbefdSBarry Smith - norm - the value of the norm
2081c5ce4427SMatthew G. Knepley 
2082c5ce4427SMatthew G. Knepley   Level: developer
2083c5ce4427SMatthew G. Knepley 
20841cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2085c5ce4427SMatthew G. Knepley @*/
2086d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
2087d71ae5a4SJacob Faibussowitsch {
2088c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2089c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2090c5ce4427SMatthew G. Knepley   snes->norm = norm;
20913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2092c5ce4427SMatthew G. Knepley }
2093c5ce4427SMatthew G. Knepley 
2094c5ce4427SMatthew G. Knepley /*@
2095c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
2096c5ce4427SMatthew G. Knepley 
2097c5ce4427SMatthew G. Knepley   Not Collective
2098c5ce4427SMatthew G. Knepley 
2099c5ce4427SMatthew G. Knepley   Input Parameter:
2100f6dfbefdSBarry Smith . snes - the `SNES` context
2101c5ce4427SMatthew G. Knepley 
2102c5ce4427SMatthew G. Knepley   Output Parameter:
2103c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2104c5ce4427SMatthew G. Knepley 
2105c5ce4427SMatthew G. Knepley   Level: developer
2106c5ce4427SMatthew G. Knepley 
21071cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2108c5ce4427SMatthew G. Knepley @*/
2109d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2110d71ae5a4SJacob Faibussowitsch {
2111c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2112c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21134f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2114c5ce4427SMatthew G. Knepley   *norm = snes->norm;
21153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2116c5ce4427SMatthew G. Knepley }
2117c5ce4427SMatthew G. Knepley 
2118c1e67a49SFande Kong /*@
2119f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2120c1e67a49SFande Kong 
2121c1e67a49SFande Kong   Not Collective
2122c1e67a49SFande Kong 
2123c1e67a49SFande Kong   Input Parameter:
2124f6dfbefdSBarry Smith . snes - the `SNES` context
2125c1e67a49SFande Kong 
2126c1e67a49SFande Kong   Output Parameter:
2127c1e67a49SFande Kong . ynorm - the last computed update norm
2128c1e67a49SFande Kong 
2129c1e67a49SFande Kong   Level: developer
2130c1e67a49SFande Kong 
2131f6dfbefdSBarry Smith   Note:
2132f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2133f6dfbefdSBarry Smith 
21341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2135c1e67a49SFande Kong @*/
2136d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2137d71ae5a4SJacob Faibussowitsch {
2138c1e67a49SFande Kong   PetscFunctionBegin;
2139c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21404f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2141c1e67a49SFande Kong   *ynorm = snes->ynorm;
21423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2143c1e67a49SFande Kong }
2144c1e67a49SFande Kong 
2145c1e67a49SFande Kong /*@
21464591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2147c1e67a49SFande Kong 
2148c1e67a49SFande Kong   Not Collective
2149c1e67a49SFande Kong 
2150c1e67a49SFande Kong   Input Parameter:
2151f6dfbefdSBarry Smith . snes - the `SNES` context
2152c1e67a49SFande Kong 
2153c1e67a49SFande Kong   Output Parameter:
2154c1e67a49SFande Kong . xnorm - the last computed solution norm
2155c1e67a49SFande Kong 
2156c1e67a49SFande Kong   Level: developer
2157c1e67a49SFande Kong 
21581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2159c1e67a49SFande Kong @*/
2160d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2161d71ae5a4SJacob Faibussowitsch {
2162c1e67a49SFande Kong   PetscFunctionBegin;
2163c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21644f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2165c1e67a49SFande Kong   *xnorm = snes->xnorm;
21663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2167c1e67a49SFande Kong }
2168c1e67a49SFande Kong 
2169cc4c1da9SBarry Smith /*@
2170f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2171f6dfbefdSBarry Smith   of the `SNES` method.
217247073ea2SPeter Brune 
2173c3339decSBarry Smith   Logically Collective
217447073ea2SPeter Brune 
217547073ea2SPeter Brune   Input Parameters:
2176f6dfbefdSBarry Smith + snes - the `SNES` context
2177f6dfbefdSBarry Smith - type - the function type
217847073ea2SPeter Brune 
217947073ea2SPeter Brune   Level: developer
218047073ea2SPeter Brune 
2181420bcc1bSBarry Smith   Values of the function type\:
2182f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT`          - the default for the given `SNESType`
2183f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2184f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED`   - a transformation of the function provided with `SNESSetFunction()`
2185f6dfbefdSBarry Smith 
2186420bcc1bSBarry Smith   Note:
2187f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2188f6dfbefdSBarry Smith 
21891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
219047073ea2SPeter Brune @*/
2191d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2192d71ae5a4SJacob Faibussowitsch {
219347073ea2SPeter Brune   PetscFunctionBegin;
219447073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
219547073ea2SPeter Brune   snes->functype = type;
21963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
219747073ea2SPeter Brune }
219847073ea2SPeter Brune 
2199cc4c1da9SBarry Smith /*@
2200f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
220147073ea2SPeter Brune   of the SNES method.
220247073ea2SPeter Brune 
2203c3339decSBarry Smith   Logically Collective
220447073ea2SPeter Brune 
220547073ea2SPeter Brune   Input Parameters:
2206f6dfbefdSBarry Smith + snes - the `SNES` context
2207f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
220847073ea2SPeter Brune 
220947073ea2SPeter Brune   Level: advanced
221047073ea2SPeter Brune 
22111cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
221247073ea2SPeter Brune @*/
2213d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2214d71ae5a4SJacob Faibussowitsch {
221547073ea2SPeter Brune   PetscFunctionBegin;
221647073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
221747073ea2SPeter Brune   *type = snes->functype;
22183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2219534ebe21SPeter Brune }
2220534ebe21SPeter Brune 
2221c79ef259SPeter Brune /*@C
2222be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2223c79ef259SPeter Brune   use with composed nonlinear solvers.
2224c79ef259SPeter Brune 
2225c79ef259SPeter Brune   Input Parameters:
22269bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
22278434afd1SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
222877e5a1f9SBarry Smith - ctx  - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`)
2229c79ef259SPeter Brune 
2230dc4c0fb0SBarry Smith   Level: intermediate
2231dc4c0fb0SBarry Smith 
2232f6dfbefdSBarry Smith   Note:
2233f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2234f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2235c79ef259SPeter Brune 
22368434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2237c79ef259SPeter Brune @*/
22388434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx)
2239d71ae5a4SJacob Faibussowitsch {
22406cab3a1bSJed Brown   DM dm;
22416cab3a1bSJed Brown 
2242646217ecSPeter Brune   PetscFunctionBegin;
22436cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22449566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22459566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
22463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2247646217ecSPeter Brune }
2248646217ecSPeter Brune 
2249bbc1464cSBarry Smith /*
2250bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2251bbc1464cSBarry Smith    changed during the KSPSolve()
2252bbc1464cSBarry Smith */
2253d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2254d71ae5a4SJacob Faibussowitsch {
2255bbc1464cSBarry Smith   DM     dm;
2256bbc1464cSBarry Smith   DMSNES sdm;
2257bbc1464cSBarry Smith 
2258bbc1464cSBarry Smith   PetscFunctionBegin;
22599566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22609566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2261bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2262bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2263792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22649566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
22650df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2266ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2267792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22689566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2269bbc1464cSBarry Smith   } else {
2270792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22719566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2272bbc1464cSBarry Smith   }
22733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2274bbc1464cSBarry Smith }
2275bbc1464cSBarry Smith 
2276d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2277d71ae5a4SJacob Faibussowitsch {
2278e03ab78fSPeter Brune   DM     dm;
2279942e3340SBarry Smith   DMSNES sdm;
22806cab3a1bSJed Brown 
22818b0a5094SBarry Smith   PetscFunctionBegin;
22829566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22839566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22848b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2285bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2286792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22879566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2288792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22899566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2290bbc1464cSBarry Smith   } else {
2291792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22929566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2293bbc1464cSBarry Smith   }
22943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22958b0a5094SBarry Smith }
22968b0a5094SBarry Smith 
2297d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2298d71ae5a4SJacob Faibussowitsch {
22998b0a5094SBarry Smith   PetscFunctionBegin;
2300e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2301bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
23029566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
23039566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
23043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23058b0a5094SBarry Smith }
23068b0a5094SBarry Smith 
23078b0a5094SBarry Smith /*@C
23081d27aa22SBarry Smith   SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
23098b0a5094SBarry Smith 
2310c3339decSBarry Smith   Logically Collective
23118b0a5094SBarry Smith 
23128b0a5094SBarry Smith   Input Parameters:
2313f6dfbefdSBarry Smith + snes - the `SNES` context
2314dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
23158434afd1SBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
231626a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed
2317dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
23188434afd1SBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2319dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2320dc4c0fb0SBarry Smith 
2321dc4c0fb0SBarry Smith   Level: intermediate
23228b0a5094SBarry Smith 
23238b0a5094SBarry Smith   Notes:
232426a11704SBarry Smith   It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use
2325f450aa47SBarry 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.
2326f450aa47SBarry Smith 
2327f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
23288b0a5094SBarry Smith 
23291d27aa22SBarry 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}$.
23301d27aa22SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
23318b0a5094SBarry Smith 
233226a11704SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner.
23338b0a5094SBarry Smith 
23340d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
23351d27aa22SBarry Smith   the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
23368b0a5094SBarry Smith 
23378b0a5094SBarry 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
23381d27aa22SBarry 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
23391d27aa22SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
23408b0a5094SBarry Smith 
23411d27aa22SBarry 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
234226a11704SBarry Smith   $A(x^{n})$ is used to build the preconditioner
23436b7fb656SBarry Smith 
234415229ffcSPierre 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.
23456b7fb656SBarry Smith 
2346dc4c0fb0SBarry 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
234726a11704SBarry 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
234826a11704SBarry 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`.
2349aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2350bbc1464cSBarry Smith 
23519bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
23528434afd1SBarry Smith           `SNESFunctionFn`, `SNESJacobianFn`
23538b0a5094SBarry Smith @*/
23548434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
2355d71ae5a4SJacob Faibussowitsch {
2356e03ab78fSPeter Brune   DM dm;
2357e03ab78fSPeter Brune 
23588b0a5094SBarry Smith   PetscFunctionBegin;
23598b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23609566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23619566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
23629566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
23639566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
23649566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
23653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23668b0a5094SBarry Smith }
23678b0a5094SBarry Smith 
23687971a8bfSPeter Brune /*@C
23697971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
23707971a8bfSPeter Brune 
2371f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
23727971a8bfSPeter Brune 
23737971a8bfSPeter Brune   Input Parameter:
2374f6dfbefdSBarry Smith . snes - the `SNES` context
23757971a8bfSPeter Brune 
2376d8d19677SJose E. Roman   Output Parameters:
2377dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
23788434afd1SBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunctionFn`
2379dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2380dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
23818434afd1SBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFn`
2382dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
23837971a8bfSPeter Brune 
23847971a8bfSPeter Brune   Level: advanced
23857971a8bfSPeter Brune 
23868434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
23877971a8bfSPeter Brune @*/
23888434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
2389d71ae5a4SJacob Faibussowitsch {
23907971a8bfSPeter Brune   DM dm;
23917971a8bfSPeter Brune 
23927971a8bfSPeter Brune   PetscFunctionBegin;
23937971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23949566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23959566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23969566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23979566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23997971a8bfSPeter Brune }
24007971a8bfSPeter Brune 
2401d25893d9SBarry Smith /*@C
2402dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2403d25893d9SBarry Smith 
2404c3339decSBarry Smith   Logically Collective
2405d25893d9SBarry Smith 
2406d25893d9SBarry Smith   Input Parameters:
2407f6dfbefdSBarry Smith + snes - the `SNES` context
24088434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2409d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2410dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2411d25893d9SBarry Smith 
2412d25893d9SBarry Smith   Level: intermediate
2413d25893d9SBarry Smith 
24148434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2415d25893d9SBarry Smith @*/
24168434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx)
2417d71ae5a4SJacob Faibussowitsch {
2418d25893d9SBarry Smith   PetscFunctionBegin;
2419d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2420d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2421d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
24223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2423d25893d9SBarry Smith }
2424d25893d9SBarry Smith 
24251096aae1SMatthew Knepley /*@C
2426dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2427dd8e379bSPierre Jolivet   it assumes a zero right-hand side.
24281096aae1SMatthew Knepley 
2429c3339decSBarry Smith   Logically Collective
24301096aae1SMatthew Knepley 
24311096aae1SMatthew Knepley   Input Parameter:
2432f6dfbefdSBarry Smith . snes - the `SNES` context
24331096aae1SMatthew Knepley 
24341096aae1SMatthew Knepley   Output Parameter:
2435dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
24361096aae1SMatthew Knepley 
24371096aae1SMatthew Knepley   Level: intermediate
24381096aae1SMatthew Knepley 
24391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
24401096aae1SMatthew Knepley @*/
2441d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2442d71ae5a4SJacob Faibussowitsch {
24431096aae1SMatthew Knepley   PetscFunctionBegin;
24440700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24454f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
244685385478SLisandro Dalcin   *rhs = snes->vec_rhs;
24473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24481096aae1SMatthew Knepley }
24491096aae1SMatthew Knepley 
24509b94acceSBarry Smith /*@
2451f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
24529b94acceSBarry Smith 
2453c3339decSBarry Smith   Collective
2454c7afd0dbSLois Curfman McInnes 
24559b94acceSBarry Smith   Input Parameters:
2456f6dfbefdSBarry Smith + snes - the `SNES` context
2457c7afd0dbSLois Curfman McInnes - x    - input vector
24589b94acceSBarry Smith 
24599b94acceSBarry Smith   Output Parameter:
2460f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
24619b94acceSBarry Smith 
2462dc4c0fb0SBarry Smith   Level: developer
2463dc4c0fb0SBarry Smith 
246400677de2SStefano Zampini   Notes:
2465f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2466bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
246736851e7fSLois Curfman McInnes 
246800677de2SStefano Zampini   When solving for $F(x) = b$, this routine computes $y = F(x) - b$.
246900677de2SStefano Zampini 
24701cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
24719b94acceSBarry Smith @*/
2472d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2473d71ae5a4SJacob Faibussowitsch {
24746cab3a1bSJed Brown   DM     dm;
2475942e3340SBarry Smith   DMSNES sdm;
24769b94acceSBarry Smith 
24773a40ed3dSBarry Smith   PetscFunctionBegin;
24780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24790700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
24800700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2481c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2482c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2483e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2484184914b5SBarry Smith 
24859566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24869566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24870fdf79fbSJacob 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().");
248832f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
248948a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24909566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24918ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24928ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2493800f99ffSJeremy L Thompson     {
2494800f99ffSJeremy L Thompson       void           *ctx;
24958434afd1SBarry Smith       SNESFunctionFn *computefunction;
2496800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2497800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2498800f99ffSJeremy L Thompson     }
24999566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
250048a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
25010fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
25029566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
25030fdf79fbSJacob Faibussowitsch   }
25041baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2505ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2506422a814eSBarry Smith   /*
2507422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2508422a814eSBarry Smith      propagate the value to all processes
2509422a814eSBarry Smith   */
2510f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25129b94acceSBarry Smith }
25139b94acceSBarry Smith 
2514c79ef259SPeter Brune /*@
25150b4b7b1cSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`.
2516bbc1464cSBarry Smith 
2517c3339decSBarry Smith   Collective
2518bbc1464cSBarry Smith 
2519bbc1464cSBarry Smith   Input Parameters:
2520f6dfbefdSBarry Smith + snes - the `SNES` context
2521bbc1464cSBarry Smith - x    - input vector
2522bbc1464cSBarry Smith 
2523bbc1464cSBarry Smith   Output Parameter:
25240b4b7b1cSBarry Smith . y - output vector
2525bbc1464cSBarry Smith 
2526dc4c0fb0SBarry Smith   Level: developer
2527dc4c0fb0SBarry Smith 
2528bbc1464cSBarry Smith   Notes:
2529420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2530bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2531bbc1464cSBarry Smith 
2532dd8e379bSPierre Jolivet   Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2533f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2534dd8e379bSPierre 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.
2535bbc1464cSBarry Smith 
25360b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()`
2537bbc1464cSBarry Smith @*/
2538d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2539d71ae5a4SJacob Faibussowitsch {
2540bbc1464cSBarry Smith   DM     dm;
2541bbc1464cSBarry Smith   DMSNES sdm;
2542bbc1464cSBarry Smith 
2543bbc1464cSBarry Smith   PetscFunctionBegin;
2544bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2545bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2546bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2547bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2548bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2549e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2550bbc1464cSBarry Smith 
25519566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25529566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25539566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
25549566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2555bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2556bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2557792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
25589566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
25599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2560bbc1464cSBarry Smith   snes->nfuncs++;
2561bbc1464cSBarry Smith   /*
2562bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2563bbc1464cSBarry Smith      propagate the value to all processes
2564bbc1464cSBarry Smith   */
2565f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2567bbc1464cSBarry Smith }
2568bbc1464cSBarry Smith 
2569bbc1464cSBarry Smith /*@
2570f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2571c79ef259SPeter Brune 
2572c3339decSBarry Smith   Collective
2573c79ef259SPeter Brune 
2574c79ef259SPeter Brune   Input Parameters:
2575f6dfbefdSBarry Smith + snes - the `SNES` context
2576c79ef259SPeter Brune . x    - input vector
2577c79ef259SPeter Brune - b    - rhs vector
2578c79ef259SPeter Brune 
2579c79ef259SPeter Brune   Output Parameter:
2580c79ef259SPeter Brune . x - new solution vector
2581c79ef259SPeter Brune 
2582dc4c0fb0SBarry Smith   Level: developer
2583dc4c0fb0SBarry Smith 
2584f6dfbefdSBarry Smith   Note:
2585f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2586c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2587c79ef259SPeter Brune   themselves.
2588c79ef259SPeter Brune 
25898434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2590c79ef259SPeter Brune @*/
2591d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2592d71ae5a4SJacob Faibussowitsch {
25936cab3a1bSJed Brown   DM     dm;
2594942e3340SBarry Smith   DMSNES sdm;
2595646217ecSPeter Brune 
2596646217ecSPeter Brune   PetscFunctionBegin;
2597646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2598064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2599064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2600064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2601064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2602e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
26039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
26049566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
26059566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
26060fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
26079566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2608792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
26099566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
26109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
26113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2612646217ecSPeter Brune }
2613646217ecSPeter Brune 
2614494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2615494a190aSStefano Zampini {
2616494a190aSStefano Zampini   Vec          X;
2617494a190aSStefano Zampini   PetscScalar *g;
2618494a190aSStefano Zampini   PetscReal    f, f2;
2619494a190aSStefano Zampini   PetscInt     low, high, N, i;
2620494a190aSStefano Zampini   PetscBool    flg;
2621494a190aSStefano Zampini   PetscReal    h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2622494a190aSStefano Zampini 
2623494a190aSStefano Zampini   PetscFunctionBegin;
2624494a190aSStefano Zampini   PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2625494a190aSStefano Zampini   PetscCall(VecDuplicate(Xin, &X));
2626494a190aSStefano Zampini   PetscCall(VecCopy(Xin, X));
2627494a190aSStefano Zampini   PetscCall(VecGetSize(X, &N));
2628494a190aSStefano Zampini   PetscCall(VecGetOwnershipRange(X, &low, &high));
2629494a190aSStefano Zampini   PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2630494a190aSStefano Zampini   PetscCall(VecGetArray(G, &g));
2631494a190aSStefano Zampini   for (i = 0; i < N; i++) {
2632494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2633494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2634494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2635494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f));
2636494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2637494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2638494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2639494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f2));
2640494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2641494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2642494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2643494a190aSStefano Zampini     if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2644494a190aSStefano Zampini   }
2645494a190aSStefano Zampini   PetscCall(VecRestoreArray(G, &g));
2646494a190aSStefano Zampini   PetscCall(VecDestroy(&X));
2647494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2648494a190aSStefano Zampini }
2649494a190aSStefano Zampini 
26501dfd7622SMatthew Knepley /*@
26511dfd7622SMatthew Knepley   SNESTestFunction - Computes the difference between the computed and finite-difference functions
26521dfd7622SMatthew Knepley 
26531dfd7622SMatthew Knepley   Collective
26541dfd7622SMatthew Knepley 
2655d5bfe6baSJose E. Roman   Input Parameter:
26561dfd7622SMatthew Knepley . snes - the `SNES` context
26571dfd7622SMatthew Knepley 
26581dfd7622SMatthew Knepley   Options Database Keys:
26591dfd7622SMatthew Knepley + -snes_test_function      - compare the user provided function with one compute via finite differences to check for errors.
26601dfd7622SMatthew Knepley - -snes_test_function_view - display the user provided function, the finite difference function and the difference
26611dfd7622SMatthew Knepley 
26621dfd7622SMatthew Knepley   Level: developer
26631dfd7622SMatthew Knepley 
26641dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestJacobian()`, `SNESSetFunction()`, `SNESComputeFunction()`
26651dfd7622SMatthew Knepley @*/
2666494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2667494a190aSStefano Zampini {
2668494a190aSStefano Zampini   Vec               x, g1, g2, g3;
26691dfd7622SMatthew Knepley   PetscBool         complete_print = PETSC_FALSE;
2670494a190aSStefano Zampini   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2671494a190aSStefano Zampini   PetscScalar       dot;
2672494a190aSStefano Zampini   MPI_Comm          comm;
2673494a190aSStefano Zampini   PetscViewer       viewer, mviewer;
2674494a190aSStefano Zampini   PetscViewerFormat format;
2675494a190aSStefano Zampini   PetscInt          tabs;
2676494a190aSStefano Zampini   static PetscBool  directionsprinted = PETSC_FALSE;
26778434afd1SBarry Smith   SNESObjectiveFn  *objective;
2678494a190aSStefano Zampini 
2679494a190aSStefano Zampini   PetscFunctionBegin;
2680494a190aSStefano Zampini   PetscCall(SNESGetObjective(snes, &objective, NULL));
2681494a190aSStefano Zampini   if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2682494a190aSStefano Zampini 
2683494a190aSStefano Zampini   PetscObjectOptionsBegin((PetscObject)snes);
2684494a190aSStefano Zampini   PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2685494a190aSStefano Zampini   PetscOptionsEnd();
2686494a190aSStefano Zampini 
2687494a190aSStefano Zampini   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2688494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2689494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2690494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2691494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Function -------------\n"));
2692494a190aSStefano Zampini   if (!complete_print && !directionsprinted) {
2693494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2694494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference function entries greater than <threshold>.\n"));
2695494a190aSStefano Zampini   }
2696494a190aSStefano Zampini   if (!directionsprinted) {
2697494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2698494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Function is probably correct.\n"));
2699494a190aSStefano Zampini     directionsprinted = PETSC_TRUE;
2700494a190aSStefano Zampini   }
2701494a190aSStefano Zampini   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2702494a190aSStefano Zampini 
2703494a190aSStefano Zampini   PetscCall(SNESGetSolution(snes, &x));
2704494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g1));
2705494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g2));
2706494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g3));
2707494a190aSStefano Zampini   PetscCall(SNESComputeFunction(snes, x, g1));
2708494a190aSStefano Zampini   PetscCall(SNESComputeFunction_FD(snes, x, g2));
2709494a190aSStefano Zampini 
2710494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2711494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2712494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2713494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2714494a190aSStefano Zampini   PetscCall(VecDot(g1, g2, &dot));
2715494a190aSStefano Zampini   PetscCall(VecCopy(g1, g3));
2716494a190aSStefano Zampini   PetscCall(VecAXPY(g3, -1.0, g2));
2717494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2718494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2719494a190aSStefano 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))));
2720494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2721494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2722494a190aSStefano Zampini 
2723494a190aSStefano Zampini   if (complete_print) {
2724494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded function ----------\n"));
2725494a190aSStefano Zampini     PetscCall(VecView(g1, mviewer));
2726494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference function ----------\n"));
2727494a190aSStefano Zampini     PetscCall(VecView(g2, mviewer));
2728494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference function ----------\n"));
2729494a190aSStefano Zampini     PetscCall(VecView(g3, mviewer));
2730494a190aSStefano Zampini   }
2731494a190aSStefano Zampini   PetscCall(VecDestroy(&g1));
2732494a190aSStefano Zampini   PetscCall(VecDestroy(&g2));
2733494a190aSStefano Zampini   PetscCall(VecDestroy(&g3));
2734494a190aSStefano Zampini 
2735494a190aSStefano Zampini   if (complete_print) {
2736494a190aSStefano Zampini     PetscCall(PetscViewerPopFormat(mviewer));
2737494a190aSStefano Zampini     PetscCall(PetscViewerDestroy(&mviewer));
2738494a190aSStefano Zampini   }
2739494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2740494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2741494a190aSStefano Zampini }
2742494a190aSStefano Zampini 
2743cbf8f02cSMatthew G. Knepley /*@
2744cbf8f02cSMatthew G. Knepley   SNESTestJacobian - Computes the difference between the computed and finite-difference Jacobians
2745cbf8f02cSMatthew G. Knepley 
2746cbf8f02cSMatthew G. Knepley   Collective
2747cbf8f02cSMatthew G. Knepley 
2748d5bfe6baSJose E. Roman   Input Parameter:
2749cbf8f02cSMatthew G. Knepley . snes - the `SNES` context
2750cbf8f02cSMatthew G. Knepley 
2751cbf8f02cSMatthew G. Knepley   Output Parameters:
27521dfd7622SMatthew Knepley + Jnorm    - the Frobenius norm of the computed Jacobian, or `NULL`
27531dfd7622SMatthew Knepley - diffNorm - the Frobenius norm of the difference of the computed and finite-difference Jacobians, or `NULL`
2754cbf8f02cSMatthew G. Knepley 
2755cbf8f02cSMatthew G. Knepley   Options Database Keys:
2756cbf8f02cSMatthew G. Knepley + -snes_test_jacobian <optional threshold> - compare the user provided Jacobian with one compute via finite differences to check for errors.  If a threshold is given, display only those entries whose difference is greater than the threshold.
2757cbf8f02cSMatthew G. Knepley - -snes_test_jacobian_view                 - display the user provided Jacobian, the finite difference Jacobian and the difference
2758cbf8f02cSMatthew G. Knepley 
2759cbf8f02cSMatthew G. Knepley   Level: developer
2760cbf8f02cSMatthew G. Knepley 
27611dfd7622SMatthew Knepley   Note:
27621dfd7622SMatthew Knepley   Directions and norms are printed to stdout if `diffNorm` is `NULL`.
27631dfd7622SMatthew Knepley 
27641dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestFunction()`, `SNESSetJacobian()`, `SNESComputeJacobian()`
2765cbf8f02cSMatthew G. Knepley @*/
2766cbf8f02cSMatthew G. Knepley PetscErrorCode SNESTestJacobian(SNES snes, PetscReal *Jnorm, PetscReal *diffNorm)
2767d71ae5a4SJacob Faibussowitsch {
276812837594SBarry Smith   Mat               A, B, C, D, jacobian;
27694df93895SStefano Zampini   Vec               x = snes->vec_sol, f;
2770e885f1abSBarry Smith   PetscReal         nrm, gnorm;
277181e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
27720e276705SLisandro Dalcin   MatType           mattype;
2773e885f1abSBarry Smith   PetscInt          m, n, M, N;
2774e885f1abSBarry Smith   void             *functx;
27751dfd7622SMatthew Knepley   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, flg, istranspose;
27761dfd7622SMatthew Knepley   PetscBool         silent = diffNorm != PETSC_NULLPTR ? PETSC_TRUE : PETSC_FALSE;
27773325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2778e885f1abSBarry Smith   MPI_Comm          comm;
2779e885f1abSBarry Smith   PetscInt          tabs;
278012837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
27813325ff46SBarry Smith   PetscViewerFormat format;
2782e885f1abSBarry Smith 
2783e885f1abSBarry Smith   PetscFunctionBegin;
2784d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
27859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
27869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
27874ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
27889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
27899566063dSJacob 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));
2790d0609cedSBarry Smith   PetscOptionsEnd();
2791e885f1abSBarry Smith 
27929566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
27939566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
27949566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
27959566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
27961dfd7622SMatthew Knepley   if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
27971dfd7622SMatthew Knepley   if (!complete_print && !silent && !directionsprinted) {
27989566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
27999566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
280012837594SBarry Smith   }
28011dfd7622SMatthew Knepley   if (!directionsprinted && !silent) {
28029566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
28039566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
280412837594SBarry Smith     directionsprinted = PETSC_TRUE;
2805e885f1abSBarry Smith   }
28061baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2807e885f1abSBarry Smith 
28089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
280912837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
281012837594SBarry Smith   else jacobian = snes->jacobian_pre;
281112837594SBarry Smith 
28124df93895SStefano Zampini   if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
28134df93895SStefano Zampini   else PetscCall(PetscObjectReference((PetscObject)x));
28149566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &f));
28154df93895SStefano Zampini 
2816a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
28179566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
28189566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
28199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
282012837594SBarry Smith   while (jacobian) {
28212cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
28222cd624f9SStefano Zampini 
28232cd624f9SStefano Zampini     if (istranspose) {
28249566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
28252cd624f9SStefano Zampini       Jsave    = jacobian;
28262cd624f9SStefano Zampini       jacobian = JT;
28272cd624f9SStefano Zampini     }
28289566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
282912837594SBarry Smith     if (flg) {
283012837594SBarry Smith       A = jacobian;
28319566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
283212837594SBarry Smith     } else {
28339566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
283412837594SBarry Smith     }
2835e885f1abSBarry Smith 
28369566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
28379566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
28389566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
28399566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
28409566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
28419566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
28429566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
28439566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
28449566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2845e885f1abSBarry Smith 
28469566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
28479566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
284812837594SBarry Smith 
28499566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
28509566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28519566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
28529566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
28539566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
285412837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
28551dfd7622SMatthew Knepley     if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
2856e885f1abSBarry Smith     if (complete_print) {
28579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
28589566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
28599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
28609566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2861e885f1abSBarry Smith     }
2862e885f1abSBarry Smith 
2863df10fb39SFande Kong     if (threshold_print || complete_print) {
2864e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2865e885f1abSBarry Smith       PetscScalar       *cvals;
2866e885f1abSBarry Smith       const PetscInt    *bcols;
2867e885f1abSBarry Smith       const PetscScalar *bvals;
2868e885f1abSBarry Smith 
28699566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
28709566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
28719566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
28729566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
28739566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
28749566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
28750e276705SLisandro Dalcin 
28769566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28779566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2878e885f1abSBarry Smith 
2879e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
28809566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
28819566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2882e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
288323a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2884e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2885e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2886e885f1abSBarry Smith             cncols += 1;
2887e885f1abSBarry Smith           }
2888e885f1abSBarry Smith         }
288948a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
28909566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
28919566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2892e885f1abSBarry Smith       }
28939566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
28949566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
28959566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
28969566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
28979566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2898e885f1abSBarry Smith     }
28999566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
29009566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
29019566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
29022cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
290312837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
290412837594SBarry Smith       jacobian = snes->jacobian_pre;
29051dfd7622SMatthew Knepley       if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
29069371c9d4SSatish Balay     } else jacobian = NULL;
290712837594SBarry Smith   }
29089566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
29091baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2910648c30bcSBarry Smith   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
29119566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2912cbf8f02cSMatthew G. Knepley 
2913cbf8f02cSMatthew G. Knepley   if (Jnorm) *Jnorm = gnorm;
2914cbf8f02cSMatthew G. Knepley   if (diffNorm) *diffNorm = nrm;
29153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2916e885f1abSBarry Smith }
2917e885f1abSBarry Smith 
291862fef451SLois Curfman McInnes /*@
2919f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
292062fef451SLois Curfman McInnes 
2921c3339decSBarry Smith   Collective
2922c7afd0dbSLois Curfman McInnes 
292362fef451SLois Curfman McInnes   Input Parameters:
2924f6dfbefdSBarry Smith + snes - the `SNES` context
2925e4094ef1SJacob Faibussowitsch - X    - input vector
292662fef451SLois Curfman McInnes 
292762fef451SLois Curfman McInnes   Output Parameters:
2928c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2929420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2930fee21e36SBarry Smith 
2931e35cf81dSBarry Smith   Options Database Keys:
293267b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
293367b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2934455a5933SJed 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.
2935455a5933SJed 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
2936693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2937693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2938693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
29397addb90fSBarry Smith . -snes_compare_operator                   - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner
294094d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2941a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2942c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2943dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2944dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2945a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2946a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2947c01495d3SJed Brown 
2948dc4c0fb0SBarry Smith   Level: developer
2949dc4c0fb0SBarry Smith 
2950f6dfbefdSBarry Smith   Note:
295162fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
295262fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
295362fef451SLois Curfman McInnes 
2954420bcc1bSBarry Smith   Developer Note:
2955dc4c0fb0SBarry 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
2956420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2957e885f1abSBarry Smith 
29581cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
295962fef451SLois Curfman McInnes @*/
2960d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2961d71ae5a4SJacob Faibussowitsch {
2962ace3abfcSBarry Smith   PetscBool flag;
29636cab3a1bSJed Brown   DM        dm;
2964942e3340SBarry Smith   DMSNES    sdm;
2965e0e3a89bSBarry Smith   KSP       ksp;
29663a40ed3dSBarry Smith 
29673a40ed3dSBarry Smith   PetscFunctionBegin;
29680700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
29690700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2970c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2971e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
29729566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
29739566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
29743232da50SPeter Brune 
297501c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2976fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2977fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2978f5af7f23SKarl Rupp 
29799566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2980fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
29819566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
29829566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2983ebd3b9afSBarry Smith     if (flag) {
29849566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29859566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2986ebd3b9afSBarry Smith     }
29873ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
298837ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
298963a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
29909566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2991ebd3b9afSBarry Smith     if (flag) {
29929566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29939566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2994ebd3b9afSBarry Smith     }
29953ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2996e35cf81dSBarry Smith   }
2997efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
29989566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29999566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
30003ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3001d728fb7dSPeter Brune   }
3002e35cf81dSBarry Smith 
30039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
30049566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
3005800f99ffSJeremy L Thompson   {
3006800f99ffSJeremy L Thompson     void           *ctx;
30078434afd1SBarry Smith     SNESJacobianFn *J;
3008800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
3009800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
3010800f99ffSJeremy L Thompson   }
30119566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
30129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
301328d58a37SPierre Jolivet 
30147addb90fSBarry Smith   /* attach latest linearization point to the matrix used to construct the preconditioner */
30159566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
3016a8054027SBarry Smith 
3017e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
30189566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
30193b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
30209566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
30219566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
30223b4f5425SBarry Smith     snes->lagpreconditioner = -1;
30233b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
30249566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
30259566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
302637ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
302763a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
30289566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
3029d1e9a80fSBarry Smith   } else {
30309566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
30319566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
3032a8054027SBarry Smith   }
3033a8054027SBarry Smith 
30344df93895SStefano Zampini   /* monkey business to allow testing Jacobians in multilevel solvers.
30354df93895SStefano Zampini      This is needed because the SNESTestXXX interface does not accept vectors and matrices */
30364df93895SStefano Zampini   {
30374df93895SStefano Zampini     Vec xsave            = snes->vec_sol;
30384df93895SStefano Zampini     Mat jacobiansave     = snes->jacobian;
30394df93895SStefano Zampini     Mat jacobian_presave = snes->jacobian_pre;
30404df93895SStefano Zampini 
30414df93895SStefano Zampini     snes->vec_sol      = X;
30424df93895SStefano Zampini     snes->jacobian     = A;
30434df93895SStefano Zampini     snes->jacobian_pre = B;
30441dfd7622SMatthew Knepley     if (snes->testFunc) PetscCall(SNESTestFunction(snes));
30451dfd7622SMatthew Knepley     if (snes->testJac) PetscCall(SNESTestJacobian(snes, NULL, NULL));
3046494a190aSStefano Zampini 
30474df93895SStefano Zampini     snes->vec_sol      = xsave;
30484df93895SStefano Zampini     snes->jacobian     = jacobiansave;
30494df93895SStefano Zampini     snes->jacobian_pre = jacobian_presave;
30504df93895SStefano Zampini   }
30514df93895SStefano Zampini 
3052693365a8SJed Brown   {
3053693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
3054648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
3055648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
3056648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
3057648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
3058693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
30590298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
3060693365a8SJed Brown       PetscViewer vdraw, vstdout;
30616b3a5b13SJed Brown       PetscBool   flg;
3062693365a8SJed Brown       if (flag_operator) {
30639566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
3064693365a8SJed Brown         Bexp = Bexp_mine;
3065693365a8SJed Brown       } else {
30667addb90fSBarry Smith         /* See if the matrix used to construct the preconditioner can be viewed and added directly */
30679566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
306894ab13aaSBarry Smith         if (flg) Bexp = B;
3069693365a8SJed Brown         else {
3070693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
30719566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
3072693365a8SJed Brown           Bexp = Bexp_mine;
3073693365a8SJed Brown         }
3074693365a8SJed Brown       }
30759566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
30769566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
30779566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
3078693365a8SJed Brown       if (flag_draw || flag_contour) {
30799566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30809566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30810298fd71SBarry Smith       } else vdraw = NULL;
30829566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
30839566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
30849566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
30859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
30869566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
30879566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
30889566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
30899566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
30909566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
3091693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
30929566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30939566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
30949566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
3095693365a8SJed Brown       }
30969566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30979566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
30989566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
30999566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
3100693365a8SJed Brown     }
3101693365a8SJed Brown   }
31024c30e9fbSJed Brown   {
31036719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
31046719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
3105648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
3106648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
3107648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
3108648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
3109648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
311027b0f280SBarry Smith     if (flag_threshold) {
31119566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
31129566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
311327b0f280SBarry Smith     }
31146719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
31154c30e9fbSJed Brown       Mat             Bfd;
31164c30e9fbSJed Brown       PetscViewer     vdraw, vstdout;
3117335efc43SPeter Brune       MatColoring     coloring;
31184c30e9fbSJed Brown       ISColoring      iscoloring;
31194c30e9fbSJed Brown       MatFDColoring   matfdcoloring;
31208434afd1SBarry Smith       SNESFunctionFn *func;
31214c30e9fbSJed Brown       void           *funcctx;
31226719d8e4SJed Brown       PetscReal       norm1, norm2, normmax;
31234c30e9fbSJed Brown 
31249566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
31259566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
31269566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
31279566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
31289566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
31299566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
31309566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
31319566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
31329566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
31339566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
31344c30e9fbSJed Brown 
31354c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
31369566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
31372ba42892SBarry Smith       PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)func, funcctx));
31389566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
31399566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
31409566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
31419566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
31429566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
31434c30e9fbSJed Brown 
31449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
31454c30e9fbSJed Brown       if (flag_draw || flag_contour) {
31469566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
31479566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31480298fd71SBarry Smith       } else vdraw = NULL;
31499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
31509566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
31519566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
31529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
31539566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31549566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
31559566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
31569566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
31579566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
31589566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
31599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
31609566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31614c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
31629566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31639566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
31649566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
31654c30e9fbSJed Brown       }
31669566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
31676719d8e4SJed Brown 
31686719d8e4SJed Brown       if (flag_threshold) {
31696719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
31709566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
31719566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
31726719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
31736719d8e4SJed Brown           const PetscScalar *ba, *ca;
31746719d8e4SJed Brown           const PetscInt    *bj, *cj;
31756719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
31766719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
31779566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
31789566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
31795f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
31806719d8e4SJed Brown           for (j = 0; j < bn; j++) {
31816719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
31826719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
31836719d8e4SJed Brown               maxentrycol = bj[j];
31846719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
31856719d8e4SJed Brown             }
31866719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
31876719d8e4SJed Brown               maxdiffcol = bj[j];
31886719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
31896719d8e4SJed Brown             }
31906719d8e4SJed Brown             if (rdiff > maxrdiff) {
31916719d8e4SJed Brown               maxrdiffcol = bj[j];
31926719d8e4SJed Brown               maxrdiff    = rdiff;
31936719d8e4SJed Brown             }
31946719d8e4SJed Brown           }
31956719d8e4SJed Brown           if (maxrdiff > 1) {
319663a3b9bcSJacob 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));
31976719d8e4SJed Brown             for (j = 0; j < bn; j++) {
31986719d8e4SJed Brown               PetscReal rdiff;
31996719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
320048a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
32016719d8e4SJed Brown             }
320263a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
32036719d8e4SJed Brown           }
32049566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
32059566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
32066719d8e4SJed Brown         }
32076719d8e4SJed Brown       }
32089566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
32099566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
32104c30e9fbSJed Brown     }
32114c30e9fbSJed Brown   }
32123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32139b94acceSBarry Smith }
32149b94acceSBarry Smith 
32159b94acceSBarry Smith /*@C
32169b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3217044dda88SLois Curfman McInnes   location to store the matrix.
32189b94acceSBarry Smith 
3219c3339decSBarry Smith   Logically Collective
3220c7afd0dbSLois Curfman McInnes 
32219b94acceSBarry Smith   Input Parameters:
3222f6dfbefdSBarry Smith + snes - the `SNES` context
3223e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3224dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
32258434afd1SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3226c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3227dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3228dc4c0fb0SBarry Smith 
3229dc4c0fb0SBarry Smith   Level: beginner
32309b94acceSBarry Smith 
32319b94acceSBarry Smith   Notes:
3232dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
323316913363SBarry Smith   each matrix.
323416913363SBarry Smith 
3235dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3236dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3237895c21f2SBarry Smith 
3238dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3239f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3240a8a26c1eSJed Brown 
3241c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3242f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3243c3cc8fd1SJed Brown 
32441cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
32458434afd1SBarry Smith           `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
32469b94acceSBarry Smith @*/
32478434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
3248d71ae5a4SJacob Faibussowitsch {
32496cab3a1bSJed Brown   DM dm;
32503a7fca6bSBarry Smith 
32513a40ed3dSBarry Smith   PetscFunctionBegin;
32520700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3253e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3254e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3255e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3256e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
32579566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32589566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3259e5d3d808SBarry Smith   if (Amat) {
32609566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
32619566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3262f5af7f23SKarl Rupp 
3263e5d3d808SBarry Smith     snes->jacobian = Amat;
32643a7fca6bSBarry Smith   }
3265e5d3d808SBarry Smith   if (Pmat) {
32669566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
32679566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3268f5af7f23SKarl Rupp 
3269e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
32703a7fca6bSBarry Smith   }
32713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32729b94acceSBarry Smith }
327362fef451SLois Curfman McInnes 
3274c2aafc4cSSatish Balay /*@C
3275b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3276b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3277b4fd4287SBarry Smith 
3278420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3279c7afd0dbSLois Curfman McInnes 
3280b4fd4287SBarry Smith   Input Parameter:
3281b4fd4287SBarry Smith . snes - the nonlinear solver context
3282b4fd4287SBarry Smith 
3283b4fd4287SBarry Smith   Output Parameters:
3284dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3285dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
32868434afd1SBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3287dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3288fee21e36SBarry Smith 
328936851e7fSLois Curfman McInnes   Level: advanced
329036851e7fSLois Curfman McInnes 
32918434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3292b4fd4287SBarry Smith @*/
32938434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
3294d71ae5a4SJacob Faibussowitsch {
32956cab3a1bSJed Brown   DM dm;
32966cab3a1bSJed Brown 
32973a40ed3dSBarry Smith   PetscFunctionBegin;
32980700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3299e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3300e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
33019566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3302800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
33033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3304b4fd4287SBarry Smith }
3305b4fd4287SBarry Smith 
3306d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3307d71ae5a4SJacob Faibussowitsch {
330858b371f3SBarry Smith   DM     dm;
330958b371f3SBarry Smith   DMSNES sdm;
331058b371f3SBarry Smith 
331158b371f3SBarry Smith   PetscFunctionBegin;
33129566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
33139566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
331458b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
331558b371f3SBarry Smith     DM        dm;
331658b371f3SBarry Smith     PetscBool isdense, ismf;
331758b371f3SBarry Smith 
33189566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
33199566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
33209566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
332158b371f3SBarry Smith     if (isdense) {
33229566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
332358b371f3SBarry Smith     } else if (!ismf) {
33249566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
332558b371f3SBarry Smith     }
332658b371f3SBarry Smith   }
33273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
332858b371f3SBarry Smith }
332958b371f3SBarry Smith 
33309b94acceSBarry Smith /*@
33319b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
33320b4b7b1cSBarry Smith   of a nonlinear solver `SNESSolve()`.
33339b94acceSBarry Smith 
3334c3339decSBarry Smith   Collective
3335fee21e36SBarry Smith 
33362fe279fdSBarry Smith   Input Parameter:
3337f6dfbefdSBarry Smith . snes - the `SNES` context
3338c7afd0dbSLois Curfman McInnes 
3339dc4c0fb0SBarry Smith   Level: advanced
3340dc4c0fb0SBarry Smith 
3341f6dfbefdSBarry Smith   Note:
33420b4b7b1cSBarry Smith   For basic use of the `SNES` solvers the user does not need to explicitly call
3343f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3344f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3345f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3346f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3347272ac6f2SLois Curfman McInnes 
33480b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()`
33499b94acceSBarry Smith @*/
3350d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3351d71ae5a4SJacob Faibussowitsch {
33526cab3a1bSJed Brown   DM             dm;
3353942e3340SBarry Smith   DMSNES         sdm;
3354c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
33556e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
33569b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
33579b5c1c08SStefano Zampini   Vec            f, fpc;
33589b5c1c08SStefano Zampini   void          *funcctx;
33599b5c1c08SStefano Zampini   void          *jacctx, *appctx;
33609b5c1c08SStefano Zampini   Mat            j, jpre;
33616b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
33626b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
33638434afd1SBarry Smith   SNESFunctionFn *func;
33648434afd1SBarry Smith   SNESJacobianFn *jac;
33653a40ed3dSBarry Smith 
33663a40ed3dSBarry Smith   PetscFunctionBegin;
33670700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33683ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3369fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
33709b94acceSBarry Smith 
337148a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
337285385478SLisandro Dalcin 
33739566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
337458c9b817SLisandro Dalcin 
33759566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
33769566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
33779566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
337858b371f3SBarry Smith 
337948a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3380efd51863SBarry Smith 
338148a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3382b710008aSBarry Smith 
3383d8d34be6SBarry Smith   if (snes->linesearch) {
33849566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
33859566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3386d8d34be6SBarry Smith   }
33879e764e56SPeter Brune 
33889b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3389b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3390172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3391172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3392172a4300SPeter Brune   }
3393d8f46077SPeter Brune 
3394efd4aadfSBarry Smith   if (snes->npc) {
33956e2a1849SPeter Brune     /* copy the DM over */
33969566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
33979566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
33986e2a1849SPeter Brune 
33999566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
34009566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
34019566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
34029566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
34039566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
34049566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
34059566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
34069b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
34079566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
34086e2a1849SPeter Brune 
34096e2a1849SPeter Brune     /* copy the function pointers over */
34109566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
34116e2a1849SPeter Brune 
34126e2a1849SPeter Brune     /* default to 1 iteration */
34139566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3414efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
34159566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3416a9936a0cSPeter Brune     } else {
34179566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3418a9936a0cSPeter Brune     }
34199566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
34206e2a1849SPeter Brune 
34216e2a1849SPeter Brune     /* copy the line search context over */
3422d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
34239566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
34249566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
34259566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
34269566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
34279566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
34289566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
34299566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
34306e2a1849SPeter Brune     }
3431d8d34be6SBarry Smith   }
34321baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
3433835f2295SStefano Zampini   if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx));
34346e2a1849SPeter Brune 
343537ec4e1aSPeter Brune   snes->jac_iter = 0;
343637ec4e1aSPeter Brune   snes->pre_iter = 0;
343737ec4e1aSPeter Brune 
3438dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
343958c9b817SLisandro Dalcin 
34409566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
344158b371f3SBarry Smith 
3442b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
34436c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3444d8d34be6SBarry Smith       if (snes->linesearch) {
34459566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
34469566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
34476c67d002SPeter Brune       }
34486c67d002SPeter Brune     }
3449d8d34be6SBarry Smith   }
3450fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
34517aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
34523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34539b94acceSBarry Smith }
34549b94acceSBarry Smith 
345537596af1SLisandro Dalcin /*@
34560b4b7b1cSBarry 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
345737596af1SLisandro Dalcin 
3458c3339decSBarry Smith   Collective
345937596af1SLisandro Dalcin 
346037596af1SLisandro Dalcin   Input Parameter:
34610b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
346237596af1SLisandro Dalcin 
3463d25893d9SBarry Smith   Level: intermediate
3464d25893d9SBarry Smith 
346595452b02SPatrick Sanan   Notes:
34660b4b7b1cSBarry Smith   Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain.
34670b4b7b1cSBarry Smith 
3468f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
346937596af1SLisandro Dalcin 
3470f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3471f6dfbefdSBarry Smith 
34721cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
347337596af1SLisandro Dalcin @*/
3474d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3475d71ae5a4SJacob Faibussowitsch {
347637596af1SLisandro Dalcin   PetscFunctionBegin;
347737596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
347849abdd8aSBarry Smith   if (snes->ops->ctxdestroy && snes->ctx) {
3479835f2295SStefano Zampini     PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx));
348049abdd8aSBarry Smith     snes->ctx = NULL;
3481d25893d9SBarry Smith   }
34821baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
34838a23116dSBarry Smith 
3484dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
34851baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
34869e764e56SPeter Brune 
34871baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
34889e764e56SPeter Brune 
34899566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
34909566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
34919566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
34929566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
34939566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
34949566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
34959566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
34969566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
34979566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3498f5af7f23SKarl Rupp 
349940fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
350040fdac6aSLawrence Mitchell 
350137596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
350237596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
35033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
350437596af1SLisandro Dalcin }
350537596af1SLisandro Dalcin 
350652baeb72SSatish Balay /*@
350736d43d94SBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also
350836d43d94SBarry Smith   removes the default viewer.
3509c4421ceaSFande Kong 
3510c3339decSBarry Smith   Collective
3511c4421ceaSFande Kong 
3512c4421ceaSFande Kong   Input Parameter:
35130b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
3514c4421ceaSFande Kong 
3515c4421ceaSFande Kong   Level: intermediate
3516c4421ceaSFande Kong 
3517420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3518c4421ceaSFande Kong @*/
3519d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3520d71ae5a4SJacob Faibussowitsch {
3521c4421ceaSFande Kong   PetscInt i;
3522c4421ceaSFande Kong 
3523c4421ceaSFande Kong   PetscFunctionBegin;
3524c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3525c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
352648a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3527c4421ceaSFande Kong   }
3528c4421ceaSFande Kong   snes->numberreasonviews = 0;
3529648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
35303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3531c4421ceaSFande Kong }
3532c4421ceaSFande Kong 
35330764c050SBarry Smith /*@
35349b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3535f6dfbefdSBarry Smith   with `SNESCreate()`.
35369b94acceSBarry Smith 
3537c3339decSBarry Smith   Collective
3538c7afd0dbSLois Curfman McInnes 
35399b94acceSBarry Smith   Input Parameter:
3540f6dfbefdSBarry Smith . snes - the `SNES` context
35419b94acceSBarry Smith 
354236851e7fSLois Curfman McInnes   Level: beginner
354336851e7fSLois Curfman McInnes 
35441cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
35459b94acceSBarry Smith @*/
3546d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3547d71ae5a4SJacob Faibussowitsch {
354892e852f7SPablo Brubeck   DM dm;
354992e852f7SPablo Brubeck 
35503a40ed3dSBarry Smith   PetscFunctionBegin;
35513ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3552f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3553f4f49eeaSPierre Jolivet   if (--((PetscObject)*snes)->refct > 0) {
35549371c9d4SSatish Balay     *snes = NULL;
35553ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
35569371c9d4SSatish Balay   }
3557d4bb536fSBarry Smith 
3558f4f49eeaSPierre Jolivet   PetscCall(SNESReset(*snes));
35599566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
35606b8b9a38SLisandro Dalcin 
3561e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
35629566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3563f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*snes, destroy);
35646d4c513bSLisandro Dalcin 
356592e852f7SPablo Brubeck   dm = (*snes)->dm;
356692e852f7SPablo Brubeck   while (dm) {
356792e852f7SPablo Brubeck     PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
356892e852f7SPablo Brubeck     PetscCall(DMGetCoarseDM(dm, &dm));
356992e852f7SPablo Brubeck   }
357092e852f7SPablo Brubeck 
35719566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
35729566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
35739566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
35746b8b9a38SLisandro Dalcin 
35759566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
357648a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
357748a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3578f4f49eeaSPierre Jolivet   PetscCall(SNESMonitorCancel(*snes));
3579f4f49eeaSPierre Jolivet   PetscCall(SNESConvergedReasonViewCancel(*snes));
35809566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
35813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35829b94acceSBarry Smith }
35839b94acceSBarry Smith 
35849b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
35859b94acceSBarry Smith 
3586a8054027SBarry Smith /*@
35870b4b7b1cSBarry Smith   SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`.
3588a8054027SBarry Smith 
3589c3339decSBarry Smith   Logically Collective
3590a8054027SBarry Smith 
3591a8054027SBarry Smith   Input Parameters:
3592f6dfbefdSBarry Smith + snes - the `SNES` context
3593d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
35943b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3595a8054027SBarry Smith 
3596a8054027SBarry Smith   Options Database Keys:
3597420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
35983d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3599420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
36003d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3601a8054027SBarry Smith 
3602dc4c0fb0SBarry Smith   Level: intermediate
3603dc4c0fb0SBarry Smith 
3604420bcc1bSBarry Smith   Notes:
3605a8054027SBarry Smith   The default is 1
3606420bcc1bSBarry Smith 
3607f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3608d8e291bfSBarry Smith 
3609f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3610a8054027SBarry Smith 
36113201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3612f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3613a8054027SBarry Smith @*/
3614d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3615d71ae5a4SJacob Faibussowitsch {
3616a8054027SBarry Smith   PetscFunctionBegin;
36170700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
36185f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
36195f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3620c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3621a8054027SBarry Smith   snes->lagpreconditioner = lag;
36223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3623a8054027SBarry Smith }
3624a8054027SBarry Smith 
3625efd51863SBarry Smith /*@
3626f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3627efd51863SBarry Smith 
3628c3339decSBarry Smith   Logically Collective
3629efd51863SBarry Smith 
3630efd51863SBarry Smith   Input Parameters:
3631f6dfbefdSBarry Smith + snes  - the `SNES` context
3632efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3633efd51863SBarry Smith 
3634f6dfbefdSBarry Smith   Options Database Key:
363567b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3636efd51863SBarry Smith 
3637efd51863SBarry Smith   Level: intermediate
3638efd51863SBarry Smith 
36390b4b7b1cSBarry Smith   Notes:
36400b4b7b1cSBarry Smith   Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement.
36410b4b7b1cSBarry Smith 
3642f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3643c0df2a02SJed Brown 
36443201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
364554c05997SPierre Jolivet           `SNESSetDM()`, `SNESSolve()`
3646efd51863SBarry Smith @*/
3647d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3648d71ae5a4SJacob Faibussowitsch {
3649efd51863SBarry Smith   PetscFunctionBegin;
3650efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3651efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3652efd51863SBarry Smith   snes->gridsequence = steps;
36533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3654efd51863SBarry Smith }
3655efd51863SBarry Smith 
3656fa19ca70SBarry Smith /*@
3657f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3658fa19ca70SBarry Smith 
3659c3339decSBarry Smith   Logically Collective
3660fa19ca70SBarry Smith 
3661fa19ca70SBarry Smith   Input Parameter:
3662f6dfbefdSBarry Smith . snes - the `SNES` context
3663fa19ca70SBarry Smith 
3664fa19ca70SBarry Smith   Output Parameter:
3665fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3666fa19ca70SBarry Smith 
3667fa19ca70SBarry Smith   Level: intermediate
3668fa19ca70SBarry Smith 
36693201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3670fa19ca70SBarry Smith @*/
3671d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3672d71ae5a4SJacob Faibussowitsch {
3673fa19ca70SBarry Smith   PetscFunctionBegin;
3674fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3675fa19ca70SBarry Smith   *steps = snes->gridsequence;
36763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3677fa19ca70SBarry Smith }
3678fa19ca70SBarry Smith 
3679a8054027SBarry Smith /*@
3680f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3681a8054027SBarry Smith 
36823f9fe445SBarry Smith   Not Collective
3683a8054027SBarry Smith 
3684a8054027SBarry Smith   Input Parameter:
3685f6dfbefdSBarry Smith . snes - the `SNES` context
3686a8054027SBarry Smith 
3687a8054027SBarry Smith   Output Parameter:
3688a8054027SBarry 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
36893b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3690a8054027SBarry Smith 
3691dc4c0fb0SBarry Smith   Level: intermediate
3692dc4c0fb0SBarry Smith 
3693a8054027SBarry Smith   Notes:
3694a8054027SBarry Smith   The default is 1
3695f6dfbefdSBarry Smith 
3696a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3697a8054027SBarry Smith 
36983201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3699a8054027SBarry Smith @*/
3700d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3701d71ae5a4SJacob Faibussowitsch {
3702a8054027SBarry Smith   PetscFunctionBegin;
37030700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3704a8054027SBarry Smith   *lag = snes->lagpreconditioner;
37053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3706a8054027SBarry Smith }
3707a8054027SBarry Smith 
3708e35cf81dSBarry Smith /*@
3709f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3710e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3711e35cf81dSBarry Smith 
3712c3339decSBarry Smith   Logically Collective
3713e35cf81dSBarry Smith 
3714e35cf81dSBarry Smith   Input Parameters:
3715f6dfbefdSBarry Smith + snes - the `SNES` context
3716e35cf81dSBarry 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
3717fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3718e35cf81dSBarry Smith 
3719e35cf81dSBarry Smith   Options Database Keys:
372079a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37213d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
372279a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37233d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3724e35cf81dSBarry Smith 
3725dc4c0fb0SBarry Smith   Level: intermediate
3726dc4c0fb0SBarry Smith 
3727e35cf81dSBarry Smith   Notes:
3728e35cf81dSBarry Smith   The default is 1
3729f6dfbefdSBarry Smith 
3730e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3731f6dfbefdSBarry Smith 
3732fe3ffe1eSBarry 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
3733fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3734e35cf81dSBarry Smith 
37353201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3736e35cf81dSBarry Smith @*/
3737d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3738d71ae5a4SJacob Faibussowitsch {
3739e35cf81dSBarry Smith   PetscFunctionBegin;
37400700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
37415f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
37425f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3743c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3744e35cf81dSBarry Smith   snes->lagjacobian = lag;
37453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3746e35cf81dSBarry Smith }
3747e35cf81dSBarry Smith 
3748e35cf81dSBarry Smith /*@
3749f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3750e35cf81dSBarry Smith 
37513f9fe445SBarry Smith   Not Collective
3752e35cf81dSBarry Smith 
3753e35cf81dSBarry Smith   Input Parameter:
3754f6dfbefdSBarry Smith . snes - the `SNES` context
3755e35cf81dSBarry Smith 
3756e35cf81dSBarry Smith   Output Parameter:
3757e35cf81dSBarry 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
3758e35cf81dSBarry Smith          the Jacobian is built etc.
3759e35cf81dSBarry Smith 
3760dc4c0fb0SBarry Smith   Level: intermediate
3761dc4c0fb0SBarry Smith 
3762e35cf81dSBarry Smith   Notes:
3763e35cf81dSBarry Smith   The default is 1
3764f6dfbefdSBarry Smith 
3765f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3766e35cf81dSBarry Smith 
37673201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3768e35cf81dSBarry Smith 
3769e35cf81dSBarry Smith @*/
3770d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3771d71ae5a4SJacob Faibussowitsch {
3772e35cf81dSBarry Smith   PetscFunctionBegin;
37730700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3774e35cf81dSBarry Smith   *lag = snes->lagjacobian;
37753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3776e35cf81dSBarry Smith }
3777e35cf81dSBarry Smith 
377837ec4e1aSPeter Brune /*@
3779f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
378037ec4e1aSPeter Brune 
3781c3339decSBarry Smith   Logically collective
378237ec4e1aSPeter Brune 
3783d8d19677SJose E. Roman   Input Parameters:
3784f6dfbefdSBarry Smith + snes - the `SNES` context
37859d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
378637ec4e1aSPeter Brune 
378737ec4e1aSPeter Brune   Options Database Keys:
378879a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37893d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
379079a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37913d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
37923d5a8a6aSBarry Smith 
3793dc4c0fb0SBarry Smith   Level: advanced
3794dc4c0fb0SBarry Smith 
379595452b02SPatrick Sanan   Notes:
3796420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3797f6dfbefdSBarry Smith 
379895452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
379937ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
380037ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
380137ec4e1aSPeter Brune 
380242747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
380337ec4e1aSPeter Brune @*/
3804d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3805d71ae5a4SJacob Faibussowitsch {
380637ec4e1aSPeter Brune   PetscFunctionBegin;
380737ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
380837ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
380937ec4e1aSPeter Brune   snes->lagjac_persist = flg;
38103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
381137ec4e1aSPeter Brune }
381237ec4e1aSPeter Brune 
381337ec4e1aSPeter Brune /*@
3814d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
381537ec4e1aSPeter Brune 
3816c3339decSBarry Smith   Logically Collective
381737ec4e1aSPeter Brune 
3818d8d19677SJose E. Roman   Input Parameters:
3819f6dfbefdSBarry Smith + snes - the `SNES` context
38209d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
382137ec4e1aSPeter Brune 
382237ec4e1aSPeter Brune   Options Database Keys:
382379a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
38243d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
382579a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
38263d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
382737ec4e1aSPeter Brune 
3828dc4c0fb0SBarry Smith   Level: developer
3829dc4c0fb0SBarry Smith 
383095452b02SPatrick Sanan   Notes:
3831420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3832f6dfbefdSBarry Smith 
383395452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
383437ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
383537ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
383637ec4e1aSPeter Brune 
38371cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
383837ec4e1aSPeter Brune @*/
3839d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3840d71ae5a4SJacob Faibussowitsch {
384137ec4e1aSPeter Brune   PetscFunctionBegin;
384237ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
384337ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
384437ec4e1aSPeter Brune   snes->lagpre_persist = flg;
38453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
384637ec4e1aSPeter Brune }
384737ec4e1aSPeter Brune 
38489b94acceSBarry Smith /*@
3849f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3850be5caee7SBarry Smith 
3851c3339decSBarry Smith   Logically Collective
3852be5caee7SBarry Smith 
3853be5caee7SBarry Smith   Input Parameters:
3854f6dfbefdSBarry Smith + snes  - the `SNES` context
3855f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3856be5caee7SBarry Smith 
3857f6dfbefdSBarry Smith   Options Database Key:
3858be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3859be5caee7SBarry Smith 
3860dc4c0fb0SBarry Smith   Level: intermediate
3861dc4c0fb0SBarry Smith 
3862f6dfbefdSBarry Smith   Note:
3863f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3864be5caee7SBarry Smith 
38653201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()`
3866be5caee7SBarry Smith @*/
3867d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3868d71ae5a4SJacob Faibussowitsch {
3869be5caee7SBarry Smith   PetscFunctionBegin;
3870be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3871be5caee7SBarry Smith   snes->forceiteration = force;
38723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3873be5caee7SBarry Smith }
3874be5caee7SBarry Smith 
387585216dc7SFande Kong /*@
3876f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
387785216dc7SFande Kong 
3878c3339decSBarry Smith   Logically Collective
387985216dc7SFande Kong 
38802fe279fdSBarry Smith   Input Parameter:
3881f6dfbefdSBarry Smith . snes - the `SNES` context
388285216dc7SFande Kong 
388385216dc7SFande Kong   Output Parameter:
3884dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
388585216dc7SFande Kong 
388606dd6b0eSSatish Balay   Level: intermediate
388706dd6b0eSSatish Balay 
38883201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()`
388985216dc7SFande Kong @*/
3890d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3891d71ae5a4SJacob Faibussowitsch {
389285216dc7SFande Kong   PetscFunctionBegin;
389385216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
389485216dc7SFande Kong   *force = snes->forceiteration;
38953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
389685216dc7SFande Kong }
3897be5caee7SBarry Smith 
3898be5caee7SBarry Smith /*@
38990b4b7b1cSBarry Smith   SNESSetTolerances - Sets various parameters used in `SNES` convergence tests.
39009b94acceSBarry Smith 
3901c3339decSBarry Smith   Logically Collective
3902c7afd0dbSLois Curfman McInnes 
39039b94acceSBarry Smith   Input Parameters:
3904f6dfbefdSBarry Smith + snes   - the `SNES` context
39050b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $
39060b4b7b1cSBarry Smith . rtol   - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $
39075358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
39080b4b7b1cSBarry Smith . maxit  - the maximum number of iterations allowed in the solver, default 50.
39090b4b7b1cSBarry Smith - maxf   - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000
3910fee21e36SBarry Smith 
391133174efeSLois Curfman McInnes   Options Database Keys:
391277e5a1f9SBarry Smith + -snes_atol <abstol>    - Sets `abstol`
391377e5a1f9SBarry Smith . -snes_rtol <rtol>      - Sets `rtol`
391477e5a1f9SBarry Smith . -snes_stol <stol>      - Sets `stol`
391577e5a1f9SBarry Smith . -snes_max_it <maxit>   - Sets `maxit`
391677e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum)
39179b94acceSBarry Smith 
391836851e7fSLois Curfman McInnes   Level: intermediate
391936851e7fSLois Curfman McInnes 
392077e5a1f9SBarry Smith   Note:
392177e5a1f9SBarry Smith   All parameters must be non-negative
392277e5a1f9SBarry Smith 
392377e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`.
392477e5a1f9SBarry Smith   The default value is the value in the object when its type is set.
392577e5a1f9SBarry Smith 
392677e5a1f9SBarry Smith   Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations.
392777e5a1f9SBarry Smith 
392877e5a1f9SBarry Smith   Fortran Note:
392977e5a1f9SBarry Smith   Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL`
393077e5a1f9SBarry Smith 
39313201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
39329b94acceSBarry Smith @*/
3933d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3934d71ae5a4SJacob Faibussowitsch {
39353a40ed3dSBarry Smith   PetscFunctionBegin;
39360700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3937c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3938c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3939c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3940c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3941c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3942c5eb9154SBarry Smith 
394377e5a1f9SBarry Smith   if (abstol == (PetscReal)PETSC_DETERMINE) {
394477e5a1f9SBarry Smith     snes->abstol = snes->default_abstol;
394577e5a1f9SBarry Smith   } else if (abstol != (PetscReal)PETSC_CURRENT) {
39465f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3947ab54825eSJed Brown     snes->abstol = abstol;
3948ab54825eSJed Brown   }
394977e5a1f9SBarry Smith 
395077e5a1f9SBarry Smith   if (rtol == (PetscReal)PETSC_DETERMINE) {
395177e5a1f9SBarry Smith     snes->rtol = snes->default_rtol;
395277e5a1f9SBarry Smith   } else if (rtol != (PetscReal)PETSC_CURRENT) {
39535f80ce2aSJacob 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);
3954ab54825eSJed Brown     snes->rtol = rtol;
3955ab54825eSJed Brown   }
395677e5a1f9SBarry Smith 
395777e5a1f9SBarry Smith   if (stol == (PetscReal)PETSC_DETERMINE) {
395877e5a1f9SBarry Smith     snes->stol = snes->default_stol;
395977e5a1f9SBarry Smith   } else if (stol != (PetscReal)PETSC_CURRENT) {
39605f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3961c60f73f4SPeter Brune     snes->stol = stol;
3962ab54825eSJed Brown   }
396377e5a1f9SBarry Smith 
3964835f2295SStefano Zampini   if (maxit == PETSC_DETERMINE) {
396577e5a1f9SBarry Smith     snes->max_its = snes->default_max_its;
3966835f2295SStefano Zampini   } else if (maxit == PETSC_UNLIMITED) {
396777e5a1f9SBarry Smith     snes->max_its = PETSC_INT_MAX;
396877e5a1f9SBarry Smith   } else if (maxit != PETSC_CURRENT) {
396963a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3970ab54825eSJed Brown     snes->max_its = maxit;
3971ab54825eSJed Brown   }
397277e5a1f9SBarry Smith 
3973835f2295SStefano Zampini   if (maxf == PETSC_DETERMINE) {
397477e5a1f9SBarry Smith     snes->max_funcs = snes->default_max_funcs;
3975835f2295SStefano Zampini   } else if (maxf == PETSC_UNLIMITED || maxf == -1) {
397677e5a1f9SBarry Smith     snes->max_funcs = PETSC_UNLIMITED;
397777e5a1f9SBarry Smith   } else if (maxf != PETSC_CURRENT) {
397877e5a1f9SBarry Smith     PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf);
3979ab54825eSJed Brown     snes->max_funcs = maxf;
3980ab54825eSJed Brown   }
39813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39829b94acceSBarry Smith }
39839b94acceSBarry Smith 
3984e4d06f11SPatrick Farrell /*@
3985f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3986e4d06f11SPatrick Farrell 
3987c3339decSBarry Smith   Logically Collective
3988e4d06f11SPatrick Farrell 
3989e4d06f11SPatrick Farrell   Input Parameters:
3990f6dfbefdSBarry Smith + snes   - the `SNES` context
39910b4b7b1cSBarry 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
39920b4b7b1cSBarry Smith            is stopped due to divergence.
3993e4d06f11SPatrick Farrell 
3994f6dfbefdSBarry Smith   Options Database Key:
3995dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3996e4d06f11SPatrick Farrell 
3997e4d06f11SPatrick Farrell   Level: intermediate
3998e4d06f11SPatrick Farrell 
399977e5a1f9SBarry Smith   Notes:
400077e5a1f9SBarry Smith   Use `PETSC_DETERMINE` to use the default value from when the object's type was set.
4001e5cd489fSStefano Zampini 
400277e5a1f9SBarry Smith   Fortran Note:
400377e5a1f9SBarry Smith   Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL`
400477e5a1f9SBarry Smith 
400577e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()`
4006e4d06f11SPatrick Farrell @*/
4007d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
4008d71ae5a4SJacob Faibussowitsch {
4009e4d06f11SPatrick Farrell   PetscFunctionBegin;
4010e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4011e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
401277e5a1f9SBarry Smith 
401377e5a1f9SBarry Smith   if (divtol == (PetscReal)PETSC_DETERMINE) {
401477e5a1f9SBarry Smith     snes->divtol = snes->default_divtol;
401577e5a1f9SBarry Smith   } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) {
401677e5a1f9SBarry Smith     snes->divtol = PETSC_UNLIMITED;
401777e5a1f9SBarry Smith   } else if (divtol != (PetscReal)PETSC_CURRENT) {
401877e5a1f9SBarry Smith     PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol);
401977e5a1f9SBarry Smith     snes->divtol = divtol;
402077e5a1f9SBarry Smith   }
40213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4022e4d06f11SPatrick Farrell }
4023e4d06f11SPatrick Farrell 
40249b94acceSBarry Smith /*@
40250b4b7b1cSBarry Smith   SNESGetTolerances - Gets various parameters used in `SNES` convergence tests.
402633174efeSLois Curfman McInnes 
4027c7afd0dbSLois Curfman McInnes   Not Collective
4028c7afd0dbSLois Curfman McInnes 
402977e5a1f9SBarry Smith   Input Parameter:
403077e5a1f9SBarry Smith . snes - the `SNES` context
403177e5a1f9SBarry Smith 
403277e5a1f9SBarry Smith   Output Parameters:
40330b4b7b1cSBarry Smith + atol  - the absolute convergence tolerance
40340b4b7b1cSBarry Smith . rtol  - the relative convergence tolerance
403577e5a1f9SBarry Smith . stol  - convergence tolerance in terms of the norm of the change in the solution between steps
40360b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed
40370b4b7b1cSBarry Smith - maxf  - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound
4038fee21e36SBarry Smith 
403936851e7fSLois Curfman McInnes   Level: intermediate
404036851e7fSLois Curfman McInnes 
40410b4b7b1cSBarry Smith   Notes:
40420b4b7b1cSBarry Smith   See `SNESSetTolerances()` for details on the parameters.
40430b4b7b1cSBarry Smith 
4044dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
4045dc4c0fb0SBarry Smith 
40461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
404733174efeSLois Curfman McInnes @*/
4048d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
4049d71ae5a4SJacob Faibussowitsch {
40503a40ed3dSBarry Smith   PetscFunctionBegin;
40510700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
405285385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
405333174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
4054c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
405533174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
405633174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
40573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
405833174efeSLois Curfman McInnes }
405933174efeSLois Curfman McInnes 
4060e4d06f11SPatrick Farrell /*@
4061e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
4062e4d06f11SPatrick Farrell 
4063e4d06f11SPatrick Farrell   Not Collective
4064e4d06f11SPatrick Farrell 
4065e4d06f11SPatrick Farrell   Input Parameters:
4066f6dfbefdSBarry Smith + snes   - the `SNES` context
4067e4d06f11SPatrick Farrell - divtol - divergence tolerance
4068e4d06f11SPatrick Farrell 
4069e4d06f11SPatrick Farrell   Level: intermediate
4070e4d06f11SPatrick Farrell 
40711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
4072e4d06f11SPatrick Farrell @*/
4073d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
4074d71ae5a4SJacob Faibussowitsch {
4075e4d06f11SPatrick Farrell   PetscFunctionBegin;
4076e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4077e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
40783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4079e4d06f11SPatrick Farrell }
4080e4d06f11SPatrick Farrell 
40816ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
40826ba87a44SLisandro Dalcin 
4083d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
4084d71ae5a4SJacob Faibussowitsch {
4085b271bb04SBarry Smith   PetscDrawLG      lg;
4086b271bb04SBarry Smith   PetscReal        x, y, per;
4087b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
4088b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
4089b271bb04SBarry Smith   PetscDraw        draw;
4090b271bb04SBarry Smith 
4091459f5d12SBarry Smith   PetscFunctionBegin;
40924d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
40939566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
40949566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40959566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40969566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
4097b271bb04SBarry Smith   x = (PetscReal)n;
409877b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
409994c9c6d3SKarl Rupp   else y = -15.0;
41009566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
41016934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41029566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41039566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4104b271bb04SBarry Smith   }
4105b271bb04SBarry Smith 
41069566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
41079566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
41089566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4109aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
41109566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
4111b271bb04SBarry Smith   x = (PetscReal)n;
4112b271bb04SBarry Smith   y = 100.0 * per;
41139566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
41146934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41159566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41169566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4117b271bb04SBarry Smith   }
4118b271bb04SBarry Smith 
41199566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
41209371c9d4SSatish Balay   if (!n) {
41219371c9d4SSatish Balay     prev = rnorm;
41229371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
41239371c9d4SSatish Balay   }
41249566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
41259566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
4126b271bb04SBarry Smith   x = (PetscReal)n;
4127b271bb04SBarry Smith   y = (prev - rnorm) / prev;
41289566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
41296934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41309566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41319566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4132b271bb04SBarry Smith   }
4133b271bb04SBarry Smith 
41349566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
41359566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
41369566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
41379566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
4138b271bb04SBarry Smith   x = (PetscReal)n;
4139b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
4140b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
41419566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4142b271bb04SBarry Smith   }
41436934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41449566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41459566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4146b271bb04SBarry Smith   }
4147b271bb04SBarry Smith   prev = rnorm;
41483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4149b271bb04SBarry Smith }
4150b271bb04SBarry Smith 
4151228d79bcSJed Brown /*@
41522d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
41532d157150SStefano Zampini 
41542d157150SStefano Zampini   Collective
41552d157150SStefano Zampini 
41562d157150SStefano Zampini   Input Parameters:
41572d157150SStefano Zampini + snes  - the `SNES` context
41582d157150SStefano Zampini . it    - current iteration
41592d157150SStefano Zampini . xnorm - 2-norm of current iterate
41602d157150SStefano Zampini . snorm - 2-norm of current step
41612d157150SStefano Zampini - fnorm - 2-norm of function
41622d157150SStefano Zampini 
41632d157150SStefano Zampini   Level: developer
41642d157150SStefano Zampini 
41652d157150SStefano Zampini   Note:
4166420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
41672d157150SStefano Zampini   It does not typically need to be called by the user.
41682d157150SStefano Zampini 
4169c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
41702d157150SStefano Zampini @*/
41712d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
41722d157150SStefano Zampini {
41732d157150SStefano Zampini   PetscFunctionBegin;
41742d157150SStefano Zampini   if (!snes->reason) {
41752d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
41762d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
41772d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
41782d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
41792d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
41802d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
41812d157150SStefano Zampini     }
41822d157150SStefano Zampini   }
41832d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
41842d157150SStefano Zampini }
41852d157150SStefano Zampini 
41862d157150SStefano Zampini /*@
41870b4b7b1cSBarry Smith   SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database
4188228d79bcSJed Brown 
4189c3339decSBarry Smith   Collective
4190228d79bcSJed Brown 
4191228d79bcSJed Brown   Input Parameters:
4192f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
41930b4b7b1cSBarry Smith . iter  - current iteration number
41940b4b7b1cSBarry Smith - rnorm - current relative norm of the residual
4195228d79bcSJed Brown 
4196dc4c0fb0SBarry Smith   Level: developer
4197dc4c0fb0SBarry Smith 
4198f6dfbefdSBarry Smith   Note:
4199420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
4200228d79bcSJed Brown   It does not typically need to be called by the user.
4201228d79bcSJed Brown 
42021cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4203228d79bcSJed Brown @*/
4204d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4205d71ae5a4SJacob Faibussowitsch {
42067a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
42077a03ce2fSLisandro Dalcin 
42087a03ce2fSLisandro Dalcin   PetscFunctionBegin;
42099566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
421048a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
42119566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
42123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42137a03ce2fSLisandro Dalcin }
42147a03ce2fSLisandro Dalcin 
42159b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
42169b94acceSBarry Smith 
4217bf388a1fSBarry Smith /*MC
4218f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4219bf388a1fSBarry Smith 
4220bf388a1fSBarry Smith      Synopsis:
4221aaa7dc30SBarry Smith      #include <petscsnes.h>
422237fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4223bf388a1fSBarry Smith 
4224c3339decSBarry Smith      Collective
42251843f636SBarry Smith 
42261843f636SBarry Smith     Input Parameters:
4227f6dfbefdSBarry Smith +    snes - the `SNES` context
4228bf388a1fSBarry Smith .    its - iteration number
4229bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
4230bf388a1fSBarry Smith -    mctx - [optional] monitoring context
4231bf388a1fSBarry Smith 
4232878cb397SSatish Balay    Level: advanced
4233878cb397SSatish Balay 
4234*56296ac4SStefano Zampini .seealso: [](ch_snes), `SNESMonitorSet()`
4235bf388a1fSBarry Smith M*/
4236bf388a1fSBarry Smith 
42379b94acceSBarry Smith /*@C
4238a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
42390b4b7b1cSBarry Smith   iteration of the `SNES` nonlinear solver to display the iteration's
42409b94acceSBarry Smith   progress.
42419b94acceSBarry Smith 
4242c3339decSBarry Smith   Logically Collective
4243fee21e36SBarry Smith 
4244c7afd0dbSLois Curfman McInnes   Input Parameters:
4245f6dfbefdSBarry Smith + snes           - the `SNES` context
424620f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4247420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
424849abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
42499b94acceSBarry Smith 
42509665c990SLois Curfman McInnes   Options Database Keys:
4251f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4252798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4253dc4c0fb0SBarry 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
4254c7afd0dbSLois Curfman McInnes                                 the options database.
42559665c990SLois Curfman McInnes 
4256dc4c0fb0SBarry Smith   Level: intermediate
4257dc4c0fb0SBarry Smith 
4258f6dfbefdSBarry Smith   Note:
42596bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4260f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
42616bc08f3fSLois Curfman McInnes   order in which they were set.
4262639f9d9dSBarry Smith 
4263420bcc1bSBarry Smith   Fortran Note:
4264f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4265025f1a04SBarry Smith 
426649abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn`
42679b94acceSBarry Smith @*/
426849abdd8aSBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy)
4269d71ae5a4SJacob Faibussowitsch {
4270b90d0a6eSBarry Smith   PetscInt  i;
427178064530SBarry Smith   PetscBool identical;
4272b90d0a6eSBarry Smith 
42733a40ed3dSBarry Smith   PetscFunctionBegin;
42740700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4275b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
42769566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
42773ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4278649052a6SBarry Smith   }
42795f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
42806e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4281b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4282835f2295SStefano Zampini   snes->monitorcontext[snes->numbermonitors++] = mctx;
42833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42849b94acceSBarry Smith }
42859b94acceSBarry Smith 
4286a278d85bSSatish Balay /*@
4287f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
42885cd90555SBarry Smith 
4289c3339decSBarry Smith   Logically Collective
4290c7afd0dbSLois Curfman McInnes 
42912fe279fdSBarry Smith   Input Parameter:
4292f6dfbefdSBarry Smith . snes - the `SNES` context
42935cd90555SBarry Smith 
42941a480d89SAdministrator   Options Database Key:
4295a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4296dc4c0fb0SBarry Smith                          into a code by calls to `SNESMonitorSet()`, but does not cancel those
4297c7afd0dbSLois Curfman McInnes                          set via the options database
42985cd90555SBarry Smith 
4299dc4c0fb0SBarry Smith   Level: intermediate
4300dc4c0fb0SBarry Smith 
4301f6dfbefdSBarry Smith   Note:
4302f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
43035cd90555SBarry Smith 
4304*56296ac4SStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESMonitorDefault()`, `SNESMonitorSet()`
43055cd90555SBarry Smith @*/
4306d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4307d71ae5a4SJacob Faibussowitsch {
4308d952e501SBarry Smith   PetscInt i;
4309d952e501SBarry Smith 
43105cd90555SBarry Smith   PetscFunctionBegin;
43110700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4312d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
431348a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4314d952e501SBarry Smith   }
43155cd90555SBarry Smith   snes->numbermonitors = 0;
43163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43175cd90555SBarry Smith }
43185cd90555SBarry Smith 
4319bf388a1fSBarry Smith /*MC
4320bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4321bf388a1fSBarry Smith 
4322bf388a1fSBarry Smith      Synopsis:
4323aaa7dc30SBarry Smith      #include <petscsnes.h>
432437fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4325bf388a1fSBarry Smith 
4326c3339decSBarry Smith      Collective
43271843f636SBarry Smith 
43281843f636SBarry Smith     Input Parameters:
4329f6dfbefdSBarry Smith +    snes - the `SNES` context
4330bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4331bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4332bf388a1fSBarry Smith .    gnorm - 2-norm of current step
43331843f636SBarry Smith .    f - 2-norm of function
43341843f636SBarry Smith -    cctx - [optional] convergence context
43351843f636SBarry Smith 
43361843f636SBarry Smith     Output Parameter:
43371843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4338bf388a1fSBarry Smith 
4339878cb397SSatish Balay    Level: intermediate
4340bf388a1fSBarry Smith 
4341c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
4342bf388a1fSBarry Smith M*/
4343bf388a1fSBarry Smith 
43449b94acceSBarry Smith /*@C
43459b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
43469b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
43479b94acceSBarry Smith 
4348c3339decSBarry Smith   Logically Collective
4349fee21e36SBarry Smith 
4350c7afd0dbSLois Curfman McInnes   Input Parameters:
4351f6dfbefdSBarry Smith + snes                        - the `SNES` context
4352e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4353dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4354dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
43559b94acceSBarry Smith 
435636851e7fSLois Curfman McInnes   Level: advanced
435736851e7fSLois Curfman McInnes 
43581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
43599b94acceSBarry Smith @*/
4360d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4361d71ae5a4SJacob Faibussowitsch {
43623a40ed3dSBarry Smith   PetscFunctionBegin;
43630700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4364e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
43651baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4366bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
43677f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
436885385478SLisandro Dalcin   snes->cnvP                  = cctx;
43693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43709b94acceSBarry Smith }
43719b94acceSBarry Smith 
437252baeb72SSatish Balay /*@
43730b4b7b1cSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation
4374184914b5SBarry Smith 
4375184914b5SBarry Smith   Not Collective
4376184914b5SBarry Smith 
4377184914b5SBarry Smith   Input Parameter:
4378f6dfbefdSBarry Smith . snes - the `SNES` context
4379184914b5SBarry Smith 
4380184914b5SBarry Smith   Output Parameter:
4381f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4382184914b5SBarry Smith 
4383f6dfbefdSBarry Smith   Options Database Key:
43846a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
43856a4d7782SBarry Smith 
4386184914b5SBarry Smith   Level: intermediate
4387184914b5SBarry Smith 
4388f6dfbefdSBarry Smith   Note:
4389f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4390184914b5SBarry Smith 
43911cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4392184914b5SBarry Smith @*/
4393d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4394d71ae5a4SJacob Faibussowitsch {
4395184914b5SBarry Smith   PetscFunctionBegin;
43960700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43974f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4398184914b5SBarry Smith   *reason = snes->reason;
43993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4400184914b5SBarry Smith }
4401184914b5SBarry Smith 
4402c4421ceaSFande Kong /*@C
4403f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4404c4421ceaSFande Kong 
4405c4421ceaSFande Kong   Not Collective
4406c4421ceaSFande Kong 
4407c4421ceaSFande Kong   Input Parameter:
4408f6dfbefdSBarry Smith . snes - the `SNES` context
4409c4421ceaSFande Kong 
4410c4421ceaSFande Kong   Output Parameter:
4411dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4412c4421ceaSFande Kong 
441399c90e12SSatish Balay   Level: beginner
4414c4421ceaSFande Kong 
44151cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4416c4421ceaSFande Kong @*/
4417d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4418d71ae5a4SJacob Faibussowitsch {
4419c4421ceaSFande Kong   PetscFunctionBegin;
4420c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44214f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4422c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
44233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4424c4421ceaSFande Kong }
4425c4421ceaSFande Kong 
442633866048SMatthew G. Knepley /*@
4427f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
442833866048SMatthew G. Knepley 
442933866048SMatthew G. Knepley   Not Collective
443033866048SMatthew G. Knepley 
443133866048SMatthew G. Knepley   Input Parameters:
4432f6dfbefdSBarry Smith + snes   - the `SNES` context
4433f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
443433866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
443533866048SMatthew G. Knepley 
4436f6dfbefdSBarry Smith   Level: developer
4437f6dfbefdSBarry Smith 
4438420bcc1bSBarry Smith   Developer Note:
4439f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
444033866048SMatthew G. Knepley 
44411cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
444233866048SMatthew G. Knepley @*/
4443d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4444d71ae5a4SJacob Faibussowitsch {
444533866048SMatthew G. Knepley   PetscFunctionBegin;
444633866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44475f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
444833866048SMatthew G. Knepley   snes->reason = reason;
44493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
445033866048SMatthew G. Knepley }
445133866048SMatthew G. Knepley 
4452c9005455SLois Curfman McInnes /*@
4453420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4454c9005455SLois Curfman McInnes 
4455c3339decSBarry Smith   Logically Collective
4456fee21e36SBarry Smith 
4457c7afd0dbSLois Curfman McInnes   Input Parameters:
4458f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
44598c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4460cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4461420bcc1bSBarry Smith . na    - size of `a` and `its`
4462f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4463758f92a0SBarry Smith           else it continues storing new values for new nonlinear solves after the old ones
4464c7afd0dbSLois Curfman McInnes 
4465dc4c0fb0SBarry Smith   Level: intermediate
4466dc4c0fb0SBarry Smith 
4467308dcc3eSBarry Smith   Notes:
4468ce78bad3SBarry 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
446977e5a1f9SBarry Smith   default array of length 1,000 is allocated.
4470308dcc3eSBarry Smith 
4471c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4472c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4473c9005455SLois Curfman McInnes   during the section of code that is being timed.
4474c9005455SLois Curfman McInnes 
4475420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4476420bcc1bSBarry Smith 
44771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4478c9005455SLois Curfman McInnes @*/
4479d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4480d71ae5a4SJacob Faibussowitsch {
44813a40ed3dSBarry Smith   PetscFunctionBegin;
44820700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44834f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
44844f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
44857a1ec6d4SBarry Smith   if (!a) {
448677e5a1f9SBarry Smith     if (na == PETSC_DECIDE) na = 1000;
44879566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4488071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4489308dcc3eSBarry Smith   }
4490c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4491758f92a0SBarry Smith   snes->conv_hist_its   = its;
4492115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4493a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4494758f92a0SBarry Smith   snes->conv_hist_reset = reset;
44953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4496758f92a0SBarry Smith }
4497758f92a0SBarry Smith 
4498d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4499c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4500c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
450199e0435eSBarry Smith 
4502d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4503d71ae5a4SJacob Faibussowitsch {
4504308dcc3eSBarry Smith   mxArray   *mat;
4505308dcc3eSBarry Smith   PetscInt   i;
4506308dcc3eSBarry Smith   PetscReal *ar;
4507308dcc3eSBarry Smith 
4508308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4509308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4510f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
451111cc89d2SBarry Smith   return mat;
4512308dcc3eSBarry Smith }
4513308dcc3eSBarry Smith #endif
4514308dcc3eSBarry Smith 
45150c4c9dddSBarry Smith /*@C
4516420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4517758f92a0SBarry Smith 
45183f9fe445SBarry Smith   Not Collective
4519758f92a0SBarry Smith 
4520758f92a0SBarry Smith   Input Parameter:
4521f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4522758f92a0SBarry Smith 
4523758f92a0SBarry Smith   Output Parameters:
4524f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4525758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4526758f92a0SBarry Smith          negative if not converged) for each solve.
452720f4b53cSBarry Smith - na  - size of `a` and `its`
4528758f92a0SBarry Smith 
4529dc4c0fb0SBarry Smith   Level: intermediate
4530dc4c0fb0SBarry Smith 
453120f4b53cSBarry Smith   Note:
453220f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
453320f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
453420f4b53cSBarry Smith   during the section of code that is being timed.
453520f4b53cSBarry Smith 
4536ce78bad3SBarry Smith   Fortran Notes:
4537ce78bad3SBarry Smith   Return the arrays with ``SNESRestoreConvergenceHistory()`
4538ce78bad3SBarry Smith 
4539ce78bad3SBarry Smith   Use the arguments
4540dc4c0fb0SBarry Smith .vb
4541ce78bad3SBarry Smith   PetscReal, pointer :: a(:)
4542ce78bad3SBarry Smith   PetscInt, pointer :: its(:)
4543dc4c0fb0SBarry Smith .ve
4544758f92a0SBarry Smith 
45451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4546758f92a0SBarry Smith @*/
4547d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4548d71ae5a4SJacob Faibussowitsch {
4549758f92a0SBarry Smith   PetscFunctionBegin;
45500700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4551758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4552758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4553115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
45543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4555c9005455SLois Curfman McInnes }
4556c9005455SLois Curfman McInnes 
4557ac226902SBarry Smith /*@C
455876b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4559eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
456053e5d35bSStefano Zampini   it is called just before the Jacobian is "evaluated" and after the function
456153e5d35bSStefano Zampini   evaluation.
456276b2cf59SMatthew Knepley 
4563c3339decSBarry Smith   Logically Collective
456476b2cf59SMatthew Knepley 
456576b2cf59SMatthew Knepley   Input Parameters:
4566a2b725a8SWilliam Gropp + snes - The nonlinear solver context
456753e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn`
456876b2cf59SMatthew Knepley 
4569fe97e370SBarry Smith   Level: advanced
4570fe97e370SBarry Smith 
4571420bcc1bSBarry Smith   Notes:
4572f6dfbefdSBarry 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
4573f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
457453e5d35bSStefano Zampini   This is not used by most users, and it is intended to provide a general hook that is run
457553e5d35bSStefano Zampini   right before the direction step is computed.
4576ce78bad3SBarry Smith 
457753e5d35bSStefano Zampini   Users are free to modify the current residual vector,
457853e5d35bSStefano Zampini   the current linearization point, or any other vector associated to the specific solver used.
457953e5d35bSStefano Zampini   If such modifications take place, it is the user responsibility to update all the relevant
4580ce78bad3SBarry Smith   vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like
4581ce78bad3SBarry Smith .vb
4582ce78bad3SBarry Smith   PetscErrorCode update(SNES snes, PetscInt iteration)
4583ce78bad3SBarry Smith   {
4584ce78bad3SBarry Smith     PetscFunctionBeginUser;
4585ce78bad3SBarry Smith     if (iteration > 0) {
4586ce78bad3SBarry Smith       // update the model parameters here
4587ce78bad3SBarry Smith       Vec x,f;
4588ce78bad3SBarry Smith       PetscCall(SNESGetSolution(snes,&x));
4589ce78bad3SBarry Smith       PetcCall(SNESGetFunction(snes,&f,NULL,NULL));
4590ce78bad3SBarry Smith       PetscCall(SNESComputeFunction(snes,x,f));
4591ce78bad3SBarry Smith     }
4592ce78bad3SBarry Smith     PetscFunctionReturn(PETSC_SUCCESS);
4593ce78bad3SBarry Smith   }
4594ce78bad3SBarry Smith .ve
459576b2cf59SMatthew Knepley 
4596aaa8cc7dSPierre 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.
45976b7fb656SBarry Smith 
4598e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
459953e5d35bSStefano Zampini          `SNESMonitorSet()`
460076b2cf59SMatthew Knepley @*/
460153e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4602d71ae5a4SJacob Faibussowitsch {
460376b2cf59SMatthew Knepley   PetscFunctionBegin;
46040700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4605e7788613SBarry Smith   snes->ops->update = func;
46063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
460776b2cf59SMatthew Knepley }
460876b2cf59SMatthew Knepley 
4609ffeef943SBarry Smith /*@
4610f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
46112a359c20SBarry Smith 
4612c3339decSBarry Smith   Collective
46132a359c20SBarry Smith 
4614e4094ef1SJacob Faibussowitsch   Input Parameters:
4615f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
46162a359c20SBarry Smith - viewer - the viewer to display the reason
46172a359c20SBarry Smith 
46182a359c20SBarry Smith   Options Database Keys:
4619ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4620ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4621eafd5ff0SAlex Lindsay 
4622420bcc1bSBarry Smith   Level: beginner
4623420bcc1bSBarry Smith 
4624f6dfbefdSBarry Smith   Note:
4625f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4626f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
46272a359c20SBarry Smith 
46281cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4629f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4630f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4631db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
46322a359c20SBarry Smith @*/
4633d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4634d71ae5a4SJacob Faibussowitsch {
463575cca76cSMatthew G. Knepley   PetscViewerFormat format;
46362a359c20SBarry Smith   PetscBool         isAscii;
46372a359c20SBarry Smith 
46382a359c20SBarry Smith   PetscFunctionBegin;
463919a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
46409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
46412a359c20SBarry Smith   if (isAscii) {
46429566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
464365bf60d2SBarry Smith     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
464475cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
464575cca76cSMatthew G. Knepley       DM       dm;
464675cca76cSMatthew G. Knepley       Vec      u;
464775cca76cSMatthew G. Knepley       PetscDS  prob;
464875cca76cSMatthew G. Knepley       PetscInt Nf, f;
464995cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
465095cbbfd3SMatthew G. Knepley       void    **exactCtx;
465175cca76cSMatthew G. Knepley       PetscReal error;
465275cca76cSMatthew G. Knepley 
46539566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
46549566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
46559566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
46569566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
46579566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
46589566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
46599566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
46609566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
46619566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
466263a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
466375cca76cSMatthew G. Knepley     }
4664eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
46652a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
466663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
46672a359c20SBarry Smith       } else {
466863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46692a359c20SBarry Smith       }
4670eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
46712a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
467263a3b9bcSJacob 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));
46732a359c20SBarry Smith       } else {
467463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46752a359c20SBarry Smith       }
46762a359c20SBarry Smith     }
467765bf60d2SBarry Smith     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
46782a359c20SBarry Smith   }
46793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46802a359c20SBarry Smith }
46812a359c20SBarry Smith 
4682c4421ceaSFande Kong /*@C
4683c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4684aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4685c4421ceaSFande Kong 
4686c3339decSBarry Smith   Logically Collective
4687c4421ceaSFande Kong 
4688c4421ceaSFande Kong   Input Parameters:
4689f6dfbefdSBarry Smith + snes              - the `SNES` context
4690420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4691420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
469249abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
4693420bcc1bSBarry Smith 
4694420bcc1bSBarry Smith   Calling sequence of `f`:
4695420bcc1bSBarry Smith + snes - the `SNES` context
469649abdd8aSBarry Smith - vctx - [optional] context for private data for the function
4697c4421ceaSFande Kong 
4698c4421ceaSFande Kong   Options Database Keys:
4699f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4700420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4701420bcc1bSBarry Smith                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4702c4421ceaSFande Kong 
4703dc4c0fb0SBarry Smith   Level: intermediate
4704dc4c0fb0SBarry Smith 
4705f6dfbefdSBarry Smith   Note:
4706c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4707f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4708c4421ceaSFande Kong   order in which they were set.
4709c4421ceaSFande Kong 
471049abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`,
471149abdd8aSBarry Smith           `PetscCtxDestroyFn`
4712c4421ceaSFande Kong @*/
471349abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy)
4714d71ae5a4SJacob Faibussowitsch {
4715c4421ceaSFande Kong   PetscInt  i;
4716c4421ceaSFande Kong   PetscBool identical;
4717c4421ceaSFande Kong 
4718c4421ceaSFande Kong   PetscFunctionBegin;
4719c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4720c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
47219566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
47223ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4723c4421ceaSFande Kong   }
47245f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4725c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4726c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4727835f2295SStefano Zampini   snes->reasonviewcontext[snes->numberreasonviews++] = vctx;
47283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4729c4421ceaSFande Kong }
4730c4421ceaSFande Kong 
473191f3e32bSBarry Smith /*@
4732420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
47330b4b7b1cSBarry Smith   All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist.
47342a359c20SBarry Smith 
4735c3339decSBarry Smith   Collective
47362a359c20SBarry Smith 
47372fe279fdSBarry Smith   Input Parameter:
4738f6dfbefdSBarry Smith . snes - the `SNES` object
47392a359c20SBarry Smith 
4740f6dfbefdSBarry Smith   Level: advanced
47412a359c20SBarry Smith 
47421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4743f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
47442a359c20SBarry Smith @*/
4745d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4746d71ae5a4SJacob Faibussowitsch {
47472a359c20SBarry Smith   static PetscBool incall = PETSC_FALSE;
47482a359c20SBarry Smith 
47492a359c20SBarry Smith   PetscFunctionBegin;
47503ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
47512a359c20SBarry Smith   incall = PETSC_TRUE;
4752c4421ceaSFande Kong 
4753c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
475436d43d94SBarry Smith   for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4755c4421ceaSFande Kong 
4756c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
475736d43d94SBarry Smith   if (snes->convergedreasonviewer) {
475836d43d94SBarry Smith     PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
475936d43d94SBarry Smith     PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
476036d43d94SBarry Smith     PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
47612a359c20SBarry Smith   }
47622a359c20SBarry Smith   incall = PETSC_FALSE;
47633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47642a359c20SBarry Smith }
47652a359c20SBarry Smith 
4766487a658cSBarry Smith /*@
47670b4b7b1cSBarry Smith   SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object
47689b94acceSBarry Smith 
4769c3339decSBarry Smith   Collective
4770c7afd0dbSLois Curfman McInnes 
4771b2002411SLois Curfman McInnes   Input Parameters:
4772f6dfbefdSBarry Smith + snes - the `SNES` context
47730b4b7b1cSBarry Smith . b    - the constant part of the equation $F(x) = b$, or `NULL` to use zero.
477485385478SLisandro Dalcin - x    - the solution vector.
47759b94acceSBarry Smith 
4776dc4c0fb0SBarry Smith   Level: beginner
4777dc4c0fb0SBarry Smith 
4778f6dfbefdSBarry Smith   Note:
4779420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4780a9b45538SStefano Zampini   for the nonlinear solve prior to calling `SNESSolve()` .
47818ddd3da0SLois Curfman McInnes 
47821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4783db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4784a9b45538SStefano Zampini           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
47859b94acceSBarry Smith @*/
4786d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4787d71ae5a4SJacob Faibussowitsch {
4788ace3abfcSBarry Smith   PetscBool flg;
4789efd51863SBarry Smith   PetscInt  grid;
47900298fd71SBarry Smith   Vec       xcreated = NULL;
4791caa4e7f2SJed Brown   DM        dm;
4792052efed2SBarry Smith 
47933a40ed3dSBarry Smith   PetscFunctionBegin;
47940700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4795a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4796a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
47970700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
479885385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
479985385478SLisandro Dalcin 
480034b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
480106fc46c8SMatthew G. Knepley   {
480206fc46c8SMatthew G. Knepley     PetscViewer       viewer;
480306fc46c8SMatthew G. Knepley     PetscViewerFormat format;
48047c88af5aSMatthew G. Knepley     PetscInt          num;
480506fc46c8SMatthew G. Knepley     PetscBool         flg;
480606fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
480706fc46c8SMatthew G. Knepley 
480806fc46c8SMatthew G. Knepley     if (!incall) {
480934b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
4810648c30bcSBarry Smith       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
481106fc46c8SMatthew G. Knepley       if (flg) {
481206fc46c8SMatthew G. Knepley         PetscConvEst conv;
481346079b62SMatthew G. Knepley         DM           dm;
481446079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
481546079b62SMatthew G. Knepley         PetscInt     Nf;
481606fc46c8SMatthew G. Knepley 
481706fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
48189566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
48199566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
48209566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
48219566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
48229566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
48239566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
48249566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
48259566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
48269566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
48279566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
48289566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4829648c30bcSBarry Smith         PetscCall(PetscViewerDestroy(&viewer));
48309566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
48319566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
483206fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
483306fc46c8SMatthew G. Knepley       }
483434b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4835b2588ea6SMatthew G. Knepley       num = 1;
48369566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
483734b4d3a8SMatthew G. Knepley       if (flg) {
483834b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
483934b4d3a8SMatthew G. Knepley 
484034b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
48419566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
48429566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48439566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48449566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48459566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
48469566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
48479566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
484834b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
484934b4d3a8SMatthew G. Knepley       }
48507c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
48517c88af5aSMatthew G. Knepley       num = 0;
48529566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
48537c88af5aSMatthew G. Knepley       if (num) {
48547c88af5aSMatthew G. Knepley         DMAdaptor   adaptor;
4855e03fd340SMatthew G. Knepley         const char *prefix;
48567c88af5aSMatthew G. Knepley 
48577c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
48589566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4859e03fd340SMatthew G. Knepley         PetscCall(SNESGetOptionsPrefix(snes, &prefix));
4860e03fd340SMatthew G. Knepley         PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix));
48619566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48629566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48639566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48649566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
4865e5148a0bSMatthew G. Knepley         PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
48669566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
48679566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
48687c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
48697c88af5aSMatthew G. Knepley       }
487006fc46c8SMatthew G. Knepley     }
487106fc46c8SMatthew G. Knepley   }
4872ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4873caa4e7f2SJed Brown   if (!x) {
48749566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
48759566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4876a69afd8bSBarry Smith     x = xcreated;
4877a69afd8bSBarry Smith   }
48789566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4879f05ece33SBarry Smith 
48809566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4881efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
488285385478SLisandro Dalcin     /* set solution vector */
48839566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
48849566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
488585385478SLisandro Dalcin     snes->vec_sol = x;
48869566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4887caa4e7f2SJed Brown 
4888caa4e7f2SJed Brown     /* set affine vector if provided */
48899566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
48909566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
489185385478SLisandro Dalcin     snes->vec_rhs = b;
489285385478SLisandro Dalcin 
48935f80ce2aSJacob 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");
48945f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4895dd8e379bSPierre Jolivet     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4896aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
48979566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
48989566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
48993f149594SLisandro Dalcin 
49007eee914bSBarry Smith     if (!grid) {
49019927e4dfSBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4902dd568438SSatish Balay     }
4903d25893d9SBarry Smith 
4904abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
490512b1dd1aSStefano Zampini     PetscCall(SNESResetCounters(snes));
49062d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
49079566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4908dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
49099566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
49102d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4911422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
49123f149594SLisandro Dalcin 
491337ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
491437ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
491537ec4e1aSPeter Brune 
4916648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
49179566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4918c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
49199566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
49205968eb51SBarry Smith 
49215f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
49229c8e83a9SBarry Smith     if (snes->reason < 0) break;
4923efd51863SBarry Smith     if (grid < snes->gridsequence) {
4924efd51863SBarry Smith       DM  fine;
4925efd51863SBarry Smith       Vec xnew;
4926efd51863SBarry Smith       Mat interp;
4927efd51863SBarry Smith 
49289566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
49295f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
49302eace19aSMatthew G. Knepley       PetscCall(DMGetCoordinatesLocalSetUp(fine));
49319566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
49329566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
49339566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
49349566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
49359566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4936efd51863SBarry Smith       x = xnew;
4937efd51863SBarry Smith 
49389566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
49399566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
49409566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
49419566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
49429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4943efd51863SBarry Smith     }
4944efd51863SBarry Smith   }
49459566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
49469566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
49479566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
49489566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
49493f7e2da0SPeter Brune 
49509566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
49519566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
49523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49539b94acceSBarry Smith }
49549b94acceSBarry Smith 
49559b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
49569b94acceSBarry Smith 
4957cc4c1da9SBarry Smith /*@
49580b4b7b1cSBarry Smith   SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES`
49599b94acceSBarry Smith 
4960c3339decSBarry Smith   Collective
4961fee21e36SBarry Smith 
4962c7afd0dbSLois Curfman McInnes   Input Parameters:
4963f6dfbefdSBarry Smith + snes - the `SNES` context
4964454a90a3SBarry Smith - type - a known method
4965c7afd0dbSLois Curfman McInnes 
4966c7afd0dbSLois Curfman McInnes   Options Database Key:
4967454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
496804d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4969ae12b187SLois Curfman McInnes 
4970dc4c0fb0SBarry Smith   Level: intermediate
4971dc4c0fb0SBarry Smith 
49729b94acceSBarry Smith   Notes:
49730b4b7b1cSBarry Smith   See `SNESType` for available methods (for instance)
4974f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4975c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49764a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4977c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49789b94acceSBarry Smith 
4979f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4980f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4981ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4982ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4983f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4984ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4985ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4986ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4987ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4988b0a32e0cSBarry Smith   appropriate method.
498936851e7fSLois Curfman McInnes 
4990420bcc1bSBarry Smith   Developer Note:
4991f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4992f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
49938f6c3df8SBarry Smith 
49941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
49959b94acceSBarry Smith @*/
4996d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4997d71ae5a4SJacob Faibussowitsch {
4998ace3abfcSBarry Smith   PetscBool match;
49995f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
50003a40ed3dSBarry Smith 
50013a40ed3dSBarry Smith   PetscFunctionBegin;
50020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50034f572ea9SToby Isaac   PetscAssertPointer(type, 2);
500482bf6240SBarry Smith 
50059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
50063ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
500792ff6ae8SBarry Smith 
50089566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
50096adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
501075396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
5011dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
501243547594SStefano Zampini   /* Reinitialize type-specific function pointers in SNESOps structure */
501343547594SStefano Zampini   snes->ops->reset          = NULL;
50149e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
50159e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
50169e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
50179e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
50189e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
50197fe760d5SStefano Zampini 
50207fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
50219566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
50227fe760d5SStefano Zampini 
502375396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
502475396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
5025f5af7f23SKarl Rupp 
50269566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
50279566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
50283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50299b94acceSBarry Smith }
50309b94acceSBarry Smith 
5031cc4c1da9SBarry Smith /*@
5032f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
50339b94acceSBarry Smith 
5034c7afd0dbSLois Curfman McInnes   Not Collective
5035c7afd0dbSLois Curfman McInnes 
50369b94acceSBarry Smith   Input Parameter:
50374b0e389bSBarry Smith . snes - nonlinear solver context
50389b94acceSBarry Smith 
50399b94acceSBarry Smith   Output Parameter:
5040f6dfbefdSBarry Smith . type - `SNES` method (a character string)
50419b94acceSBarry Smith 
504236851e7fSLois Curfman McInnes   Level: intermediate
504336851e7fSLois Curfman McInnes 
50441cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
50459b94acceSBarry Smith @*/
5046d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
5047d71ae5a4SJacob Faibussowitsch {
50483a40ed3dSBarry Smith   PetscFunctionBegin;
50490700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50504f572ea9SToby Isaac   PetscAssertPointer(type, 2);
50517adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
50523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50539b94acceSBarry Smith }
50549b94acceSBarry Smith 
50553cd8a7caSMatthew G. Knepley /*@
5056f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
50573cd8a7caSMatthew G. Knepley 
5058c3339decSBarry Smith   Logically Collective
50593cd8a7caSMatthew G. Knepley 
50603cd8a7caSMatthew G. Knepley   Input Parameters:
5061f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
50623cd8a7caSMatthew G. Knepley - u    - the solution vector
50633cd8a7caSMatthew G. Knepley 
50643cd8a7caSMatthew G. Knepley   Level: beginner
50653cd8a7caSMatthew G. Knepley 
50661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
50673cd8a7caSMatthew G. Knepley @*/
5068d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
5069d71ae5a4SJacob Faibussowitsch {
50703cd8a7caSMatthew G. Knepley   DM dm;
50713cd8a7caSMatthew G. Knepley 
50723cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
50733cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50743cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
50759566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
50769566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
50773cd8a7caSMatthew G. Knepley 
50783cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
50793cd8a7caSMatthew G. Knepley 
50809566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50819566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
50823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50833cd8a7caSMatthew G. Knepley }
50843cd8a7caSMatthew G. Knepley 
508552baeb72SSatish Balay /*@
50869b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
5087f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
50889b94acceSBarry Smith 
5089420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5090c7afd0dbSLois Curfman McInnes 
50919b94acceSBarry Smith   Input Parameter:
5092f6dfbefdSBarry Smith . snes - the `SNES` context
50939b94acceSBarry Smith 
50949b94acceSBarry Smith   Output Parameter:
50959b94acceSBarry Smith . x - the solution
50969b94acceSBarry Smith 
509770e92668SMatthew Knepley   Level: intermediate
509836851e7fSLois Curfman McInnes 
50991cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
51009b94acceSBarry Smith @*/
5101d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
5102d71ae5a4SJacob Faibussowitsch {
51033a40ed3dSBarry Smith   PetscFunctionBegin;
51040700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51054f572ea9SToby Isaac   PetscAssertPointer(x, 2);
510685385478SLisandro Dalcin   *x = snes->vec_sol;
51073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
510870e92668SMatthew Knepley }
510970e92668SMatthew Knepley 
511052baeb72SSatish Balay /*@
51119b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
51129b94acceSBarry Smith   stored.
51139b94acceSBarry Smith 
5114420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5115c7afd0dbSLois Curfman McInnes 
51169b94acceSBarry Smith   Input Parameter:
5117f6dfbefdSBarry Smith . snes - the `SNES` context
51189b94acceSBarry Smith 
51199b94acceSBarry Smith   Output Parameter:
51209b94acceSBarry Smith . x - the solution update
51219b94acceSBarry Smith 
512236851e7fSLois Curfman McInnes   Level: advanced
512336851e7fSLois Curfman McInnes 
51241cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
51259b94acceSBarry Smith @*/
5126d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
5127d71ae5a4SJacob Faibussowitsch {
51283a40ed3dSBarry Smith   PetscFunctionBegin;
51290700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51304f572ea9SToby Isaac   PetscAssertPointer(x, 2);
513185385478SLisandro Dalcin   *x = snes->vec_sol_update;
51323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51339b94acceSBarry Smith }
51349b94acceSBarry Smith 
51359b94acceSBarry Smith /*@C
5136f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
51379b94acceSBarry Smith 
5138420bcc1bSBarry Smith   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
5139c7afd0dbSLois Curfman McInnes 
51409b94acceSBarry Smith   Input Parameter:
5141f6dfbefdSBarry Smith . snes - the `SNES` context
51429b94acceSBarry Smith 
5143d8d19677SJose E. Roman   Output Parameters:
5144dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
51458434afd1SBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
5146dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
51479b94acceSBarry Smith 
514836851e7fSLois Curfman McInnes   Level: advanced
514936851e7fSLois Curfman McInnes 
5150f6dfbefdSBarry Smith   Note:
5151dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
515204edfde5SBarry Smith 
51538434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
51549b94acceSBarry Smith @*/
51558434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
5156d71ae5a4SJacob Faibussowitsch {
51576cab3a1bSJed Brown   DM dm;
5158a63bb30eSJed Brown 
51593a40ed3dSBarry Smith   PetscFunctionBegin;
51600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5161a63bb30eSJed Brown   if (r) {
5162a63bb30eSJed Brown     if (!snes->vec_func) {
5163a63bb30eSJed Brown       if (snes->vec_rhs) {
51649566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5165a63bb30eSJed Brown       } else if (snes->vec_sol) {
51669566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5167a63bb30eSJed Brown       } else if (snes->dm) {
51689566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5169a63bb30eSJed Brown       }
5170a63bb30eSJed Brown     }
5171a63bb30eSJed Brown     *r = snes->vec_func;
5172a63bb30eSJed Brown   }
51739566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51749566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
51753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51769b94acceSBarry Smith }
51779b94acceSBarry Smith 
5178c79ef259SPeter Brune /*@C
517937fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5180c79ef259SPeter Brune 
5181c79ef259SPeter Brune   Input Parameter:
5182f6dfbefdSBarry Smith . snes - the `SNES` context
5183c79ef259SPeter Brune 
5184d8d19677SJose E. Roman   Output Parameters:
51858434afd1SBarry Smith + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5186dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
5187c79ef259SPeter Brune 
5188c79ef259SPeter Brune   Level: advanced
5189c79ef259SPeter Brune 
51908434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5191c79ef259SPeter Brune @*/
51928434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5193d71ae5a4SJacob Faibussowitsch {
51946cab3a1bSJed Brown   DM dm;
51956cab3a1bSJed Brown 
5196646217ecSPeter Brune   PetscFunctionBegin;
5197646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51989566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51999566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
52003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5201646217ecSPeter Brune }
5202646217ecSPeter Brune 
5203cc4c1da9SBarry Smith /*@
52043c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5205f6dfbefdSBarry Smith   `SNES` options in the database.
52063c7409f5SSatish Balay 
5207c3339decSBarry Smith   Logically Collective
5208fee21e36SBarry Smith 
5209d8d19677SJose E. Roman   Input Parameters:
5210f6dfbefdSBarry Smith + snes   - the `SNES` context
5211c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5212c7afd0dbSLois Curfman McInnes 
5213dc4c0fb0SBarry Smith   Level: advanced
5214dc4c0fb0SBarry Smith 
5215f6dfbefdSBarry Smith   Note:
5216a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5217c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5218d850072dSLois Curfman McInnes 
52191cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
52203c7409f5SSatish Balay @*/
5221d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5222d71ae5a4SJacob Faibussowitsch {
52233a40ed3dSBarry Smith   PetscFunctionBegin;
52240700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52259566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
52269566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
522735f5d045SPeter Brune   if (snes->linesearch) {
52289566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
52299566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
523035f5d045SPeter Brune   }
52319566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
52323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52333c7409f5SSatish Balay }
52343c7409f5SSatish Balay 
5235cc4c1da9SBarry Smith /*@
5236f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5237f6dfbefdSBarry Smith   `SNES` options in the database.
52383c7409f5SSatish Balay 
5239c3339decSBarry Smith   Logically Collective
5240fee21e36SBarry Smith 
5241c7afd0dbSLois Curfman McInnes   Input Parameters:
5242f6dfbefdSBarry Smith + snes   - the `SNES` context
5243c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5244c7afd0dbSLois Curfman McInnes 
5245dc4c0fb0SBarry Smith   Level: advanced
5246dc4c0fb0SBarry Smith 
5247f6dfbefdSBarry Smith   Note:
5248a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5249c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5250d850072dSLois Curfman McInnes 
52511cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
52523c7409f5SSatish Balay @*/
5253d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5254d71ae5a4SJacob Faibussowitsch {
52553a40ed3dSBarry Smith   PetscFunctionBegin;
52560700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52579566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
52589566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
525935f5d045SPeter Brune   if (snes->linesearch) {
52609566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
52619566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
526235f5d045SPeter Brune   }
52639566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
52643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52653c7409f5SSatish Balay }
52663c7409f5SSatish Balay 
5267cc4c1da9SBarry Smith /*@
5268f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5269f6dfbefdSBarry Smith   `SNES` options in the database.
52703c7409f5SSatish Balay 
5271c7afd0dbSLois Curfman McInnes   Not Collective
5272c7afd0dbSLois Curfman McInnes 
52733c7409f5SSatish Balay   Input Parameter:
5274f6dfbefdSBarry Smith . snes - the `SNES` context
52753c7409f5SSatish Balay 
52763c7409f5SSatish Balay   Output Parameter:
52773c7409f5SSatish Balay . prefix - pointer to the prefix string used
52783c7409f5SSatish Balay 
527936851e7fSLois Curfman McInnes   Level: advanced
528036851e7fSLois Curfman McInnes 
52811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
52823c7409f5SSatish Balay @*/
5283d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5284d71ae5a4SJacob Faibussowitsch {
52853a40ed3dSBarry Smith   PetscFunctionBegin;
52860700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52879566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
52883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52893c7409f5SSatish Balay }
52903c7409f5SSatish Balay 
52913cea93caSBarry Smith /*@C
52921c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
52931c84c290SBarry Smith 
529420f4b53cSBarry Smith   Not Collective
52951c84c290SBarry Smith 
52961c84c290SBarry Smith   Input Parameters:
529720f4b53cSBarry Smith + sname    - name of a new user-defined solver
529820f4b53cSBarry Smith - function - routine to create method context
52991c84c290SBarry Smith 
5300dc4c0fb0SBarry Smith   Level: advanced
5301dc4c0fb0SBarry Smith 
5302f6dfbefdSBarry Smith   Note:
5303f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
53041c84c290SBarry Smith 
5305e4094ef1SJacob Faibussowitsch   Example Usage:
53061c84c290SBarry Smith .vb
5307bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
53081c84c290SBarry Smith .ve
53091c84c290SBarry Smith 
53101c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
5311b44f4de4SBarry Smith .vb
5312b44f4de4SBarry Smith   SNESSetType(snes, "my_solver")
5313b44f4de4SBarry Smith .ve
53141c84c290SBarry Smith   or at runtime via the option
5315b44f4de4SBarry Smith .vb
5316b44f4de4SBarry Smith   -snes_type my_solver
5317b44f4de4SBarry Smith .ve
53181c84c290SBarry Smith 
53191cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
53203cea93caSBarry Smith @*/
5321d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5322d71ae5a4SJacob Faibussowitsch {
5323b2002411SLois Curfman McInnes   PetscFunctionBegin;
53249566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
53259566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
53263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5327b2002411SLois Curfman McInnes }
5328da9b6338SBarry Smith 
5329d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5330d71ae5a4SJacob Faibussowitsch {
533177431f27SBarry Smith   PetscInt    N, i, j;
5332da9b6338SBarry Smith   Vec         u, uh, fh;
5333da9b6338SBarry Smith   PetscScalar value;
5334da9b6338SBarry Smith   PetscReal   norm;
5335da9b6338SBarry Smith 
5336da9b6338SBarry Smith   PetscFunctionBegin;
53379566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
53389566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
53399566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5340da9b6338SBarry Smith 
5341da9b6338SBarry Smith   /* currently only works for sequential */
53429566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
53439566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5344da9b6338SBarry Smith   for (i = 0; i < N; i++) {
53459566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
534663a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5347da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
53488b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
53499566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
53509566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
53519566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
535263a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5353da9b6338SBarry Smith       value = -value;
53549566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5355da9b6338SBarry Smith     }
5356da9b6338SBarry Smith   }
53579566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
53589566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
53593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5360da9b6338SBarry Smith }
536171f87433Sdalcinl 
536271f87433Sdalcinl /*@
5363f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
536471f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
536571f87433Sdalcinl   Newton method.
536671f87433Sdalcinl 
5367c3339decSBarry Smith   Logically Collective
536871f87433Sdalcinl 
536971f87433Sdalcinl   Input Parameters:
5370f6dfbefdSBarry Smith + snes - `SNES` context
5371f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
537271f87433Sdalcinl 
5373f6dfbefdSBarry Smith   Options Database Keys:
537464ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
537564ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
537664ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
537764ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
537864ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
537964ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
538064ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
538164ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
538264ba62caSBarry Smith 
5383dc4c0fb0SBarry Smith   Level: advanced
5384dc4c0fb0SBarry Smith 
5385f6dfbefdSBarry Smith   Note:
5386f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
538771f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
53881d27aa22SBarry Smith   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
538971f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
539071f87433Sdalcinl   solver.
539171f87433Sdalcinl 
53921cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
539371f87433Sdalcinl @*/
5394d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5395d71ae5a4SJacob Faibussowitsch {
539671f87433Sdalcinl   PetscFunctionBegin;
53970700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5398acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
539971f87433Sdalcinl   snes->ksp_ewconv = flag;
54003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
540171f87433Sdalcinl }
540271f87433Sdalcinl 
540371f87433Sdalcinl /*@
5404f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
540571f87433Sdalcinl   for computing relative tolerance for linear solvers within an
540671f87433Sdalcinl   inexact Newton method.
540771f87433Sdalcinl 
540871f87433Sdalcinl   Not Collective
540971f87433Sdalcinl 
541071f87433Sdalcinl   Input Parameter:
5411f6dfbefdSBarry Smith . snes - `SNES` context
541271f87433Sdalcinl 
541371f87433Sdalcinl   Output Parameter:
5414f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
541571f87433Sdalcinl 
541671f87433Sdalcinl   Level: advanced
541771f87433Sdalcinl 
54181cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
541971f87433Sdalcinl @*/
5420d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5421d71ae5a4SJacob Faibussowitsch {
542271f87433Sdalcinl   PetscFunctionBegin;
54230700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54244f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
542571f87433Sdalcinl   *flag = snes->ksp_ewconv;
54263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
542771f87433Sdalcinl }
542871f87433Sdalcinl 
542971f87433Sdalcinl /*@
5430fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
543171f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
543271f87433Sdalcinl   Newton method.
543371f87433Sdalcinl 
5434c3339decSBarry Smith   Logically Collective
543571f87433Sdalcinl 
543671f87433Sdalcinl   Input Parameters:
5437f6dfbefdSBarry Smith + snes      - `SNES` context
54380f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
543971f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
544071f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
544171f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
544271f87433Sdalcinl              (0 <= gamma2 <= 1)
544371f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
544471f87433Sdalcinl . alpha2    - power for safeguard
544571f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
544671f87433Sdalcinl 
5447dc4c0fb0SBarry Smith   Level: advanced
5448dc4c0fb0SBarry Smith 
5449f6dfbefdSBarry Smith   Notes:
545071f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
545171f87433Sdalcinl 
545277e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the default for any of the parameters.
545371f87433Sdalcinl 
54541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
545571f87433Sdalcinl @*/
5456d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5457d71ae5a4SJacob Faibussowitsch {
5458fa9f3622SBarry Smith   SNESKSPEW *kctx;
54595fd66863SKarl Rupp 
546071f87433Sdalcinl   PetscFunctionBegin;
54610700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5462fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
54635f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5464c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5465c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5466c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5467c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5468c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5469c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5470c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
547171f87433Sdalcinl 
547277e5a1f9SBarry Smith   if (version != PETSC_CURRENT) kctx->version = version;
547377e5a1f9SBarry Smith   if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0;
547477e5a1f9SBarry Smith   if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max;
547577e5a1f9SBarry Smith   if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma;
547677e5a1f9SBarry Smith   if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha;
547777e5a1f9SBarry Smith   if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2;
547877e5a1f9SBarry Smith   if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold;
547971f87433Sdalcinl 
54800f0abf79SStefano 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);
54810b121fc5SBarry 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);
54820b121fc5SBarry 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);
54830b121fc5SBarry 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);
54840b121fc5SBarry 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);
54850b121fc5SBarry 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);
54863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
548771f87433Sdalcinl }
548871f87433Sdalcinl 
548971f87433Sdalcinl /*@
5490fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
549171f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
549271f87433Sdalcinl   Newton method.
549371f87433Sdalcinl 
549471f87433Sdalcinl   Not Collective
549571f87433Sdalcinl 
549697bb3fdcSJose E. Roman   Input Parameter:
5497f6dfbefdSBarry Smith . snes - `SNES` context
549871f87433Sdalcinl 
549971f87433Sdalcinl   Output Parameters:
55000f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
550171f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
550271f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5503bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
550471f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
550571f87433Sdalcinl . alpha2    - power for safeguard
550671f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
550771f87433Sdalcinl 
550871f87433Sdalcinl   Level: advanced
550971f87433Sdalcinl 
55101cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
551171f87433Sdalcinl @*/
5512d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5513d71ae5a4SJacob Faibussowitsch {
5514fa9f3622SBarry Smith   SNESKSPEW *kctx;
55155fd66863SKarl Rupp 
551671f87433Sdalcinl   PetscFunctionBegin;
55170700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5518fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
55195f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
552071f87433Sdalcinl   if (version) *version = kctx->version;
552171f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
552271f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
552371f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
552471f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
552571f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
552671f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
55273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
552871f87433Sdalcinl }
552971f87433Sdalcinl 
55305c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5531d71ae5a4SJacob Faibussowitsch {
55325c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5533fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
553477e5a1f9SBarry Smith   PetscReal  rtol = PETSC_CURRENT, stol;
553571f87433Sdalcinl 
553671f87433Sdalcinl   PetscFunctionBegin;
55373ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
553830058271SDmitry Karpeev   if (!snes->iter) {
553930058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
55409566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
55410f0abf79SStefano Zampini   } else {
55420fdf79fbSJacob 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);
554371f87433Sdalcinl     if (kctx->version == 1) {
55440f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
554585ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
554671f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
554771f87433Sdalcinl     } else if (kctx->version == 2) {
554885ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
554985ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
555071f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
555171f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
555285ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
555371f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
555485ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
555571f87433Sdalcinl       stol = PetscMax(rtol, stol);
555671f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
555771f87433Sdalcinl       /* safeguard: avoid oversolving */
555830058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
555971f87433Sdalcinl       stol = PetscMax(rtol, stol);
556071f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
55610fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
55620fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
55630f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
55640f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
55650f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
55660f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
55670f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
55680f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
55690f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
55700f0abf79SStefano Zampini 
5571a4598233SStefano 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;
55720f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
55730f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
55740f0abf79SStefano Zampini       kctx->rk_last     = rk;
55750fdf79fbSJacob Faibussowitsch     }
55760f0abf79SStefano Zampini   }
55770f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
557871f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
557977e5a1f9SBarry Smith   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT));
558063a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
55813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
558271f87433Sdalcinl }
558371f87433Sdalcinl 
55845c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5585d71ae5a4SJacob Faibussowitsch {
55865c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5587fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
558871f87433Sdalcinl   PCSide     pcside;
558971f87433Sdalcinl   Vec        lres;
559071f87433Sdalcinl 
559171f87433Sdalcinl   PetscFunctionBegin;
55923ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
55939566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
559471dbe336SPeter Brune   kctx->norm_last = snes->norm;
55950f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
55964f00ce20SMatthew G. Knepley     PC        pc;
55970f0abf79SStefano Zampini     PetscBool getRes;
55984f00ce20SMatthew G. Knepley 
55999566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
56000f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
56010f0abf79SStefano Zampini     if (!getRes) {
56020f0abf79SStefano Zampini       KSPNormType normtype;
56030f0abf79SStefano Zampini 
56040f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
56050f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
56060f0abf79SStefano Zampini     }
56079566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
56080f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
56099566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
561071f87433Sdalcinl     } else {
561171f87433Sdalcinl       /* KSP residual is preconditioned residual */
561271f87433Sdalcinl       /* compute true linear residual norm */
56130f0abf79SStefano Zampini       Mat J;
56140f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
56159566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
56160f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
56179566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
56189566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
56199566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
562071f87433Sdalcinl     }
562171f87433Sdalcinl   }
56223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
562371f87433Sdalcinl }
562471f87433Sdalcinl 
5625d4211eb9SBarry Smith /*@
5626f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5627d4211eb9SBarry Smith 
5628420bcc1bSBarry Smith   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5629d4211eb9SBarry Smith 
5630d4211eb9SBarry Smith   Input Parameter:
5631f6dfbefdSBarry Smith . snes - the `SNES` context
5632d4211eb9SBarry Smith 
5633d4211eb9SBarry Smith   Output Parameter:
5634f6dfbefdSBarry Smith . ksp - the `KSP` context
5635d4211eb9SBarry Smith 
5636dc4c0fb0SBarry Smith   Level: beginner
5637dc4c0fb0SBarry Smith 
5638d4211eb9SBarry Smith   Notes:
5639f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5640d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5641f6dfbefdSBarry Smith   `PC` contexts as well.
5642f6dfbefdSBarry Smith 
56430b4b7b1cSBarry 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.
5644d4211eb9SBarry Smith 
56451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5646d4211eb9SBarry Smith @*/
5647d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5648d71ae5a4SJacob Faibussowitsch {
564971f87433Sdalcinl   PetscFunctionBegin;
5650d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56514f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5652d4211eb9SBarry Smith 
5653d4211eb9SBarry Smith   if (!snes->ksp) {
56549566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
56559566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5656d4211eb9SBarry Smith 
56575c0db29aSPierre Jolivet     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
56585c0db29aSPierre Jolivet     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5659a5c2985bSBarry Smith 
56609566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
56619566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5662d4211eb9SBarry Smith   }
5663d4211eb9SBarry Smith   *ksp = snes->ksp;
56643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
566571f87433Sdalcinl }
56666c699258SBarry Smith 
5667af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
56686c699258SBarry Smith /*@
56690b4b7b1cSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners
56706c699258SBarry Smith 
5671c3339decSBarry Smith   Logically Collective
56726c699258SBarry Smith 
56736c699258SBarry Smith   Input Parameters:
56742a808120SBarry Smith + snes - the nonlinear solver context
5675420bcc1bSBarry Smith - dm   - the `DM`, cannot be `NULL`
5676dc4c0fb0SBarry Smith 
5677dc4c0fb0SBarry Smith   Level: intermediate
56786c699258SBarry Smith 
5679f6dfbefdSBarry Smith   Note:
5680f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5681f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5682e03a659cSJed Brown   problems using the same function space.
5683e03a659cSJed Brown 
5684420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
56856c699258SBarry Smith @*/
5686d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5687d71ae5a4SJacob Faibussowitsch {
5688345fed2cSBarry Smith   KSP    ksp;
5689942e3340SBarry Smith   DMSNES sdm;
56906c699258SBarry Smith 
56916c699258SBarry Smith   PetscFunctionBegin;
56920700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56932a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
56949566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5695942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
569651f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
56979566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
56989566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5699f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
57006cab3a1bSJed Brown     }
57019566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
57029566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
57036cab3a1bSJed Brown   }
57046c699258SBarry Smith   snes->dm     = dm;
5705116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5706f5af7f23SKarl Rupp 
57079566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
57089566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
57099566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5710efd4aadfSBarry Smith   if (snes->npc) {
57119566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
57129566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
57132c155ee1SBarry Smith   }
57143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57156c699258SBarry Smith }
57166c699258SBarry Smith 
57176c699258SBarry Smith /*@
57180b4b7b1cSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners
57196c699258SBarry Smith 
57200b4b7b1cSBarry Smith   Not Collective but `dm` obtained is parallel on `snes`
57216c699258SBarry Smith 
57226c699258SBarry Smith   Input Parameter:
5723420bcc1bSBarry Smith . snes - the `SNES` context
57246c699258SBarry Smith 
57256c699258SBarry Smith   Output Parameter:
5726420bcc1bSBarry Smith . dm - the `DM`
57276c699258SBarry Smith 
57286c699258SBarry Smith   Level: intermediate
57296c699258SBarry Smith 
5730420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
57316c699258SBarry Smith @*/
5732d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5733d71ae5a4SJacob Faibussowitsch {
57346c699258SBarry Smith   PetscFunctionBegin;
57350700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57366cab3a1bSJed Brown   if (!snes->dm) {
57379566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5738116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
57396cab3a1bSJed Brown   }
57406c699258SBarry Smith   *dm = snes->dm;
57413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57426c699258SBarry Smith }
57430807856dSBarry Smith 
574431823bd8SMatthew G Knepley /*@
5745be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
574631823bd8SMatthew G Knepley 
5747c3339decSBarry Smith   Collective
574831823bd8SMatthew G Knepley 
574931823bd8SMatthew G Knepley   Input Parameters:
5750f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
575162842358SBarry Smith - npc  - the `SNES` nonlinear preconditioner object
575262842358SBarry Smith 
575362842358SBarry Smith   Options Database Key:
575462842358SBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
575531823bd8SMatthew G Knepley 
5756dc4c0fb0SBarry Smith   Level: developer
5757dc4c0fb0SBarry Smith 
575831823bd8SMatthew G Knepley   Notes:
575962842358SBarry Smith   This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API.
576031823bd8SMatthew G Knepley 
5761f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5762f6dfbefdSBarry Smith 
5763420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
576431823bd8SMatthew G Knepley @*/
5765d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5766d71ae5a4SJacob Faibussowitsch {
576731823bd8SMatthew G Knepley   PetscFunctionBegin;
576831823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5769f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5770f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5771f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
57729566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5773f6dfbefdSBarry Smith   snes->npc = npc;
57743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
577531823bd8SMatthew G Knepley }
577631823bd8SMatthew G Knepley 
577731823bd8SMatthew G Knepley /*@
5778f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
577931823bd8SMatthew G Knepley 
57800b4b7b1cSBarry Smith   Not Collective; but any changes to the obtained the `pc` object must be applied collectively
578131823bd8SMatthew G Knepley 
578231823bd8SMatthew G Knepley   Input Parameter:
5783f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
578431823bd8SMatthew G Knepley 
578531823bd8SMatthew G Knepley   Output Parameter:
578662842358SBarry Smith . pc - the `SNES` preconditioner context
578731823bd8SMatthew G Knepley 
5788f6dfbefdSBarry Smith   Options Database Key:
5789f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5790b5badacbSBarry Smith 
57910b4b7b1cSBarry Smith   Level: advanced
5792dc4c0fb0SBarry Smith 
579395452b02SPatrick Sanan   Notes:
57940b4b7b1cSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will
57950b4b7b1cSBarry Smith   be used as the nonlinear preconditioner for the current `SNES`.
5796be95d8f1SBarry Smith 
5797f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
579862842358SBarry Smith   `SNES`. These may be overwritten if needed.
579962842358SBarry Smith 
580062842358SBarry Smith   Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner
5801951fe5abSBarry Smith 
58021cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
580331823bd8SMatthew G Knepley @*/
5804d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5805d71ae5a4SJacob Faibussowitsch {
5806a64e098fSPeter Brune   const char *optionsprefix;
580731823bd8SMatthew G Knepley 
580831823bd8SMatthew G Knepley   PetscFunctionBegin;
580931823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58104f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5811efd4aadfSBarry Smith   if (!snes->npc) {
5812ec785e5bSStefano Zampini     void *ctx;
5813ec785e5bSStefano Zampini 
58149566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
58159566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
58169566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
58179566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
58189566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5819fb87a551SStefano Zampini     if (snes->ops->usercompute) {
582049abdd8aSBarry Smith       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy));
5821fb87a551SStefano Zampini     } else {
5822ec785e5bSStefano Zampini       PetscCall(SNESGetApplicationContext(snes, &ctx));
5823ec785e5bSStefano Zampini       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5824fb87a551SStefano Zampini     }
58259566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
582631823bd8SMatthew G Knepley   }
5827efd4aadfSBarry Smith   *pc = snes->npc;
58283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
582931823bd8SMatthew G Knepley }
583031823bd8SMatthew G Knepley 
58313ad1a0b9SPatrick Farrell /*@
58320b4b7b1cSBarry Smith   SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES`
58333ad1a0b9SPatrick Farrell 
58343ad1a0b9SPatrick Farrell   Not Collective
58353ad1a0b9SPatrick Farrell 
58363ad1a0b9SPatrick Farrell   Input Parameter:
5837f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
58383ad1a0b9SPatrick Farrell 
58393ad1a0b9SPatrick Farrell   Output Parameter:
5840420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
58413ad1a0b9SPatrick Farrell 
58423ad1a0b9SPatrick Farrell   Level: developer
58433ad1a0b9SPatrick Farrell 
58441cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
58453ad1a0b9SPatrick Farrell @*/
5846d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5847d71ae5a4SJacob Faibussowitsch {
58483ad1a0b9SPatrick Farrell   PetscFunctionBegin;
58493ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5850835f2295SStefano Zampini   PetscAssertPointer(has_npc, 2);
5851835f2295SStefano Zampini   *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE;
58523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58533ad1a0b9SPatrick Farrell }
58543ad1a0b9SPatrick Farrell 
5855c40d0f55SPeter Brune /*@
585662842358SBarry Smith   SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`.
5857c40d0f55SPeter Brune 
5858c3339decSBarry Smith   Logically Collective
5859c40d0f55SPeter Brune 
5860c40d0f55SPeter Brune   Input Parameter:
5861f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5862c40d0f55SPeter Brune 
5863c40d0f55SPeter Brune   Output Parameter:
5864c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5865c40d0f55SPeter Brune .vb
58662d547940SBarry Smith       PC_LEFT  - left preconditioning
58672d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5868c40d0f55SPeter Brune .ve
5869c40d0f55SPeter Brune 
5870f6dfbefdSBarry Smith   Options Database Key:
587167b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5872c40d0f55SPeter Brune 
5873dc4c0fb0SBarry Smith   Level: intermediate
5874dc4c0fb0SBarry Smith 
5875f6dfbefdSBarry Smith   Note:
5876f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
58772d547940SBarry Smith 
587862842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5879c40d0f55SPeter Brune @*/
5880d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5881d71ae5a4SJacob Faibussowitsch {
5882c40d0f55SPeter Brune   PetscFunctionBegin;
5883c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5884c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5885b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
588654c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5887efd4aadfSBarry Smith   snes->npcside = side;
58883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5889c40d0f55SPeter Brune }
5890c40d0f55SPeter Brune 
5891c40d0f55SPeter Brune /*@
589262842358SBarry Smith   SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`.
5893c40d0f55SPeter Brune 
5894c40d0f55SPeter Brune   Not Collective
5895c40d0f55SPeter Brune 
5896c40d0f55SPeter Brune   Input Parameter:
5897f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5898c40d0f55SPeter Brune 
5899c40d0f55SPeter Brune   Output Parameter:
5900c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5901c40d0f55SPeter Brune .vb
5902f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5903f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5904c40d0f55SPeter Brune .ve
5905c40d0f55SPeter Brune 
5906c40d0f55SPeter Brune   Level: intermediate
5907c40d0f55SPeter Brune 
590862842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5909c40d0f55SPeter Brune @*/
5910d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5911d71ae5a4SJacob Faibussowitsch {
5912c40d0f55SPeter Brune   PetscFunctionBegin;
5913c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
59144f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5915efd4aadfSBarry Smith   *side = snes->npcside;
59163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5917c40d0f55SPeter Brune }
5918c40d0f55SPeter Brune 
59199e764e56SPeter Brune /*@
59200b4b7b1cSBarry Smith   SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES`
59219e764e56SPeter Brune 
5922c3339decSBarry Smith   Collective
59239e764e56SPeter Brune 
59249e764e56SPeter Brune   Input Parameters:
5925f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
59269e764e56SPeter Brune - linesearch - the linesearch object
59279e764e56SPeter Brune 
5928dc4c0fb0SBarry Smith   Level: developer
5929dc4c0fb0SBarry Smith 
5930f6dfbefdSBarry Smith   Note:
5931420bcc1bSBarry Smith   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
59329e764e56SPeter Brune   to configure it using the API).
59339e764e56SPeter Brune 
5934420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
59359e764e56SPeter Brune @*/
5936d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5937d71ae5a4SJacob Faibussowitsch {
59389e764e56SPeter Brune   PetscFunctionBegin;
59399e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5940f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
59419e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
59429566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
59439566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5944f5af7f23SKarl Rupp 
59459e764e56SPeter Brune   snes->linesearch = linesearch;
59463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59479e764e56SPeter Brune }
59489e764e56SPeter Brune 
5949a34ceb2aSJed Brown /*@
595062842358SBarry Smith   SNESGetLineSearch - Returns the line search associated with the `SNES`.
59519e764e56SPeter Brune 
59529e764e56SPeter Brune   Not Collective
59539e764e56SPeter Brune 
59549e764e56SPeter Brune   Input Parameter:
5955f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
59569e764e56SPeter Brune 
59579e764e56SPeter Brune   Output Parameter:
59589e764e56SPeter Brune . linesearch - linesearch context
59599e764e56SPeter Brune 
5960162e0bf5SPeter Brune   Level: beginner
59619e764e56SPeter Brune 
596262842358SBarry Smith   Notes:
596362842358SBarry Smith   It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`.
596462842358SBarry Smith 
596562842358SBarry Smith   You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options.
596662842358SBarry Smith 
596762842358SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`
59689e764e56SPeter Brune @*/
5969d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5970d71ae5a4SJacob Faibussowitsch {
59719e764e56SPeter Brune   const char *optionsprefix;
59729e764e56SPeter Brune 
59739e764e56SPeter Brune   PetscFunctionBegin;
59749e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
59754f572ea9SToby Isaac   PetscAssertPointer(linesearch, 2);
59769e764e56SPeter Brune   if (!snes->linesearch) {
59779566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
59789566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
59799566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
59809566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
59819566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
59829e764e56SPeter Brune   }
59839e764e56SPeter Brune   *linesearch = snes->linesearch;
59843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59859e764e56SPeter Brune }
5986