xref: /petsc/src/snes/interface/snes.c (revision 126519442fb4dd57a5f782a20905ab3872bce6dc)
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);
1504936397dSBarry Smith   snes->domainerror = PETSC_TRUE;
1513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1524936397dSBarry Smith }
1534936397dSBarry Smith 
1546a388c36SPeter Brune /*@
155f6dfbefdSBarry Smith   SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation.
15607b62357SFande Kong 
157c3339decSBarry Smith   Logically Collective
15807b62357SFande Kong 
1592fe279fdSBarry Smith   Input Parameter:
160f6dfbefdSBarry Smith . snes - the `SNES` context
16107b62357SFande Kong 
16207b62357SFande Kong   Level: advanced
16307b62357SFande Kong 
164ced0f3aeSBarry Smith   Notes:
165ced0f3aeSBarry Smith   If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
166ced0f3aeSBarry Smith 
167ced0f3aeSBarry Smith   You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
168ced0f3aeSBarry Smith 
169f0b84518SBarry Smith   You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
170f0b84518SBarry Smith   `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
171f0b84518SBarry Smith 
1728434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`,
173ced0f3aeSBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`
17407b62357SFande Kong @*/
175d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes)
176d71ae5a4SJacob Faibussowitsch {
17707b62357SFande Kong   PetscFunctionBegin;
17807b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1795f80ce2aSJacob Faibussowitsch   PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense");
18007b62357SFande Kong   snes->jacobiandomainerror = PETSC_TRUE;
1813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18207b62357SFande Kong }
18307b62357SFande Kong 
18407b62357SFande Kong /*@
185f6dfbefdSBarry Smith   SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` Jacobian domain error after
186420bcc1bSBarry 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.
187b351a90bSFande Kong 
188c3339decSBarry Smith   Logically Collective
189b351a90bSFande Kong 
190b351a90bSFande Kong   Input Parameters:
19120f4b53cSBarry Smith + snes - the `SNES` context
192f6dfbefdSBarry Smith - flg  - indicates if or not to check Jacobian domain error after each Jacobian evaluation
193b351a90bSFande Kong 
194b351a90bSFande Kong   Level: advanced
195b351a90bSFande Kong 
196f6dfbefdSBarry Smith   Note:
197f6dfbefdSBarry Smith   Checks require one extra parallel synchronization for each Jacobian evaluation
198f6dfbefdSBarry Smith 
1998434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()`
200b351a90bSFande Kong @*/
201d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg)
202d71ae5a4SJacob Faibussowitsch {
203b351a90bSFande Kong   PetscFunctionBegin;
204b351a90bSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
205b351a90bSFande Kong   snes->checkjacdomainerror = flg;
2063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
207b351a90bSFande Kong }
208b351a90bSFande Kong 
209b351a90bSFande Kong /*@
210420bcc1bSBarry Smith   SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation.
2118383d7d7SFande Kong 
212c3339decSBarry Smith   Logically Collective
2138383d7d7SFande Kong 
2142fe279fdSBarry Smith   Input Parameter:
215f6dfbefdSBarry Smith . snes - the `SNES` context
2168383d7d7SFande Kong 
2172fe279fdSBarry Smith   Output Parameter:
218420bcc1bSBarry Smith . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation
2198383d7d7SFande Kong 
2208383d7d7SFande Kong   Level: advanced
2218383d7d7SFande Kong 
2228434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()`
2238383d7d7SFande Kong @*/
224d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg)
225d71ae5a4SJacob Faibussowitsch {
2268383d7d7SFande Kong   PetscFunctionBegin;
2278383d7d7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2284f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
2298383d7d7SFande Kong   *flg = snes->checkjacdomainerror;
2303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2318383d7d7SFande Kong }
2328383d7d7SFande Kong 
2338383d7d7SFande Kong /*@
234420bcc1bSBarry Smith   SNESGetFunctionDomainError - Gets the status of the domain error after a call to `SNESComputeFunction()`
2356a388c36SPeter Brune 
2366b1535e8SBarry Smith   Not Collective, different MPI processes may return different values
2376a388c36SPeter Brune 
2382fe279fdSBarry Smith   Input Parameter:
239f6dfbefdSBarry Smith . snes - the `SNES` context
2406a388c36SPeter Brune 
2412fe279fdSBarry Smith   Output Parameter:
242f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a domain error; `PETSC_FALSE` otherwise.
2436a388c36SPeter Brune 
244f6dfbefdSBarry Smith   Level: developer
2456a388c36SPeter Brune 
2466b1535e8SBarry Smith   Notes:
2476b1535e8SBarry Smith   The value will only be true on those MPI processes that called `SNESSetFunctionDomainError()`
2486b1535e8SBarry Smith 
2496b1535e8SBarry Smith   The value is reset to `PETSC_FALSE` when `SNESCheckFunctionNorm()` is called.
2506b1535e8SBarry Smith 
2511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`
2526a388c36SPeter Brune @*/
253d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror)
254d71ae5a4SJacob Faibussowitsch {
2556a388c36SPeter Brune   PetscFunctionBegin;
2566a388c36SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2574f572ea9SToby Isaac   PetscAssertPointer(domainerror, 2);
2586a388c36SPeter Brune   *domainerror = snes->domainerror;
2593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2606a388c36SPeter Brune }
2616a388c36SPeter Brune 
26207b62357SFande Kong /*@
263420bcc1bSBarry Smith   SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()`
26407b62357SFande Kong 
2656b1535e8SBarry Smith   Not Collective, different MPI processes may return different values
26607b62357SFande Kong 
2672fe279fdSBarry Smith   Input Parameter:
268f6dfbefdSBarry Smith . snes - the `SNES` context
26907b62357SFande Kong 
2702fe279fdSBarry Smith   Output Parameter:
271f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a Jacobian domain error; `PETSC_FALSE` otherwise.
27207b62357SFande Kong 
27307b62357SFande Kong   Level: advanced
27407b62357SFande Kong 
2756b1535e8SBarry Smith   Notes:
2766b1535e8SBarry Smith   The value will only be true on those MPI processes that called `SNESSetJacobianDomainError()`
2776b1535e8SBarry Smith 
2786b1535e8SBarry Smith   The value is reset to `PETSC_FALSE` when `SNESCheckJacobianDomainerror()` is called but only `SNESSetCheckJacobianDomainError()` was called
2796b1535e8SBarry Smith 
2801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`, `SNESGetFunctionDomainError()`
28107b62357SFande Kong @*/
282d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror)
283d71ae5a4SJacob Faibussowitsch {
28407b62357SFande Kong   PetscFunctionBegin;
28507b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2864f572ea9SToby Isaac   PetscAssertPointer(domainerror, 2);
28707b62357SFande Kong   *domainerror = snes->jacobiandomainerror;
2883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28907b62357SFande Kong }
29007b62357SFande Kong 
291ffeef943SBarry Smith /*@
292f6dfbefdSBarry Smith   SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`.
29355849f57SBarry Smith 
294c3339decSBarry Smith   Collective
29555849f57SBarry Smith 
29655849f57SBarry Smith   Input Parameters:
297e4094ef1SJacob Faibussowitsch + snes   - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or
298f6dfbefdSBarry Smith            some related function before a call to `SNESLoad()`.
299f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
30055849f57SBarry Smith 
30155849f57SBarry Smith   Level: intermediate
30255849f57SBarry Smith 
303f6dfbefdSBarry Smith   Note:
304420bcc1bSBarry Smith   The `SNESType` is determined by the data in the file, any type set into the `SNES` before this call is ignored.
30555849f57SBarry Smith 
3061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()`
30755849f57SBarry Smith @*/
308d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer)
309d71ae5a4SJacob Faibussowitsch {
31055849f57SBarry Smith   PetscBool isbinary;
311060da220SMatthew G. Knepley   PetscInt  classid;
31255849f57SBarry Smith   char      type[256];
31355849f57SBarry Smith   KSP       ksp;
3142d53ad75SBarry Smith   DM        dm;
3152d53ad75SBarry Smith   DMSNES    dmsnes;
31655849f57SBarry Smith 
31755849f57SBarry Smith   PetscFunctionBegin;
3182d53ad75SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
31955849f57SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
3215f80ce2aSJacob Faibussowitsch   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");
32255849f57SBarry Smith 
3239566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
3245f80ce2aSJacob Faibussowitsch   PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file");
3259566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
3269566063dSJacob Faibussowitsch   PetscCall(SNESSetType(snes, type));
327dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, load, viewer);
3289566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3299566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &dmsnes));
3309566063dSJacob Faibussowitsch   PetscCall(DMSNESLoad(dmsnes, viewer));
3319566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
3329566063dSJacob Faibussowitsch   PetscCall(KSPLoad(ksp, viewer));
3333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33455849f57SBarry Smith }
3356a388c36SPeter Brune 
3369804daf3SBarry Smith #include <petscdraw.h>
337e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
338e04113cfSBarry Smith   #include <petscviewersaws.h>
339bfb97211SBarry Smith #endif
3408404b7f3SBarry Smith 
341ffeef943SBarry Smith /*@
342dc4c0fb0SBarry Smith   SNESViewFromOptions - View a `SNES` based on values in the options database
343fe2efc57SMark 
344c3339decSBarry Smith   Collective
345fe2efc57SMark 
346fe2efc57SMark   Input Parameters:
347f6dfbefdSBarry Smith + A    - the `SNES` context
348dc4c0fb0SBarry Smith . obj  - Optional object that provides the options prefix for the checks
349736c3998SJose E. Roman - name - command line option
350fe2efc57SMark 
351fe2efc57SMark   Level: intermediate
352f6dfbefdSBarry Smith 
3531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()`
354fe2efc57SMark @*/
355d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[])
356d71ae5a4SJacob Faibussowitsch {
357fe2efc57SMark   PetscFunctionBegin;
358fe2efc57SMark   PetscValidHeaderSpecific(A, SNES_CLASSID, 1);
3599566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
3603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
361fe2efc57SMark }
362fe2efc57SMark 
363789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *);
364789d8953SBarry Smith 
365ffeef943SBarry Smith /*@
366dc4c0fb0SBarry Smith   SNESView - Prints or visualizes the `SNES` data structure.
3679b94acceSBarry Smith 
368c3339decSBarry Smith   Collective
369fee21e36SBarry Smith 
370c7afd0dbSLois Curfman McInnes   Input Parameters:
371f6dfbefdSBarry Smith + snes   - the `SNES` context
372f6dfbefdSBarry Smith - viewer - the `PetscViewer`
373c7afd0dbSLois Curfman McInnes 
3749b94acceSBarry Smith   Options Database Key:
375f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()`
3769b94acceSBarry Smith 
377dc4c0fb0SBarry Smith   Level: beginner
378dc4c0fb0SBarry Smith 
3799b94acceSBarry Smith   Notes:
3809b94acceSBarry Smith   The available visualization contexts include
381f6dfbefdSBarry Smith +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
382f6dfbefdSBarry Smith -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
383c8a8ba5cSLois Curfman McInnes   output where only the first processor opens
384c8a8ba5cSLois Curfman McInnes   the file.  All other processors send their
385c8a8ba5cSLois Curfman McInnes   data to the first processor to print.
3869b94acceSBarry Smith 
387052bf0daSPierre Jolivet   The available formats include
388f6dfbefdSBarry Smith +     `PETSC_VIEWER_DEFAULT` - standard output (default)
389f6dfbefdSBarry Smith -     `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM`
390052bf0daSPierre Jolivet 
3913e081fefSLois Curfman McInnes   The user can open an alternative visualization context with
392f6dfbefdSBarry Smith   `PetscViewerASCIIOpen()` - output to a specified file.
3939b94acceSBarry Smith 
394f6dfbefdSBarry Smith   In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer).
395595c91d4SBarry Smith 
3961cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()`
3979b94acceSBarry Smith @*/
398d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer)
399d71ae5a4SJacob Faibussowitsch {
400fa9f3622SBarry Smith   SNESKSPEW     *kctx;
40194b7f48cSBarry Smith   KSP            ksp;
4027f1410a3SPeter Brune   SNESLineSearch linesearch;
4039f196a02SMartin Diehl   PetscBool      isascii, isstring, isbinary, isdraw;
4042d53ad75SBarry Smith   DMSNES         dmsnes;
405e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
406536b137fSBarry Smith   PetscBool issaws;
407bfb97211SBarry Smith #endif
4089b94acceSBarry Smith 
4093a40ed3dSBarry Smith   PetscFunctionBegin;
4100700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
41148a46eb9SPierre Jolivet   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer));
4120700a824SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
413c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, viewer, 2);
41474679c65SBarry Smith 
4159f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
4169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
4179566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
4189566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
419e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
4209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
421bfb97211SBarry Smith #endif
4229f196a02SMartin Diehl   if (isascii) {
423dc0571f2SMatthew G. Knepley     SNESNormSchedule normschedule;
4248404b7f3SBarry Smith     DM               dm;
4258434afd1SBarry Smith     SNESJacobianFn  *cJ;
4268404b7f3SBarry Smith     void            *ctx;
427789d8953SBarry Smith     const char      *pre = "";
428dc0571f2SMatthew G. Knepley 
4299566063dSJacob Faibussowitsch     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer));
43048a46eb9SPierre Jolivet     if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  SNES has not been set up so information may be incomplete\n"));
431e7788613SBarry Smith     if (snes->ops->view) {
4329566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
433dbbe0bcdSBarry Smith       PetscUseTypeMethod(snes, view, viewer);
4349566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
4350ef38995SBarry Smith     }
43677e5a1f9SBarry Smith     if (snes->max_funcs == PETSC_UNLIMITED) {
43777e5a1f9SBarry Smith       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=unlimited\n", snes->max_its));
43877e5a1f9SBarry Smith     } else {
43963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs));
44077e5a1f9SBarry Smith     }
4419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol));
44248a46eb9SPierre Jolivet     if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its));
44363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs));
4449566063dSJacob Faibussowitsch     PetscCall(SNESGetNormSchedule(snes, &normschedule));
4459566063dSJacob Faibussowitsch     if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "  norm schedule %s\n", SNESNormSchedules[normschedule]));
44648a46eb9SPierre Jolivet     if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence));
4479b94acceSBarry Smith     if (snes->ksp_ewconv) {
448fa9f3622SBarry Smith       kctx = (SNESKSPEW *)snes->kspconvctx;
4499b94acceSBarry Smith       if (kctx) {
45063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version));
4519566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold));
4529566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2));
4539b94acceSBarry Smith       }
4549b94acceSBarry Smith     }
455eb1f6c34SBarry Smith     if (snes->lagpreconditioner == -1) {
4569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is never rebuilt\n"));
457eb1f6c34SBarry Smith     } else if (snes->lagpreconditioner > 1) {
45863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner));
459eb1f6c34SBarry Smith     }
460eb1f6c34SBarry Smith     if (snes->lagjacobian == -1) {
4619566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is never rebuilt\n"));
462eb1f6c34SBarry Smith     } else if (snes->lagjacobian > 1) {
46363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian));
464eb1f6c34SBarry Smith     }
4659566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4669566063dSJacob Faibussowitsch     PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx));
467789d8953SBarry Smith     if (snes->mf_operator) {
4689566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing\n"));
469789d8953SBarry Smith       pre = "Preconditioning ";
470789d8953SBarry Smith     }
4718404b7f3SBarry Smith     if (cJ == SNESComputeJacobianDefault) {
4729566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences one column at a time\n", pre));
4738404b7f3SBarry Smith     } else if (cJ == SNESComputeJacobianDefaultColor) {
4749566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences with coloring\n", pre));
475789d8953SBarry Smith       /* it slightly breaks data encapsulation for access the DMDA information directly */
476789d8953SBarry Smith     } else if (cJ == SNESComputeJacobian_DMDA) {
477789d8953SBarry Smith       MatFDColoring fdcoloring;
4789566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring));
479789d8953SBarry Smith       if (fdcoloring) {
4809566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using colored finite differences on a DMDA\n", pre));
481789d8953SBarry Smith       } else {
4829566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using a DMDA local Jacobian\n", pre));
483789d8953SBarry Smith       }
484996e1cbcSBarry Smith     } else if (snes->mf && !snes->mf_operator) {
4859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing, no explicit Jacobian\n"));
4868404b7f3SBarry Smith     }
4870f5bd95cSBarry Smith   } else if (isstring) {
488317d6ea6SBarry Smith     const char *type;
4899566063dSJacob Faibussowitsch     PetscCall(SNESGetType(snes, &type));
4909566063dSJacob Faibussowitsch     PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type));
491dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
49255849f57SBarry Smith   } else if (isbinary) {
49355849f57SBarry Smith     PetscInt    classid = SNES_FILE_CLASSID;
49455849f57SBarry Smith     MPI_Comm    comm;
49555849f57SBarry Smith     PetscMPIInt rank;
49655849f57SBarry Smith     char        type[256];
49755849f57SBarry Smith 
4989566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
4999566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
500dd400576SPatrick Sanan     if (rank == 0) {
5019566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
5029566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type)));
5039566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR));
50455849f57SBarry Smith     }
505dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
50672a02f06SBarry Smith   } else if (isdraw) {
50772a02f06SBarry Smith     PetscDraw draw;
50872a02f06SBarry Smith     char      str[36];
50989fd9fafSBarry Smith     PetscReal x, y, bottom, h;
51072a02f06SBarry Smith 
5119566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5129566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
5139566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str)));
5149566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str)));
5159566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h));
51689fd9fafSBarry Smith     bottom = y - h;
5179566063dSJacob Faibussowitsch     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
518dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
519e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
520536b137fSBarry Smith   } else if (issaws) {
521d45a07a7SBarry Smith     PetscMPIInt rank;
5222657e9d9SBarry Smith     const char *name;
523d45a07a7SBarry Smith 
5249566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)snes, &name));
5259566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
526dd400576SPatrick Sanan     if (!((PetscObject)snes)->amsmem && rank == 0) {
527d45a07a7SBarry Smith       char dir[1024];
528d45a07a7SBarry Smith 
5299566063dSJacob Faibussowitsch       PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer));
5309566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name));
531792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT));
53248a46eb9SPierre Jolivet       if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE));
5339566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name));
534792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE));
535f05ece33SBarry Smith     }
536bfb97211SBarry Smith #endif
53772a02f06SBarry Smith   }
53872a02f06SBarry Smith   if (snes->linesearch) {
5399566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &linesearch));
5409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5419566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchView(linesearch, viewer));
5429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
54319bcc07fSBarry Smith   }
544efd4aadfSBarry Smith   if (snes->npc && snes->usesnpc) {
5459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5469566063dSJacob Faibussowitsch     PetscCall(SNESView(snes->npc, viewer));
5479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5484a0c5b0cSMatthew G Knepley   }
5499566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
5509566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(snes->dm, &dmsnes));
5519566063dSJacob Faibussowitsch   PetscCall(DMSNESView(dmsnes, viewer));
5529566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
5532c155ee1SBarry Smith   if (snes->usesksp) {
5549566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
5559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5569566063dSJacob Faibussowitsch     PetscCall(KSPView(ksp, viewer));
5579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5582c155ee1SBarry Smith   }
55972a02f06SBarry Smith   if (isdraw) {
56072a02f06SBarry Smith     PetscDraw draw;
5619566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5629566063dSJacob Faibussowitsch     PetscCall(PetscDrawPopCurrentPoint(draw));
5637f1410a3SPeter Brune   }
5643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5659b94acceSBarry Smith }
5669b94acceSBarry Smith 
56776b2cf59SMatthew Knepley /*
56876b2cf59SMatthew Knepley   We retain a list of functions that also take SNES command
56976b2cf59SMatthew Knepley   line options. These are called at the end SNESSetFromOptions()
57076b2cf59SMatthew Knepley */
57176b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5
572a7cc72afSBarry Smith static PetscInt numberofsetfromoptions;
5736849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
57476b2cf59SMatthew Knepley 
575ac226902SBarry Smith /*@C
576f6dfbefdSBarry Smith   SNESAddOptionsChecker - Adds an additional function to check for `SNES` options.
57776b2cf59SMatthew Knepley 
57876b2cf59SMatthew Knepley   Not Collective
57976b2cf59SMatthew Knepley 
58076b2cf59SMatthew Knepley   Input Parameter:
58176b2cf59SMatthew Knepley . snescheck - function that checks for options
58276b2cf59SMatthew Knepley 
583420bcc1bSBarry Smith   Calling sequence of `snescheck`:
584420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options
585420bcc1bSBarry Smith 
58676b2cf59SMatthew Knepley   Level: developer
58776b2cf59SMatthew Knepley 
5881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`
58976b2cf59SMatthew Knepley @*/
590420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes))
591d71ae5a4SJacob Faibussowitsch {
59276b2cf59SMatthew Knepley   PetscFunctionBegin;
59363a3b9bcSJacob Faibussowitsch   PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS);
59476b2cf59SMatthew Knepley   othersetfromoptions[numberofsetfromoptions++] = snescheck;
5953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59676b2cf59SMatthew Knepley }
59776b2cf59SMatthew Knepley 
598d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
599d71ae5a4SJacob Faibussowitsch {
600aa3661deSLisandro Dalcin   Mat          J;
601895c21f2SBarry Smith   MatNullSpace nullsp;
602aa3661deSLisandro Dalcin 
603aa3661deSLisandro Dalcin   PetscFunctionBegin;
6040700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
605aa3661deSLisandro Dalcin 
60698613b67SLisandro Dalcin   if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
60798613b67SLisandro Dalcin     Mat A = snes->jacobian, B = snes->jacobian_pre;
6089566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func));
60998613b67SLisandro Dalcin   }
61098613b67SLisandro Dalcin 
6110fdf79fbSJacob Faibussowitsch   PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
612aa3661deSLisandro Dalcin   if (version == 1) {
6139566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
6149566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
6159566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
6161e2ae407SBarry Smith     /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
6170fdf79fbSJacob Faibussowitsch   } else /* if (version == 2) */ {
6185f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first");
619570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
620f6dfbefdSBarry Smith     PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J));
621aa3661deSLisandro Dalcin #else
6222479783cSJose E. Roman     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
623aa3661deSLisandro Dalcin #endif
6240fdf79fbSJacob Faibussowitsch   }
625aa3661deSLisandro Dalcin 
62601c1178eSBarry Smith   /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */
627895c21f2SBarry Smith   if (snes->jacobian) {
6289566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(snes->jacobian, &nullsp));
6291baa6e33SBarry Smith     if (nullsp) PetscCall(MatSetNullSpace(J, nullsp));
630895c21f2SBarry Smith   }
631895c21f2SBarry Smith 
63263a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version));
633d3462f78SMatthew Knepley   if (hasOperator) {
634aa3661deSLisandro Dalcin     /* This version replaces the user provided Jacobian matrix with a
6357addb90fSBarry Smith        matrix-free version but still employs the user-provided matrix used for computing the preconditioner. */
6369566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
637aa3661deSLisandro Dalcin   } else {
638aa3661deSLisandro Dalcin     /* This version replaces both the user-provided Jacobian and the user-
63901c1178eSBarry Smith      provided preconditioner Jacobian with the default matrix-free version. */
640b552625fSStefano Zampini     if (snes->npcside == PC_LEFT && snes->npc) {
6419566063dSJacob Faibussowitsch       if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
642172a4300SPeter Brune     } else {
643789d8953SBarry Smith       KSP       ksp;
644789d8953SBarry Smith       PC        pc;
645789d8953SBarry Smith       PetscBool match;
646789d8953SBarry Smith 
6479566063dSJacob Faibussowitsch       PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL));
648aa3661deSLisandro Dalcin       /* Force no preconditioner */
6499566063dSJacob Faibussowitsch       PetscCall(SNESGetKSP(snes, &ksp));
6509566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksp, &pc));
6512698c518SLisandro Dalcin       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, ""));
652aa3661deSLisandro Dalcin       if (!match) {
6539566063dSJacob Faibussowitsch         PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n"));
6549566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc, PCNONE));
655aa3661deSLisandro Dalcin       }
656aa3661deSLisandro Dalcin     }
657789d8953SBarry Smith   }
6589566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&J));
6593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
660aa3661deSLisandro Dalcin }
661aa3661deSLisandro Dalcin 
662d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx)
663d71ae5a4SJacob Faibussowitsch {
664dfe15315SJed Brown   SNES snes = (SNES)ctx;
6650298fd71SBarry Smith   Vec  Xfine, Xfine_named = NULL, Xcoarse;
666dfe15315SJed Brown 
667dfe15315SJed Brown   PetscFunctionBegin;
66816ebb321SJed Brown   if (PetscLogPrintInfo) {
66916ebb321SJed Brown     PetscInt finelevel, coarselevel, fineclevel, coarseclevel;
6709566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmfine, &finelevel));
6719566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel));
6729566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel));
6739566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel));
67463a3b9bcSJacob 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));
67516ebb321SJed Brown   }
676dfe15315SJed Brown   if (dmfine == snes->dm) Xfine = snes->vec_sol;
677dfe15315SJed Brown   else {
6789566063dSJacob Faibussowitsch     PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
679dfe15315SJed Brown     Xfine = Xfine_named;
680dfe15315SJed Brown   }
6819566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
682907f5c5aSLawrence Mitchell   if (Inject) {
6839566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Inject, Xfine, Xcoarse));
684907f5c5aSLawrence Mitchell   } else {
6859566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Restrict, Xfine, Xcoarse));
6869566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale));
687907f5c5aSLawrence Mitchell   }
6889566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
6899566063dSJacob Faibussowitsch   if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
6903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
691dfe15315SJed Brown }
692dfe15315SJed Brown 
693d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx)
694d71ae5a4SJacob Faibussowitsch {
69516ebb321SJed Brown   PetscFunctionBegin;
6969566063dSJacob Faibussowitsch   PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx));
6973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
69816ebb321SJed Brown }
69916ebb321SJed Brown 
700a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
701a6950cb2SJed Brown  * safely call SNESGetDM() in their residual evaluation routine. */
702d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx)
703d71ae5a4SJacob Faibussowitsch {
704caa4e7f2SJed Brown   SNES            snes = (SNES)ctx;
70597d931d1SStefano Zampini   DMSNES          sdm;
7060298fd71SBarry Smith   Vec             X, Xnamed = NULL;
707dfe15315SJed Brown   DM              dmsave;
7084e269d77SPeter Brune   void           *ctxsave;
7098434afd1SBarry Smith   SNESJacobianFn *jac = NULL;
710caa4e7f2SJed Brown 
711caa4e7f2SJed Brown   PetscFunctionBegin;
712dfe15315SJed Brown   dmsave = snes->dm;
7139566063dSJacob Faibussowitsch   PetscCall(KSPGetDM(ksp, &snes->dm));
714dfe15315SJed Brown   if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
71597d931d1SStefano Zampini   else {
716309d62e6SStefano Zampini     PetscBool has;
717309d62e6SStefano Zampini 
71897d931d1SStefano Zampini     /* We are on a coarser level, this vec was initialized using a DM restrict hook */
719309d62e6SStefano Zampini     PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has));
720309d62e6SStefano Zampini     PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol");
72197d931d1SStefano Zampini     PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
722dfe15315SJed Brown     X = Xnamed;
7239566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave));
7244e269d77SPeter Brune     /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
72548a46eb9SPierre Jolivet     if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL));
7264e269d77SPeter Brune   }
7274e269d77SPeter Brune 
7282b93b426SMatthew G. Knepley   /* Compute the operators */
72997d931d1SStefano Zampini   PetscCall(DMGetDMSNES(snes->dm, &sdm));
73097d931d1SStefano Zampini   if (Xnamed && sdm->ops->computefunction) {
73197d931d1SStefano Zampini     /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian.
73297d931d1SStefano Zampini        We make sure of this here. Disable affine shift since it is for the finest level */
73397d931d1SStefano Zampini     Vec F, saverhs = snes->vec_rhs;
73497d931d1SStefano Zampini 
73597d931d1SStefano Zampini     snes->vec_rhs = NULL;
73697d931d1SStefano Zampini     PetscCall(DMGetGlobalVector(snes->dm, &F));
73797d931d1SStefano Zampini     PetscCall(SNESComputeFunction(snes, X, F));
73897d931d1SStefano Zampini     PetscCall(DMRestoreGlobalVector(snes->dm, &F));
73997d931d1SStefano Zampini     snes->vec_rhs = saverhs;
74097d931d1SStefano Zampini     snes->nfuncs--; /* Do not log coarser level evaluations */
74197d931d1SStefano Zampini   }
74297d931d1SStefano Zampini   /* Make sure KSP DM has the Jacobian computation routine */
74397d931d1SStefano Zampini   if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm));
7449566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, X, A, B));
74597d931d1SStefano Zampini 
7462b93b426SMatthew G. Knepley   /* Put the previous context back */
74748a46eb9SPierre Jolivet   if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave));
7484e269d77SPeter Brune 
7499566063dSJacob Faibussowitsch   if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
750dfe15315SJed Brown   snes->dm = dmsave;
7513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
752caa4e7f2SJed Brown }
753caa4e7f2SJed Brown 
7546cab3a1bSJed Brown /*@
755dc4c0fb0SBarry Smith   SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()`
7566cab3a1bSJed Brown 
7576cab3a1bSJed Brown   Collective
7586cab3a1bSJed Brown 
7594165533cSJose E. Roman   Input Parameter:
76020f4b53cSBarry Smith . snes - `SNES` object to configure
7616cab3a1bSJed Brown 
7626cab3a1bSJed Brown   Level: developer
7636cab3a1bSJed Brown 
764dc4c0fb0SBarry Smith   Note:
765dc4c0fb0SBarry 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`
766dc4c0fb0SBarry Smith 
76773a84a35SBarry Smith   Developer Note:
76873a84a35SBarry Smith   The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by
76973a84a35SBarry Smith   `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the
77073a84a35SBarry Smith   logic that handles the matrix-free case is desirable.
77173a84a35SBarry Smith 
7721cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()`
7736cab3a1bSJed Brown @*/
774d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
775d71ae5a4SJacob Faibussowitsch {
7766cab3a1bSJed Brown   DM     dm;
777942e3340SBarry Smith   DMSNES sdm;
7786cab3a1bSJed Brown 
7796cab3a1bSJed Brown   PetscFunctionBegin;
7809566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
7819566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
78273a84a35SBarry Smith   if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) {
7836cab3a1bSJed Brown     Mat   J;
7846cab3a1bSJed Brown     void *functx;
7859566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7869566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7879566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7889566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7899566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7909566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
791caa4e7f2SJed Brown   } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7926cab3a1bSJed Brown     Mat J, B;
7939566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7949566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7959566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7969566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
79706f20277SJed Brown     /* sdm->computejacobian was already set to reach here */
7989566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
7999566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
8009566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
801caa4e7f2SJed Brown   } else if (!snes->jacobian_pre) {
8021ba9b98eSMatthew G. Knepley     PetscDS   prob;
8036cab3a1bSJed Brown     Mat       J, B;
8041ba9b98eSMatthew G. Knepley     PetscBool hasPrec = PETSC_FALSE;
8051ba9b98eSMatthew G. Knepley 
8066cab3a1bSJed Brown     J = snes->jacobian;
8079566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
8089566063dSJacob Faibussowitsch     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
8099566063dSJacob Faibussowitsch     if (J) PetscCall(PetscObjectReference((PetscObject)J));
8109566063dSJacob Faibussowitsch     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
8119566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
8129566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
8139566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
8149566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
8156cab3a1bSJed Brown   }
816caa4e7f2SJed Brown   {
817caa4e7f2SJed Brown     KSP ksp;
8189566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
8199566063dSJacob Faibussowitsch     PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
8209566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
821caa4e7f2SJed Brown   }
8223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8236cab3a1bSJed Brown }
8246cab3a1bSJed Brown 
825d6acfc2dSPierre Jolivet PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscMonitorPauseFinal_Internal(PetscInt, void *);
826ce78bad3SBarry Smith 
827d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
828d71ae5a4SJacob Faibussowitsch {
8295e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
8303ba16761SJacob Faibussowitsch   if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
831ce78bad3SBarry Smith   PetscCall(PetscMonitorPauseFinal_Internal(snes->numbermonitors, snes->monitorcontext));
8323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8335e7c47f3SMatthew G. Knepley }
8345e7c47f3SMatthew G. Knepley 
835fde5950dSBarry Smith /*@C
836fde5950dSBarry Smith   SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
837fde5950dSBarry Smith 
838c3339decSBarry Smith   Collective
839fde5950dSBarry Smith 
840fde5950dSBarry Smith   Input Parameters:
841dc4c0fb0SBarry Smith + snes         - `SNES` object you wish to monitor
842fde5950dSBarry Smith . name         - the monitor type one is seeking
843fde5950dSBarry Smith . help         - message indicating what monitoring is done
844fde5950dSBarry Smith . manual       - manual page for the monitor
84549abdd8aSBarry Smith . monitor      - the monitor function, this must use a `PetscViewerFormat` as its context
846f6dfbefdSBarry 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
847fde5950dSBarry Smith 
848420bcc1bSBarry Smith   Calling sequence of `monitor`:
849420bcc1bSBarry Smith + snes - the nonlinear solver context
850420bcc1bSBarry Smith . it   - the current iteration
851420bcc1bSBarry Smith . r    - the current function norm
852420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
853420bcc1bSBarry Smith 
854420bcc1bSBarry Smith   Calling sequence of `monitorsetup`:
855420bcc1bSBarry Smith + snes - the nonlinear solver context
856420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
857420bcc1bSBarry Smith 
858f6dfbefdSBarry Smith   Options Database Key:
859f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()`
860f6dfbefdSBarry Smith 
861f6dfbefdSBarry Smith   Level: advanced
862fde5950dSBarry Smith 
863648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
864db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
865e4094ef1SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
866db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
867c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
868db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
869db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
870fde5950dSBarry Smith @*/
871420bcc1bSBarry 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))
872d71ae5a4SJacob Faibussowitsch {
873fde5950dSBarry Smith   PetscViewer       viewer;
874fde5950dSBarry Smith   PetscViewerFormat format;
875fde5950dSBarry Smith   PetscBool         flg;
876fde5950dSBarry Smith 
877fde5950dSBarry Smith   PetscFunctionBegin;
878648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
879fde5950dSBarry Smith   if (flg) {
880d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8819566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
882648c30bcSBarry Smith     PetscCall(PetscViewerDestroy(&viewer));
8831baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
88449abdd8aSBarry Smith     PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
885fde5950dSBarry Smith   }
8863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
887fde5950dSBarry Smith }
888fde5950dSBarry Smith 
889a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
890d71ae5a4SJacob Faibussowitsch {
891a4598233SStefano Zampini   const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
892a4598233SStefano Zampini 
8930f0abf79SStefano Zampini   PetscFunctionBegin;
8940f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
895a4598233SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
896a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
897a4598233SStefano Zampini   kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
898a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
899a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
900a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
9010f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
902a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
9030f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
9040f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
9050f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
9060f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
9070f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
9080f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
9090f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
9100f0abf79SStefano Zampini   PetscOptionsEnd();
9113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9120f0abf79SStefano Zampini }
9130f0abf79SStefano Zampini 
9149b94acceSBarry Smith /*@
915f6dfbefdSBarry Smith   SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
9169b94acceSBarry Smith 
917c3339decSBarry Smith   Collective
918c7afd0dbSLois Curfman McInnes 
9199b94acceSBarry Smith   Input Parameter:
920f6dfbefdSBarry Smith . snes - the `SNES` context
9219b94acceSBarry Smith 
92236851e7fSLois Curfman McInnes   Options Database Keys:
923f6dfbefdSBarry Smith + -snes_type <type>                                                            - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
924b39c3a46SLois Curfman McInnes . -snes_rtol <rtol>                                                            - relative decrease in tolerance norm from initial
92577e5a1f9SBarry Smith . -snes_atol <abstol>                                                          - absolute tolerance of residual norm
92677e5a1f9SBarry Smith . -snes_stol <stol>                                                            - convergence tolerance in terms of the norm of the change in the solution between steps
927e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol>                                          - if the residual goes above divtol*rnorm0, exit with divergence
928b39c3a46SLois Curfman McInnes . -snes_max_it <max_it>                                                        - maximum number of iterations
929b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs>                                                  - maximum number of function evaluations
93077e5a1f9SBarry Smith . -snes_force_iteration <force>                                                - force `SNESSolve()` to take at least one iteration
9314839bfe8SBarry Smith . -snes_max_fail <max_fail>                                                    - maximum number of line search failures allowed before stopping, default is none
932ddf469c8SBarry Smith . -snes_max_linear_solve_fail                                                  - number of linear solver failures before SNESSolve() stops
933a8054027SBarry Smith . -snes_lag_preconditioner <lag>                                               - how often preconditioner is rebuilt (use -1 to never rebuild)
9343d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false>                               - retains the -snes_lag_preconditioner information across multiple SNESSolve()
935e35cf81dSBarry Smith . -snes_lag_jacobian <lag>                                                     - how often Jacobian is rebuilt (use -1 to never rebuild)
9363d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false>                                     - retains the -snes_lag_jacobian information across multiple SNESSolve()
937ceaaa498SBarry 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.
938fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format]                             - prints residual norm at each iteration. if no filename given prints to stdout
939fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format]        - plots solution at each iteration
940fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format]        - plots residual (not its norm) at each iteration
941fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9424619e776SBarry Smith . -snes_monitor_lg_residualnorm                                                - plots residual norm at each iteration
943459f5d12SBarry Smith . -snes_monitor_lg_range                                                       - plots residual norm at each iteration
9445e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final                                                    - Pauses all monitor drawing after the solver ends
945e24b481bSBarry Smith . -snes_fd                                                                     - use finite differences to compute Jacobian; very slow, only for testing
946e2e60de9SPeter Brune . -snes_fd_color                                                               - use finite differences with coloring to compute Jacobian
947ceaaa498SBarry Smith . -snes_mf_ksp_monitor                                                         - if using matrix-free multiply then print h at each `KSP` iteration
948b5badacbSBarry Smith . -snes_converged_reason                                                       - print the reason for convergence/divergence after each solve
949ceaaa498SBarry Smith . -npc_snes_type <type>                                                        - the `SNES` type to use as a nonlinear preconditioner
950e62ac41dSBarry 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.
951e62ac41dSBarry 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.
95282738288SBarry Smith 
953f6dfbefdSBarry Smith   Options Database Keys for Eisenstat-Walker method:
954fa9f3622SBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
9554b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
95636851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
95736851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
95836851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma>         - Sets gamma
95936851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha>         - Sets alpha
96036851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
96136851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
96282738288SBarry Smith 
963dc4c0fb0SBarry Smith   Level: beginner
964dc4c0fb0SBarry Smith 
96511ca99fdSLois Curfman McInnes   Notes:
966ec5066bdSBarry Smith   To see all options, run your program with the -help option or consult the users manual
967ec5066bdSBarry Smith 
968420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
969420bcc1bSBarry Smith   and computing explicitly with
970f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
97183e2fdc7SBarry Smith 
972420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring`
9739b94acceSBarry Smith @*/
974d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
975d71ae5a4SJacob Faibussowitsch {
9768afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
97777e5a1f9SBarry Smith   PetscInt    i, indx, lag, grids, max_its, max_funcs;
97804d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
979649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
98085385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9810f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
982c40d0f55SPeter Brune   PCSide      pcside;
983a64e098fSPeter Brune   const char *optionsprefix;
98477e5a1f9SBarry Smith   PetscReal   rtol, abstol, stol;
9859b94acceSBarry Smith 
9863a40ed3dSBarry Smith   PetscFunctionBegin;
9870700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9889566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
989d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
990639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
992d64ed03dSBarry Smith   if (flg) {
9939566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
9947adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
9959566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
996d64ed03dSBarry Smith   }
997186905e3SBarry Smith 
99877e5a1f9SBarry Smith   abstol    = snes->abstol;
99977e5a1f9SBarry Smith   rtol      = snes->rtol;
100077e5a1f9SBarry Smith   stol      = snes->stol;
100177e5a1f9SBarry Smith   max_its   = snes->max_its;
100277e5a1f9SBarry Smith   max_funcs = snes->max_funcs;
100377e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL));
100477e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL));
100577e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL));
100677e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL));
100777e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL));
100877e5a1f9SBarry Smith   PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs));
100977e5a1f9SBarry Smith 
101077e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg));
101177e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol));
101277e5a1f9SBarry Smith 
101377e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg));
101477e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures));
101577e5a1f9SBarry Smith 
101677e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg));
101777e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures));
101877e5a1f9SBarry Smith 
10199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
10209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
10219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
102285385478SLisandro Dalcin 
10239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
1024a8054027SBarry Smith   if (flg) {
10255f80ce2aSJacob 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");
10269566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
1027a8054027SBarry Smith   }
10289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
10291baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
10309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
1031e35cf81dSBarry Smith   if (flg) {
10325f80ce2aSJacob 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");
10339566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
1034e35cf81dSBarry Smith   }
10359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
10361baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
103737ec4e1aSPeter Brune 
10389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
10391baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
1040a8054027SBarry Smith 
1041400f6f02SBarry Smith   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg));
104285385478SLisandro Dalcin   if (flg) {
104385385478SLisandro Dalcin     switch (indx) {
1044d71ae5a4SJacob Faibussowitsch     case 0:
1045d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1046d71ae5a4SJacob Faibussowitsch       break;
1047d71ae5a4SJacob Faibussowitsch     case 1:
1048d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1049d71ae5a4SJacob Faibussowitsch       break;
1050d71ae5a4SJacob Faibussowitsch     case 2:
1051d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1052d71ae5a4SJacob Faibussowitsch       break;
105385385478SLisandro Dalcin     }
105485385478SLisandro Dalcin   }
105585385478SLisandro Dalcin 
10569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10579566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1058fdacfa88SPeter Brune 
10599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10609566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1061186905e3SBarry Smith 
106285385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
106385385478SLisandro Dalcin 
10649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1065186905e3SBarry Smith 
10660f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10670f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1068a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1069186905e3SBarry Smith 
107090d69ab7SBarry Smith   flg = PETSC_FALSE;
10719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10729566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1073eabae89aSBarry Smith 
10749566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10759566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10769566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1077eabae89aSBarry Smith 
10789566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10799566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10809566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10819566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10829566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10839566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10849566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10862db13446SMatthew G. Knepley 
10879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10889566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10895180491cSLisandro Dalcin 
109090d69ab7SBarry Smith   flg = PETSC_FALSE;
10919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1092459f5d12SBarry Smith   if (flg) {
1093459f5d12SBarry Smith     PetscViewer ctx;
1094e24b481bSBarry Smith 
10959566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
109649abdd8aSBarry Smith     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscCtxDestroyFn *)PetscViewerDestroy));
1097459f5d12SBarry Smith   }
10982e7541e6SPeter Brune 
1099648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
1100648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL));
110190d69ab7SBarry Smith   flg = PETSC_FALSE;
11029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
11039566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1104c4421ceaSFande Kong 
1105c4421ceaSFande Kong   flg = PETSC_FALSE;
11069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
11074b27c08aSLois Curfman McInnes   if (flg) {
11086cab3a1bSJed Brown     void *functx;
1109b1f624c7SBarry Smith     DM    dm;
11109566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1111800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11129566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
11139566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
11149566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
11159b94acceSBarry Smith   }
1116639f9d9dSBarry Smith 
111744848bc4SPeter Brune   flg = PETSC_FALSE;
11189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
11191baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
112097584545SPeter Brune 
112197584545SPeter Brune   flg = PETSC_FALSE;
11229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
112344848bc4SPeter Brune   if (flg) {
1124c52e227fSPeter Brune     DM dm;
11259566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1126800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11279566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
11289566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
112944848bc4SPeter Brune   }
113044848bc4SPeter Brune 
1131aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11327addb90fSBarry 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));
1133d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1134a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1135d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1136a8248277SBarry Smith   }
1137aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11387addb90fSBarry Smith   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1139d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
11409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1141d28543b3SPeter Brune 
11421dfd7622SMatthew Knepley   PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference functions", "None", &snes->testFunc));
11431dfd7622SMatthew Knepley   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &snes->testJac));
11441dfd7622SMatthew Knepley 
1145c40d0f55SPeter Brune   flg = PETSC_FALSE;
11469566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11489566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1149c40d0f55SPeter Brune 
1150e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11518a70d858SHong Zhang   /*
11528a70d858SHong Zhang     Publish convergence information using SAWs
11538a70d858SHong Zhang   */
11548a70d858SHong Zhang   flg = PETSC_FALSE;
11559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11568a70d858SHong Zhang   if (flg) {
11578a70d858SHong Zhang     void *ctx;
11589566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11599566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11608a70d858SHong Zhang   }
11618a70d858SHong Zhang #endif
11628a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1163b90c6cbeSBarry Smith   {
1164b90c6cbeSBarry Smith     PetscBool set;
1165b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11669566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11671baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1168b90c6cbeSBarry Smith   }
1169b90c6cbeSBarry Smith #endif
1170b90c6cbeSBarry Smith 
117148a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
117276b2cf59SMatthew Knepley 
1173dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11745d973c19SBarry Smith 
11755d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1176dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1177d0609cedSBarry Smith   PetscOptionsEnd();
11784bbc92c1SBarry Smith 
1179d8d34be6SBarry Smith   if (snes->linesearch) {
11809566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11819566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1182d8d34be6SBarry Smith   }
11839e764e56SPeter Brune 
11846aa5e7e9SBarry Smith   if (snes->usesksp) {
11859566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11869566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11879566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11886aa5e7e9SBarry Smith   }
11896991f827SBarry Smith 
1190b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11919566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
119348a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11941baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1195b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1197b3cd9a81SMatthew G. Knepley }
1198b3cd9a81SMatthew G. Knepley 
1199b3cd9a81SMatthew G. Knepley /*@
1200420bcc1bSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1201b3cd9a81SMatthew G. Knepley 
1202c3339decSBarry Smith   Collective
1203b3cd9a81SMatthew G. Knepley 
1204b3cd9a81SMatthew G. Knepley   Input Parameter:
1205f6dfbefdSBarry Smith . snes - the `SNES` context
1206b3cd9a81SMatthew G. Knepley 
1207420bcc1bSBarry Smith   Level: advanced
1208b3cd9a81SMatthew G. Knepley 
12091cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1210b3cd9a81SMatthew G. Knepley @*/
1211d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1212d71ae5a4SJacob Faibussowitsch {
1213b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
12149566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
12153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12169b94acceSBarry Smith }
12179b94acceSBarry Smith 
1218bb9467b5SJed Brown /*@C
1219d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1220d25893d9SBarry Smith   the nonlinear solvers.
1221d25893d9SBarry Smith 
1222dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1223d25893d9SBarry Smith 
1224d25893d9SBarry Smith   Input Parameters:
1225f6dfbefdSBarry Smith + snes    - the `SNES` context
1226d25893d9SBarry Smith . compute - function to compute the context
122749abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence
1228d25893d9SBarry Smith 
1229420bcc1bSBarry Smith   Calling sequence of `compute`:
1230420bcc1bSBarry Smith + snes - the `SNES` context
1231420bcc1bSBarry Smith - ctx  - context to be computed
1232420bcc1bSBarry Smith 
1233d25893d9SBarry Smith   Level: intermediate
1234d25893d9SBarry Smith 
1235f6dfbefdSBarry Smith   Note:
1236f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1237f6dfbefdSBarry Smith 
1238f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1239f6dfbefdSBarry Smith 
124049abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn`
1241d25893d9SBarry Smith @*/
124249abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy)
1243d71ae5a4SJacob Faibussowitsch {
1244d25893d9SBarry Smith   PetscFunctionBegin;
1245d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1246d25893d9SBarry Smith   snes->ops->usercompute = compute;
124749abdd8aSBarry Smith   snes->ops->ctxdestroy  = destroy;
12483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1249d25893d9SBarry Smith }
1250a847f771SSatish Balay 
1251b07ff414SBarry Smith /*@
1252f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12539b94acceSBarry Smith 
1254c3339decSBarry Smith   Logically Collective
1255fee21e36SBarry Smith 
1256c7afd0dbSLois Curfman McInnes   Input Parameters:
1257f6dfbefdSBarry Smith + snes - the `SNES` context
1258ce78bad3SBarry Smith - ctx  - the user context
1259c7afd0dbSLois Curfman McInnes 
126036851e7fSLois Curfman McInnes   Level: intermediate
126136851e7fSLois Curfman McInnes 
1262f6dfbefdSBarry Smith   Notes:
1263ce78bad3SBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function
1264f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1265f6dfbefdSBarry Smith 
1266f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1267f6dfbefdSBarry Smith 
1268420bcc1bSBarry Smith   Fortran Note:
1269ce78bad3SBarry 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
1270ce78bad3SBarry Smith   function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for
1271ce78bad3SBarry Smith   an example.
1272daf670e6SBarry Smith 
12731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12749b94acceSBarry Smith @*/
127549abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx)
1276d71ae5a4SJacob Faibussowitsch {
1277b07ff414SBarry Smith   KSP ksp;
12781b2093e4SBarry Smith 
12793a40ed3dSBarry Smith   PetscFunctionBegin;
12800700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12819566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
128249abdd8aSBarry Smith   PetscCall(KSPSetApplicationContext(ksp, ctx));
128349abdd8aSBarry Smith   snes->ctx = ctx;
12843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12859b94acceSBarry Smith }
128674679c65SBarry Smith 
1287b07ff414SBarry Smith /*@
12889b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1289420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12909b94acceSBarry Smith 
1291c7afd0dbSLois Curfman McInnes   Not Collective
1292c7afd0dbSLois Curfman McInnes 
12939b94acceSBarry Smith   Input Parameter:
1294f6dfbefdSBarry Smith . snes - `SNES` context
12959b94acceSBarry Smith 
12969b94acceSBarry Smith   Output Parameter:
129749abdd8aSBarry Smith . ctx - user context
12989b94acceSBarry Smith 
129936851e7fSLois Curfman McInnes   Level: intermediate
130036851e7fSLois Curfman McInnes 
1301ce78bad3SBarry Smith   Fortran Notes:
1302ce78bad3SBarry 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
1303ce78bad3SBarry Smith   function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example,
1304ce78bad3SBarry Smith .vb
1305ce78bad3SBarry Smith   Interface SNESGetApplicationContext
1306ce78bad3SBarry Smith     Subroutine SNESGetApplicationContext(snes,ctx,ierr)
1307ce78bad3SBarry Smith   #include <petsc/finclude/petscsnes.h>
1308ce78bad3SBarry Smith       use petscsnes
1309ce78bad3SBarry Smith       SNES snes
1310ce78bad3SBarry Smith       type(tUsertype), pointer :: ctx
1311ce78bad3SBarry Smith       PetscErrorCode ierr
1312ce78bad3SBarry Smith     End Subroutine
1313ce78bad3SBarry Smith   End Interface SNESGetApplicationContext
1314ce78bad3SBarry Smith .ve
1315ce78bad3SBarry Smith 
1316bfe80ac4SPierre Jolivet   The prototype for `ctx` must be
1317ce78bad3SBarry Smith .vb
1318ce78bad3SBarry Smith   type(tUsertype), pointer :: ctx
1319ce78bad3SBarry Smith .ve
1320dc4c0fb0SBarry Smith 
1321420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
13229b94acceSBarry Smith @*/
1323ce78bad3SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PeCtx ctx)
1324d71ae5a4SJacob Faibussowitsch {
13253a40ed3dSBarry Smith   PetscFunctionBegin;
13260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
132749abdd8aSBarry Smith   *(void **)ctx = snes->ctx;
13283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13299b94acceSBarry Smith }
133074679c65SBarry Smith 
13319b94acceSBarry Smith /*@
1332420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
13333565c898SBarry Smith 
1334dc4c0fb0SBarry Smith   Logically Collective
13353565c898SBarry Smith 
13363565c898SBarry Smith   Input Parameters:
1337f6dfbefdSBarry Smith + snes        - `SNES` context
1338f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1339f6dfbefdSBarry 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
1340420bcc1bSBarry Smith                 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
13413565c898SBarry Smith 
1342f6dfbefdSBarry Smith   Options Database Keys:
134301c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1344f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1345ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1346ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
13473565c898SBarry Smith 
13483565c898SBarry Smith   Level: intermediate
13493565c898SBarry Smith 
1350f6dfbefdSBarry Smith   Note:
1351420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1352420bcc1bSBarry Smith   and computing explicitly with
1353f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1354ec5066bdSBarry Smith 
1355420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13563565c898SBarry Smith @*/
1357d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1358d71ae5a4SJacob Faibussowitsch {
13593565c898SBarry Smith   PetscFunctionBegin;
13603565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
136188b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
136288b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13634ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13643565c898SBarry Smith   snes->mf_operator = mf_operator;
13653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13663565c898SBarry Smith }
13673565c898SBarry Smith 
13683565c898SBarry Smith /*@
1369dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13703565c898SBarry Smith 
1371420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13723565c898SBarry Smith 
13733565c898SBarry Smith   Input Parameter:
1374f6dfbefdSBarry Smith . snes - `SNES` context
13753565c898SBarry Smith 
13763565c898SBarry Smith   Output Parameters:
1377f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1378f6dfbefdSBarry 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
13793565c898SBarry Smith 
13803565c898SBarry Smith   Level: intermediate
13813565c898SBarry Smith 
13821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13833565c898SBarry Smith @*/
1384d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1385d71ae5a4SJacob Faibussowitsch {
13863565c898SBarry Smith   PetscFunctionBegin;
13873565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13883565c898SBarry Smith   if (mf) *mf = snes->mf;
13893565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13913565c898SBarry Smith }
13923565c898SBarry Smith 
13933565c898SBarry Smith /*@
1394420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13959b94acceSBarry Smith 
1396c7afd0dbSLois Curfman McInnes   Not Collective
1397c7afd0dbSLois Curfman McInnes 
13989b94acceSBarry Smith   Input Parameter:
1399f6dfbefdSBarry Smith . snes - `SNES` context
14009b94acceSBarry Smith 
14019b94acceSBarry Smith   Output Parameter:
14029b94acceSBarry Smith . iter - iteration number
14039b94acceSBarry Smith 
1404dc4c0fb0SBarry Smith   Level: intermediate
1405dc4c0fb0SBarry Smith 
1406c8228a4eSBarry Smith   Notes:
1407c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1408c8228a4eSBarry Smith 
1409c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1410f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
141108405cd6SLois Curfman McInnes .vb
141208405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
141308405cd6SLois Curfman McInnes       if (!(it % 2)) {
141408405cd6SLois Curfman McInnes         [compute Jacobian here]
141508405cd6SLois Curfman McInnes       }
141608405cd6SLois Curfman McInnes .ve
1417f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1418f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1419c8228a4eSBarry Smith 
1420f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1421c04deec6SBarry Smith 
1422420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
14239b94acceSBarry Smith @*/
1424d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1425d71ae5a4SJacob Faibussowitsch {
14263a40ed3dSBarry Smith   PetscFunctionBegin;
14270700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14284f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
14299b94acceSBarry Smith   *iter = snes->iter;
14303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14319b94acceSBarry Smith }
143274679c65SBarry Smith 
1433360c497dSPeter Brune /*@
1434360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1435360c497dSPeter Brune 
1436360c497dSPeter Brune   Not Collective
1437360c497dSPeter Brune 
1438d8d19677SJose E. Roman   Input Parameters:
1439f6dfbefdSBarry Smith + snes - `SNES` context
1440a2b725a8SWilliam Gropp - iter - iteration number
1441360c497dSPeter Brune 
1442360c497dSPeter Brune   Level: developer
1443360c497dSPeter Brune 
1444420bcc1bSBarry Smith   Note:
1445420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1446420bcc1bSBarry Smith 
14471cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1448360c497dSPeter Brune @*/
1449d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1450d71ae5a4SJacob Faibussowitsch {
1451360c497dSPeter Brune   PetscFunctionBegin;
1452360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14539566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1454360c497dSPeter Brune   snes->iter = iter;
14559566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1457360c497dSPeter Brune }
1458360c497dSPeter Brune 
14599b94acceSBarry Smith /*@
1460b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1461420bcc1bSBarry Smith   attempted by the nonlinear solver in the current or most recent `SNESSolve()` .
14629b94acceSBarry Smith 
1463c7afd0dbSLois Curfman McInnes   Not Collective
1464c7afd0dbSLois Curfman McInnes 
14659b94acceSBarry Smith   Input Parameter:
1466f6dfbefdSBarry Smith . snes - `SNES` context
14679b94acceSBarry Smith 
14689b94acceSBarry Smith   Output Parameter:
14699b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14709b94acceSBarry Smith 
1471dc4c0fb0SBarry Smith   Level: intermediate
1472dc4c0fb0SBarry Smith 
1473f6dfbefdSBarry Smith   Note:
1474f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1475c96a6f78SLois Curfman McInnes 
14761cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1477db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14789b94acceSBarry Smith @*/
1479d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1480d71ae5a4SJacob Faibussowitsch {
14813a40ed3dSBarry Smith   PetscFunctionBegin;
14820700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14834f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
148450ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
148650ffb88aSMatthew Knepley }
148750ffb88aSMatthew Knepley 
148850ffb88aSMatthew Knepley /*@
1489b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1490420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
149150ffb88aSMatthew Knepley 
149250ffb88aSMatthew Knepley   Not Collective
149350ffb88aSMatthew Knepley 
149450ffb88aSMatthew Knepley   Input Parameters:
1495f6dfbefdSBarry Smith + snes     - `SNES` context
149677e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures
149750ffb88aSMatthew Knepley 
1498420bcc1bSBarry Smith   Options Database Key:
1499420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1500420bcc1bSBarry Smith 
150150ffb88aSMatthew Knepley   Level: intermediate
150250ffb88aSMatthew Knepley 
1503420bcc1bSBarry Smith   Developer Note:
1504420bcc1bSBarry Smith   The options database key is wrong for this function name
1505420bcc1bSBarry Smith 
15061cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1507db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
150850ffb88aSMatthew Knepley @*/
1509d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1510d71ae5a4SJacob Faibussowitsch {
151150ffb88aSMatthew Knepley   PetscFunctionBegin;
15120700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
151377e5a1f9SBarry Smith 
151477e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
15151690c2aeSBarry Smith     snes->maxFailures = PETSC_INT_MAX;
151677e5a1f9SBarry Smith   } else {
151777e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
151850ffb88aSMatthew Knepley     snes->maxFailures = maxFails;
151977e5a1f9SBarry Smith   }
15203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
152150ffb88aSMatthew Knepley }
152250ffb88aSMatthew Knepley 
152350ffb88aSMatthew Knepley /*@
1524b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1525420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
152650ffb88aSMatthew Knepley 
152750ffb88aSMatthew Knepley   Not Collective
152850ffb88aSMatthew Knepley 
152950ffb88aSMatthew Knepley   Input Parameter:
153020f4b53cSBarry Smith . snes - `SNES` context
153150ffb88aSMatthew Knepley 
153250ffb88aSMatthew Knepley   Output Parameter:
153350ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
153450ffb88aSMatthew Knepley 
153550ffb88aSMatthew Knepley   Level: intermediate
153650ffb88aSMatthew Knepley 
15371cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1538db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
153950ffb88aSMatthew Knepley @*/
1540d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1541d71ae5a4SJacob Faibussowitsch {
154250ffb88aSMatthew Knepley   PetscFunctionBegin;
15430700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15444f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
154550ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
15463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15479b94acceSBarry Smith }
1548a847f771SSatish Balay 
15492541af92SBarry Smith /*@
15502541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1551420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
15522541af92SBarry Smith 
15532541af92SBarry Smith   Not Collective
15542541af92SBarry Smith 
15552541af92SBarry Smith   Input Parameter:
1556f6dfbefdSBarry Smith . snes - `SNES` context
15572541af92SBarry Smith 
15582541af92SBarry Smith   Output Parameter:
15592541af92SBarry Smith . nfuncs - number of evaluations
15602541af92SBarry Smith 
15612541af92SBarry Smith   Level: intermediate
15622541af92SBarry Smith 
1563f6dfbefdSBarry Smith   Note:
1564f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1565971e163fSPeter Brune 
15661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15672541af92SBarry Smith @*/
1568d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1569d71ae5a4SJacob Faibussowitsch {
15702541af92SBarry Smith   PetscFunctionBegin;
15710700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15724f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15732541af92SBarry Smith   *nfuncs = snes->nfuncs;
15743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15752541af92SBarry Smith }
15762541af92SBarry Smith 
15773d4c4710SBarry Smith /*@
15783d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1579420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15803d4c4710SBarry Smith 
15813d4c4710SBarry Smith   Not Collective
15823d4c4710SBarry Smith 
15833d4c4710SBarry Smith   Input Parameter:
1584f6dfbefdSBarry Smith . snes - `SNES` context
15853d4c4710SBarry Smith 
15863d4c4710SBarry Smith   Output Parameter:
15873d4c4710SBarry Smith . nfails - number of failed solves
15883d4c4710SBarry Smith 
1589f6dfbefdSBarry Smith   Options Database Key:
15909d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15919d85da0cSMatthew G. Knepley 
1592f6dfbefdSBarry Smith   Level: intermediate
1593f6dfbefdSBarry Smith 
1594f6dfbefdSBarry Smith   Note:
1595f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15963d4c4710SBarry Smith 
15971cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15983d4c4710SBarry Smith @*/
1599d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1600d71ae5a4SJacob Faibussowitsch {
16013d4c4710SBarry Smith   PetscFunctionBegin;
16020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16034f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
16043d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
16053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16063d4c4710SBarry Smith }
16073d4c4710SBarry Smith 
16083d4c4710SBarry Smith /*@
16093d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1610f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
16113d4c4710SBarry Smith 
1612c3339decSBarry Smith   Logically Collective
16133d4c4710SBarry Smith 
16143d4c4710SBarry Smith   Input Parameters:
1615f6dfbefdSBarry Smith + snes     - `SNES` context
161677e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures
16173d4c4710SBarry Smith 
1618f6dfbefdSBarry Smith   Options Database Key:
16199d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
16209d85da0cSMatthew G. Knepley 
1621dc4c0fb0SBarry Smith   Level: intermediate
1622dc4c0fb0SBarry Smith 
1623f6dfbefdSBarry Smith   Note:
1624f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
16253d4c4710SBarry Smith 
1626420bcc1bSBarry Smith   Developer Note:
1627420bcc1bSBarry Smith   The options database key is wrong for this function name
1628420bcc1bSBarry Smith 
16291cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
16303d4c4710SBarry Smith @*/
1631d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1632d71ae5a4SJacob Faibussowitsch {
16333d4c4710SBarry Smith   PetscFunctionBegin;
16340700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1635c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
163677e5a1f9SBarry Smith 
163777e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
16381690c2aeSBarry Smith     snes->maxLinearSolveFailures = PETSC_INT_MAX;
163977e5a1f9SBarry Smith   } else {
164077e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
16413d4c4710SBarry Smith     snes->maxLinearSolveFailures = maxFails;
164277e5a1f9SBarry Smith   }
16433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16443d4c4710SBarry Smith }
16453d4c4710SBarry Smith 
16463d4c4710SBarry Smith /*@
16473d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1648f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
16493d4c4710SBarry Smith 
16503d4c4710SBarry Smith   Not Collective
16513d4c4710SBarry Smith 
16523d4c4710SBarry Smith   Input Parameter:
1653f6dfbefdSBarry Smith . snes - `SNES` context
16543d4c4710SBarry Smith 
16553d4c4710SBarry Smith   Output Parameter:
16563d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16573d4c4710SBarry Smith 
16583d4c4710SBarry Smith   Level: intermediate
16593d4c4710SBarry Smith 
1660f6dfbefdSBarry Smith   Note:
1661f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16623d4c4710SBarry Smith 
16631cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16643d4c4710SBarry Smith @*/
1665d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1666d71ae5a4SJacob Faibussowitsch {
16673d4c4710SBarry Smith   PetscFunctionBegin;
16680700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16694f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16703d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16723d4c4710SBarry Smith }
16733d4c4710SBarry Smith 
1674c96a6f78SLois Curfman McInnes /*@
1675b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1676420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1677c96a6f78SLois Curfman McInnes 
1678c7afd0dbSLois Curfman McInnes   Not Collective
1679c7afd0dbSLois Curfman McInnes 
1680c96a6f78SLois Curfman McInnes   Input Parameter:
1681f6dfbefdSBarry Smith . snes - `SNES` context
1682c96a6f78SLois Curfman McInnes 
1683c96a6f78SLois Curfman McInnes   Output Parameter:
1684c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1685c96a6f78SLois Curfman McInnes 
1686dc4c0fb0SBarry Smith   Level: intermediate
1687dc4c0fb0SBarry Smith 
1688c96a6f78SLois Curfman McInnes   Notes:
1689f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1690c96a6f78SLois Curfman McInnes 
1691f6dfbefdSBarry Smith   If the linear solver fails inside the `SNESSolve()` the iterations for that call to the linear solver are not included. If you wish to count them
1692f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1693010be392SBarry Smith 
16941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1695c96a6f78SLois Curfman McInnes @*/
1696d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1697d71ae5a4SJacob Faibussowitsch {
16983a40ed3dSBarry Smith   PetscFunctionBegin;
16990700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17004f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1701c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
17023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1703c96a6f78SLois Curfman McInnes }
1704c96a6f78SLois Curfman McInnes 
1705971e163fSPeter Brune /*@
1706971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1707f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1708971e163fSPeter Brune 
1709c3339decSBarry Smith   Logically Collective
1710971e163fSPeter Brune 
1711d8d19677SJose E. Roman   Input Parameters:
1712f6dfbefdSBarry Smith + snes  - `SNES` context
1713f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1714971e163fSPeter Brune 
1715971e163fSPeter Brune   Level: developer
1716971e163fSPeter Brune 
17171cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1718971e163fSPeter Brune @*/
1719d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1720d71ae5a4SJacob Faibussowitsch {
1721971e163fSPeter Brune   PetscFunctionBegin;
1722971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1723971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1724971e163fSPeter Brune   snes->counters_reset = reset;
17253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1726971e163fSPeter Brune }
1727971e163fSPeter Brune 
17282999313aSBarry Smith /*@
172912b1dd1aSStefano Zampini   SNESResetCounters - Reset counters for linear iterations and function evaluations.
173012b1dd1aSStefano Zampini 
173112b1dd1aSStefano Zampini   Logically Collective
173212b1dd1aSStefano Zampini 
173312b1dd1aSStefano Zampini   Input Parameters:
173412b1dd1aSStefano Zampini . snes - `SNES` context
173512b1dd1aSStefano Zampini 
173612b1dd1aSStefano Zampini   Level: developer
173712b1dd1aSStefano Zampini 
173812b1dd1aSStefano Zampini   Note:
173912b1dd1aSStefano Zampini   It honors the flag set with `SNESSetCountersReset()`
174012b1dd1aSStefano Zampini 
174112b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
174212b1dd1aSStefano Zampini @*/
174312b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes)
174412b1dd1aSStefano Zampini {
174512b1dd1aSStefano Zampini   PetscFunctionBegin;
174612b1dd1aSStefano Zampini   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
174712b1dd1aSStefano Zampini   if (snes->counters_reset) {
174812b1dd1aSStefano Zampini     snes->nfuncs      = 0;
174912b1dd1aSStefano Zampini     snes->linear_its  = 0;
175012b1dd1aSStefano Zampini     snes->numFailures = 0;
175112b1dd1aSStefano Zampini   }
175212b1dd1aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
175312b1dd1aSStefano Zampini }
175412b1dd1aSStefano Zampini 
175512b1dd1aSStefano Zampini /*@
1756f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
17572999313aSBarry Smith 
1758420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
17592999313aSBarry Smith 
17602999313aSBarry Smith   Input Parameters:
1761f6dfbefdSBarry Smith + snes - the `SNES` context
1762f6dfbefdSBarry Smith - ksp  - the `KSP` context
17632999313aSBarry Smith 
1764dc4c0fb0SBarry Smith   Level: developer
1765dc4c0fb0SBarry Smith 
17662999313aSBarry Smith   Notes:
1767f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
17682999313aSBarry Smith   so this routine is rarely needed.
17692999313aSBarry Smith 
1770f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1771420bcc1bSBarry Smith   decreased by one when this is called.
17722999313aSBarry Smith 
177342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
17742999313aSBarry Smith @*/
1775d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1776d71ae5a4SJacob Faibussowitsch {
17772999313aSBarry Smith   PetscFunctionBegin;
17780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17790700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
17802999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
17819566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
17829566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17832999313aSBarry Smith   snes->ksp = ksp;
17843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17852999313aSBarry Smith }
17862999313aSBarry Smith 
178752baeb72SSatish Balay /*@
178877e5a1f9SBarry Smith   SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they
178977e5a1f9SBarry Smith   currently contain default values
179077e5a1f9SBarry Smith 
179177e5a1f9SBarry Smith   Collective
179277e5a1f9SBarry Smith 
179377e5a1f9SBarry Smith   Input Parameter:
179477e5a1f9SBarry Smith . snes - the `SNES` object
179577e5a1f9SBarry Smith 
179677e5a1f9SBarry Smith   Level: developer
179777e5a1f9SBarry Smith 
179877e5a1f9SBarry Smith   Developer Note:
179977e5a1f9SBarry Smith   This is called by all the `SNESCreate_XXX()` routines.
180077e5a1f9SBarry Smith 
180177e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`,
180277e5a1f9SBarry Smith           `PetscObjectParameterSetDefault()`
180377e5a1f9SBarry Smith @*/
180477e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes)
180577e5a1f9SBarry Smith {
180677e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_its, 50);
180777e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_funcs, 10000);
180877e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
180977e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50);
181077e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
181177e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, divtol, 1.e4);
181277e5a1f9SBarry Smith   return PETSC_SUCCESS;
181377e5a1f9SBarry Smith }
181477e5a1f9SBarry Smith 
181577e5a1f9SBarry Smith /*@
1816dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
18179b94acceSBarry Smith 
1818d083f849SBarry Smith   Collective
1819c7afd0dbSLois Curfman McInnes 
1820f6dfbefdSBarry Smith   Input Parameter:
1821906ed7ccSBarry Smith . comm - MPI communicator
18229b94acceSBarry Smith 
18239b94acceSBarry Smith   Output Parameter:
182420f4b53cSBarry Smith . outsnes - the new `SNES` context
18259b94acceSBarry Smith 
1826c7afd0dbSLois Curfman McInnes   Options Database Keys:
18277addb90fSBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner
18287addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()`
1829dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1830c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1831c1f60f51SBarry Smith 
183236851e7fSLois Curfman McInnes   Level: beginner
183336851e7fSLois Curfman McInnes 
183495452b02SPatrick Sanan   Developer Notes:
1835f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1836efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1837f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1838f6dfbefdSBarry Smith   in `SNESView()`.
1839efd4aadfSBarry Smith 
1840f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1841f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1842f6dfbefdSBarry Smith 
18437addb90fSBarry Smith   `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed.
1844efd4aadfSBarry Smith 
1845e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
18469b94acceSBarry Smith @*/
1847d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1848d71ae5a4SJacob Faibussowitsch {
18499b94acceSBarry Smith   SNES       snes;
1850fa9f3622SBarry Smith   SNESKSPEW *kctx;
185137fcc0dbSBarry Smith 
18523a40ed3dSBarry Smith   PetscFunctionBegin;
18534f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
18549566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
18558ba1e511SMatthew Knepley 
18569566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
18578d359177SBarry Smith   snes->ops->converged = SNESConvergedDefault;
18582c155ee1SBarry Smith   snes->usesksp        = PETSC_TRUE;
18599b94acceSBarry Smith   snes->norm           = 0.0;
1860c1e67a49SFande Kong   snes->xnorm          = 0.0;
1861c1e67a49SFande Kong   snes->ynorm          = 0.0;
1862365a6726SPeter Brune   snes->normschedule   = SNES_NORM_ALWAYS;
18636c67d002SPeter Brune   snes->functype       = SNES_FUNCTION_DEFAULT;
1864b4874afaSBarry Smith   snes->ttol           = 0.0;
186577e5a1f9SBarry Smith 
1866e37c518bSBarry Smith   snes->rnorm0               = 0;
18679b94acceSBarry Smith   snes->nfuncs               = 0;
186850ffb88aSMatthew Knepley   snes->numFailures          = 0;
186950ffb88aSMatthew Knepley   snes->maxFailures          = 1;
18707a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1871e35cf81dSBarry Smith   snes->lagjacobian          = 1;
187237ec4e1aSPeter Brune   snes->jac_iter             = 0;
187337ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1874a8054027SBarry Smith   snes->lagpreconditioner    = 1;
187537ec4e1aSPeter Brune   snes->pre_iter             = 0;
187637ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1877639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1878c4421ceaSFande Kong   snes->numberreasonviews    = 0;
18799e5d0892SLisandro Dalcin   snes->data                 = NULL;
18804dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1881186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
18826f24a144SLois Curfman McInnes   snes->nwork                = 0;
18839e5d0892SLisandro Dalcin   snes->work                 = NULL;
188458c9b817SLisandro Dalcin   snes->nvwork               = 0;
18859e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1886758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1887758f92a0SBarry Smith   snes->conv_hist_max        = 0;
18880298fd71SBarry Smith   snes->conv_hist            = NULL;
18890298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1890758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1891971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1892e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1893184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1894efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1895b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1896c40d0f55SPeter Brune 
1897d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1898d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1899d8f46077SPeter Brune   snes->mf_version  = 1;
1900d8f46077SPeter Brune 
19013d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
19023d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
19033d4c4710SBarry Smith 
1904349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
190576bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1906349187a7SBarry Smith 
19074fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
19084fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
19094fc747eaSLawrence Mitchell 
19109b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
19114dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1912f5af7f23SKarl Rupp 
1913835f2295SStefano Zampini   snes->kspconvctx  = kctx;
19149b94acceSBarry Smith   kctx->version     = 2;
19150f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
19169b94acceSBarry Smith                              this was too large for some test cases */
191775567043SBarry Smith   kctx->rtol_last   = 0.0;
19180f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
19199b94acceSBarry Smith   kctx->gamma       = 1.0;
19200f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
192171f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
19220f0abf79SStefano Zampini   kctx->threshold   = 0.1;
192375567043SBarry Smith   kctx->lresid_last = 0.0;
192475567043SBarry Smith   kctx->norm_last   = 0.0;
19259b94acceSBarry Smith 
19260f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
19270f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
19280f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
19290f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
19300f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
19310f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
19320f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
19330f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
19340f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
19350f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
19360f0abf79SStefano Zampini 
1937b50c806fSBarry Smith   PetscCall(SNESParametersInitialize(snes));
19389b94acceSBarry Smith   *outsnes = snes;
19393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19409b94acceSBarry Smith }
19419b94acceSBarry Smith 
19429b94acceSBarry Smith /*@C
19439b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1944f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
19459b94acceSBarry Smith   equations.
19469b94acceSBarry Smith 
1947c3339decSBarry Smith   Logically Collective
1948fee21e36SBarry Smith 
1949c7afd0dbSLois Curfman McInnes   Input Parameters:
1950f6dfbefdSBarry Smith + snes - the `SNES` context
1951dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
19528434afd1SBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunctionFn`
1953c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1954dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
19559b94acceSBarry Smith 
195636851e7fSLois Curfman McInnes   Level: beginner
195736851e7fSLois Curfman McInnes 
19588434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
19599b94acceSBarry Smith @*/
19608434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx)
1961d71ae5a4SJacob Faibussowitsch {
19626cab3a1bSJed Brown   DM dm;
19636cab3a1bSJed Brown 
19643a40ed3dSBarry Smith   PetscFunctionBegin;
19650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1966d2a683ecSLisandro Dalcin   if (r) {
1967d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1968d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
19699566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
19709566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
197185385478SLisandro Dalcin     snes->vec_func = r;
1972d2a683ecSLisandro Dalcin   }
19739566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
19749566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
197548a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
19763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19779b94acceSBarry Smith }
19789b94acceSBarry Smith 
1979e4ed7901SPeter Brune /*@C
19800b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1981e4ed7901SPeter Brune 
1982c3339decSBarry Smith   Logically Collective
1983e4ed7901SPeter Brune 
1984e4ed7901SPeter Brune   Input Parameters:
1985f6dfbefdSBarry Smith + snes - the `SNES` context
1986e4ed7901SPeter Brune - f    - vector to store function value
1987e4ed7901SPeter Brune 
1988dc4c0fb0SBarry Smith   Level: developer
1989dc4c0fb0SBarry Smith 
1990e4ed7901SPeter Brune   Notes:
1991e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1992e4ed7901SPeter Brune 
1993f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1994e4ed7901SPeter Brune 
19951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1996e4ed7901SPeter Brune @*/
1997d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1998d71ae5a4SJacob Faibussowitsch {
1999e4ed7901SPeter Brune   Vec vec_func;
2000e4ed7901SPeter Brune 
2001e4ed7901SPeter Brune   PetscFunctionBegin;
2002e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2003e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
2004e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
2005efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
2006902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
20073ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2008902f982fSPeter Brune   }
20099566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
20109566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
2011f5af7f23SKarl Rupp 
2012217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
20133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2014e4ed7901SPeter Brune }
2015e4ed7901SPeter Brune 
2016534ebe21SPeter Brune /*@
2017f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
2018f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
2019534ebe21SPeter Brune 
2020c3339decSBarry Smith   Logically Collective
2021534ebe21SPeter Brune 
2022534ebe21SPeter Brune   Input Parameters:
2023f6dfbefdSBarry Smith + snes         - the `SNES` context
2024365a6726SPeter Brune - normschedule - the frequency of norm computation
2025534ebe21SPeter Brune 
2026517f1916SMatthew G. Knepley   Options Database Key:
202767b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
2028517f1916SMatthew G. Knepley 
2029dc4c0fb0SBarry Smith   Level: advanced
2030dc4c0fb0SBarry Smith 
2031534ebe21SPeter Brune   Notes:
2032f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
2033534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
2034534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
2035f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
2036534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
2037534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
2038534ebe21SPeter Brune   their solution.
2039534ebe21SPeter Brune 
2040e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
2041534ebe21SPeter Brune @*/
2042d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
2043d71ae5a4SJacob Faibussowitsch {
2044534ebe21SPeter Brune   PetscFunctionBegin;
2045534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2046365a6726SPeter Brune   snes->normschedule = normschedule;
20473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2048534ebe21SPeter Brune }
2049534ebe21SPeter Brune 
2050534ebe21SPeter Brune /*@
2051f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
2052f6dfbefdSBarry Smith   of the `SNES` method.
2053534ebe21SPeter Brune 
2054c3339decSBarry Smith   Logically Collective
2055534ebe21SPeter Brune 
2056534ebe21SPeter Brune   Input Parameters:
2057f6dfbefdSBarry Smith + snes         - the `SNES` context
2058365a6726SPeter Brune - normschedule - the type of the norm used
2059534ebe21SPeter Brune 
2060534ebe21SPeter Brune   Level: advanced
2061534ebe21SPeter Brune 
20621cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2063534ebe21SPeter Brune @*/
2064d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
2065d71ae5a4SJacob Faibussowitsch {
2066534ebe21SPeter Brune   PetscFunctionBegin;
2067534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2068365a6726SPeter Brune   *normschedule = snes->normschedule;
20693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2070534ebe21SPeter Brune }
2071534ebe21SPeter Brune 
2072c5ce4427SMatthew G. Knepley /*@
2073c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
2074c5ce4427SMatthew G. Knepley 
2075c3339decSBarry Smith   Logically Collective
2076c5ce4427SMatthew G. Knepley 
2077c5ce4427SMatthew G. Knepley   Input Parameters:
2078f6dfbefdSBarry Smith + snes - the `SNES` context
2079f6dfbefdSBarry Smith - norm - the value of the norm
2080c5ce4427SMatthew G. Knepley 
2081c5ce4427SMatthew G. Knepley   Level: developer
2082c5ce4427SMatthew G. Knepley 
20831cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2084c5ce4427SMatthew G. Knepley @*/
2085d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
2086d71ae5a4SJacob Faibussowitsch {
2087c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2088c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2089c5ce4427SMatthew G. Knepley   snes->norm = norm;
20903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2091c5ce4427SMatthew G. Knepley }
2092c5ce4427SMatthew G. Knepley 
2093c5ce4427SMatthew G. Knepley /*@
2094c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
2095c5ce4427SMatthew G. Knepley 
2096c5ce4427SMatthew G. Knepley   Not Collective
2097c5ce4427SMatthew G. Knepley 
2098c5ce4427SMatthew G. Knepley   Input Parameter:
2099f6dfbefdSBarry Smith . snes - the `SNES` context
2100c5ce4427SMatthew G. Knepley 
2101c5ce4427SMatthew G. Knepley   Output Parameter:
2102c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2103c5ce4427SMatthew G. Knepley 
2104c5ce4427SMatthew G. Knepley   Level: developer
2105c5ce4427SMatthew G. Knepley 
21061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2107c5ce4427SMatthew G. Knepley @*/
2108d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2109d71ae5a4SJacob Faibussowitsch {
2110c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2111c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21124f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2113c5ce4427SMatthew G. Knepley   *norm = snes->norm;
21143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2115c5ce4427SMatthew G. Knepley }
2116c5ce4427SMatthew G. Knepley 
2117c1e67a49SFande Kong /*@
2118f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2119c1e67a49SFande Kong 
2120c1e67a49SFande Kong   Not Collective
2121c1e67a49SFande Kong 
2122c1e67a49SFande Kong   Input Parameter:
2123f6dfbefdSBarry Smith . snes - the `SNES` context
2124c1e67a49SFande Kong 
2125c1e67a49SFande Kong   Output Parameter:
2126c1e67a49SFande Kong . ynorm - the last computed update norm
2127c1e67a49SFande Kong 
2128c1e67a49SFande Kong   Level: developer
2129c1e67a49SFande Kong 
2130f6dfbefdSBarry Smith   Note:
2131f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2132f6dfbefdSBarry Smith 
21331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2134c1e67a49SFande Kong @*/
2135d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2136d71ae5a4SJacob Faibussowitsch {
2137c1e67a49SFande Kong   PetscFunctionBegin;
2138c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21394f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2140c1e67a49SFande Kong   *ynorm = snes->ynorm;
21413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2142c1e67a49SFande Kong }
2143c1e67a49SFande Kong 
2144c1e67a49SFande Kong /*@
21454591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2146c1e67a49SFande Kong 
2147c1e67a49SFande Kong   Not Collective
2148c1e67a49SFande Kong 
2149c1e67a49SFande Kong   Input Parameter:
2150f6dfbefdSBarry Smith . snes - the `SNES` context
2151c1e67a49SFande Kong 
2152c1e67a49SFande Kong   Output Parameter:
2153c1e67a49SFande Kong . xnorm - the last computed solution norm
2154c1e67a49SFande Kong 
2155c1e67a49SFande Kong   Level: developer
2156c1e67a49SFande Kong 
21571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2158c1e67a49SFande Kong @*/
2159d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2160d71ae5a4SJacob Faibussowitsch {
2161c1e67a49SFande Kong   PetscFunctionBegin;
2162c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21634f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2164c1e67a49SFande Kong   *xnorm = snes->xnorm;
21653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2166c1e67a49SFande Kong }
2167c1e67a49SFande Kong 
2168cc4c1da9SBarry Smith /*@
2169f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2170f6dfbefdSBarry Smith   of the `SNES` method.
217147073ea2SPeter Brune 
2172c3339decSBarry Smith   Logically Collective
217347073ea2SPeter Brune 
217447073ea2SPeter Brune   Input Parameters:
2175f6dfbefdSBarry Smith + snes - the `SNES` context
2176f6dfbefdSBarry Smith - type - the function type
217747073ea2SPeter Brune 
217847073ea2SPeter Brune   Level: developer
217947073ea2SPeter Brune 
2180420bcc1bSBarry Smith   Values of the function type\:
2181f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT`          - the default for the given `SNESType`
2182f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2183f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED`   - a transformation of the function provided with `SNESSetFunction()`
2184f6dfbefdSBarry Smith 
2185420bcc1bSBarry Smith   Note:
2186f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2187f6dfbefdSBarry Smith 
21881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
218947073ea2SPeter Brune @*/
2190d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2191d71ae5a4SJacob Faibussowitsch {
219247073ea2SPeter Brune   PetscFunctionBegin;
219347073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
219447073ea2SPeter Brune   snes->functype = type;
21953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
219647073ea2SPeter Brune }
219747073ea2SPeter Brune 
2198cc4c1da9SBarry Smith /*@
2199f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
220047073ea2SPeter Brune   of the SNES method.
220147073ea2SPeter Brune 
2202c3339decSBarry Smith   Logically Collective
220347073ea2SPeter Brune 
220447073ea2SPeter Brune   Input Parameters:
2205f6dfbefdSBarry Smith + snes - the `SNES` context
2206f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
220747073ea2SPeter Brune 
220847073ea2SPeter Brune   Level: advanced
220947073ea2SPeter Brune 
22101cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
221147073ea2SPeter Brune @*/
2212d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2213d71ae5a4SJacob Faibussowitsch {
221447073ea2SPeter Brune   PetscFunctionBegin;
221547073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
221647073ea2SPeter Brune   *type = snes->functype;
22173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2218534ebe21SPeter Brune }
2219534ebe21SPeter Brune 
2220c79ef259SPeter Brune /*@C
2221be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2222c79ef259SPeter Brune   use with composed nonlinear solvers.
2223c79ef259SPeter Brune 
2224c79ef259SPeter Brune   Input Parameters:
22259bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
22268434afd1SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
222777e5a1f9SBarry Smith - ctx  - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`)
2228c79ef259SPeter Brune 
2229dc4c0fb0SBarry Smith   Level: intermediate
2230dc4c0fb0SBarry Smith 
2231f6dfbefdSBarry Smith   Note:
2232f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2233f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2234c79ef259SPeter Brune 
22358434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2236c79ef259SPeter Brune @*/
22378434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx)
2238d71ae5a4SJacob Faibussowitsch {
22396cab3a1bSJed Brown   DM dm;
22406cab3a1bSJed Brown 
2241646217ecSPeter Brune   PetscFunctionBegin;
22426cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22439566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22449566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
22453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2246646217ecSPeter Brune }
2247646217ecSPeter Brune 
2248bbc1464cSBarry Smith /*
2249bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2250bbc1464cSBarry Smith    changed during the KSPSolve()
2251bbc1464cSBarry Smith */
2252d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2253d71ae5a4SJacob Faibussowitsch {
2254bbc1464cSBarry Smith   DM     dm;
2255bbc1464cSBarry Smith   DMSNES sdm;
2256bbc1464cSBarry Smith 
2257bbc1464cSBarry Smith   PetscFunctionBegin;
22589566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22599566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2260bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2261bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2262792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22639566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
22640df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2265ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2266792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22679566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2268bbc1464cSBarry Smith   } else {
2269792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22709566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2271bbc1464cSBarry Smith   }
22723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2273bbc1464cSBarry Smith }
2274bbc1464cSBarry Smith 
2275d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2276d71ae5a4SJacob Faibussowitsch {
2277e03ab78fSPeter Brune   DM     dm;
2278942e3340SBarry Smith   DMSNES sdm;
22796cab3a1bSJed Brown 
22808b0a5094SBarry Smith   PetscFunctionBegin;
22819566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22829566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22838b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2284bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2285792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22869566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2287792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22889566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2289bbc1464cSBarry Smith   } else {
2290792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22919566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2292bbc1464cSBarry Smith   }
22933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22948b0a5094SBarry Smith }
22958b0a5094SBarry Smith 
2296d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2297d71ae5a4SJacob Faibussowitsch {
22988b0a5094SBarry Smith   PetscFunctionBegin;
2299e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2300bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
23019566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
23029566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
23033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23048b0a5094SBarry Smith }
23058b0a5094SBarry Smith 
23068b0a5094SBarry Smith /*@C
23071d27aa22SBarry Smith   SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
23088b0a5094SBarry Smith 
2309c3339decSBarry Smith   Logically Collective
23108b0a5094SBarry Smith 
23118b0a5094SBarry Smith   Input Parameters:
2312f6dfbefdSBarry Smith + snes - the `SNES` context
2313dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
23148434afd1SBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
231526a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed
2316dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
23178434afd1SBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2318dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2319dc4c0fb0SBarry Smith 
2320dc4c0fb0SBarry Smith   Level: intermediate
23218b0a5094SBarry Smith 
23228b0a5094SBarry Smith   Notes:
232326a11704SBarry Smith   It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use
2324f450aa47SBarry Smith   an approximate Newton solver. This interface is provided to allow porting/testing a previous Picard based code in PETSc before converting it to approximate Newton.
2325f450aa47SBarry Smith 
2326f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
23278b0a5094SBarry Smith 
23281d27aa22SBarry Smith   Solves the equation $A(x) x = bp(x) - b$ via the defect correction algorithm $A(x^{n}) (x^{n+1} - x^{n}) = bp(x^{n}) + b - A(x^{n})x^{n}$.
23291d27aa22SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
23308b0a5094SBarry Smith 
233126a11704SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner.
23328b0a5094SBarry Smith 
23330d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
23341d27aa22SBarry Smith   the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
23358b0a5094SBarry Smith 
23368b0a5094SBarry Smith   There is some controversity over the definition of a Picard iteration for nonlinear systems but almost everyone agrees that it involves a linear solve and some
23371d27aa22SBarry Smith   believe it is the iteration  $A(x^{n}) x^{n+1} = b(x^{n})$ hence we use the name Picard. If anyone has an authoritative  reference that defines the Picard iteration
23381d27aa22SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
23398b0a5094SBarry Smith 
23401d27aa22SBarry Smith   When used with `-snes_mf_operator` this will run matrix-free Newton's method where the matrix-vector product is of the true Jacobian of $A(x)x - bp(x) - b$ and
234126a11704SBarry Smith   $A(x^{n})$ is used to build the preconditioner
23426b7fb656SBarry Smith 
234315229ffcSPierre Jolivet   When used with `-snes_fd` this will compute the true Jacobian (very slowly one column at a time) and thus represent Newton's method.
23446b7fb656SBarry Smith 
2345dc4c0fb0SBarry Smith   When used with `-snes_fd_coloring` this will compute the Jacobian via coloring and thus represent a faster implementation of Newton's method. But the
234626a11704SBarry Smith   the nonzero structure of the Jacobian is, in general larger than that of the Picard matrix $A$ so you must provide in $A$ the needed nonzero structure for the correct
234726a11704SBarry Smith   coloring. When using `DMDA` this may mean creating the matrix $A$ with `DMCreateMatrix()` using a wider stencil than strictly needed for $A$ or with a `DMDA_STENCIL_BOX`.
2348aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2349bbc1464cSBarry Smith 
23509bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
23518434afd1SBarry Smith           `SNESFunctionFn`, `SNESJacobianFn`
23528b0a5094SBarry Smith @*/
23538434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
2354d71ae5a4SJacob Faibussowitsch {
2355e03ab78fSPeter Brune   DM dm;
2356e03ab78fSPeter Brune 
23578b0a5094SBarry Smith   PetscFunctionBegin;
23588b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23599566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23609566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
23619566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
23629566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
23639566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
23643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23658b0a5094SBarry Smith }
23668b0a5094SBarry Smith 
23677971a8bfSPeter Brune /*@C
23687971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
23697971a8bfSPeter Brune 
2370f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
23717971a8bfSPeter Brune 
23727971a8bfSPeter Brune   Input Parameter:
2373f6dfbefdSBarry Smith . snes - the `SNES` context
23747971a8bfSPeter Brune 
2375d8d19677SJose E. Roman   Output Parameters:
2376dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
23778434afd1SBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunctionFn`
2378dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2379dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
23808434afd1SBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFn`
2381dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
23827971a8bfSPeter Brune 
23837971a8bfSPeter Brune   Level: advanced
23847971a8bfSPeter Brune 
23858434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
23867971a8bfSPeter Brune @*/
23878434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
2388d71ae5a4SJacob Faibussowitsch {
23897971a8bfSPeter Brune   DM dm;
23907971a8bfSPeter Brune 
23917971a8bfSPeter Brune   PetscFunctionBegin;
23927971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23939566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23949566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23959566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23969566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23987971a8bfSPeter Brune }
23997971a8bfSPeter Brune 
2400d25893d9SBarry Smith /*@C
2401dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2402d25893d9SBarry Smith 
2403c3339decSBarry Smith   Logically Collective
2404d25893d9SBarry Smith 
2405d25893d9SBarry Smith   Input Parameters:
2406f6dfbefdSBarry Smith + snes - the `SNES` context
24078434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2408d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2409dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2410d25893d9SBarry Smith 
2411d25893d9SBarry Smith   Level: intermediate
2412d25893d9SBarry Smith 
24138434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2414d25893d9SBarry Smith @*/
24158434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx)
2416d71ae5a4SJacob Faibussowitsch {
2417d25893d9SBarry Smith   PetscFunctionBegin;
2418d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2419d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2420d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
24213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2422d25893d9SBarry Smith }
2423d25893d9SBarry Smith 
24241096aae1SMatthew Knepley /*@C
2425dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2426dd8e379bSPierre Jolivet   it assumes a zero right-hand side.
24271096aae1SMatthew Knepley 
2428c3339decSBarry Smith   Logically Collective
24291096aae1SMatthew Knepley 
24301096aae1SMatthew Knepley   Input Parameter:
2431f6dfbefdSBarry Smith . snes - the `SNES` context
24321096aae1SMatthew Knepley 
24331096aae1SMatthew Knepley   Output Parameter:
2434dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
24351096aae1SMatthew Knepley 
24361096aae1SMatthew Knepley   Level: intermediate
24371096aae1SMatthew Knepley 
24381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
24391096aae1SMatthew Knepley @*/
2440d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2441d71ae5a4SJacob Faibussowitsch {
24421096aae1SMatthew Knepley   PetscFunctionBegin;
24430700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24444f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
244585385478SLisandro Dalcin   *rhs = snes->vec_rhs;
24463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24471096aae1SMatthew Knepley }
24481096aae1SMatthew Knepley 
24499b94acceSBarry Smith /*@
2450f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
24519b94acceSBarry Smith 
2452c3339decSBarry Smith   Collective
2453c7afd0dbSLois Curfman McInnes 
24549b94acceSBarry Smith   Input Parameters:
2455f6dfbefdSBarry Smith + snes - the `SNES` context
2456c7afd0dbSLois Curfman McInnes - x    - input vector
24579b94acceSBarry Smith 
24589b94acceSBarry Smith   Output Parameter:
2459f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
24609b94acceSBarry Smith 
2461dc4c0fb0SBarry Smith   Level: developer
2462dc4c0fb0SBarry Smith 
246300677de2SStefano Zampini   Notes:
2464f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2465bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
246636851e7fSLois Curfman McInnes 
246700677de2SStefano Zampini   When solving for $F(x) = b$, this routine computes $y = F(x) - b$.
246800677de2SStefano Zampini 
24691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
24709b94acceSBarry Smith @*/
2471d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2472d71ae5a4SJacob Faibussowitsch {
24736cab3a1bSJed Brown   DM     dm;
2474942e3340SBarry Smith   DMSNES sdm;
24759b94acceSBarry Smith 
24763a40ed3dSBarry Smith   PetscFunctionBegin;
24770700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24780700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
24790700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2480c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2481c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2482e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2483184914b5SBarry Smith 
24849566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24859566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24860fdf79fbSJacob 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().");
248732f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
248848a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24899566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24908ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24918ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2492800f99ffSJeremy L Thompson     {
2493800f99ffSJeremy L Thompson       void           *ctx;
24948434afd1SBarry Smith       SNESFunctionFn *computefunction;
2495800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2496800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2497800f99ffSJeremy L Thompson     }
24989566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
249948a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
25000fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
25019566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
25020fdf79fbSJacob Faibussowitsch   }
25031baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2504ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2505422a814eSBarry Smith   /*
2506422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2507422a814eSBarry Smith      propagate the value to all processes
2508422a814eSBarry Smith   */
2509f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25119b94acceSBarry Smith }
25129b94acceSBarry Smith 
2513c79ef259SPeter Brune /*@
25140b4b7b1cSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`.
2515bbc1464cSBarry Smith 
2516c3339decSBarry Smith   Collective
2517bbc1464cSBarry Smith 
2518bbc1464cSBarry Smith   Input Parameters:
2519f6dfbefdSBarry Smith + snes - the `SNES` context
2520bbc1464cSBarry Smith - x    - input vector
2521bbc1464cSBarry Smith 
2522bbc1464cSBarry Smith   Output Parameter:
25230b4b7b1cSBarry Smith . y - output vector
2524bbc1464cSBarry Smith 
2525dc4c0fb0SBarry Smith   Level: developer
2526dc4c0fb0SBarry Smith 
2527bbc1464cSBarry Smith   Notes:
2528420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2529bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2530bbc1464cSBarry Smith 
2531dd8e379bSPierre Jolivet   Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2532f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2533dd8e379bSPierre 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.
2534bbc1464cSBarry Smith 
25350b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()`
2536bbc1464cSBarry Smith @*/
2537d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2538d71ae5a4SJacob Faibussowitsch {
2539bbc1464cSBarry Smith   DM     dm;
2540bbc1464cSBarry Smith   DMSNES sdm;
2541bbc1464cSBarry Smith 
2542bbc1464cSBarry Smith   PetscFunctionBegin;
2543bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2544bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2545bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2546bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2547bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2548e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2549bbc1464cSBarry Smith 
25509566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25519566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25529566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
25539566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2554bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2555bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2556792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
25579566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
25589566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2559bbc1464cSBarry Smith   snes->nfuncs++;
2560bbc1464cSBarry Smith   /*
2561bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2562bbc1464cSBarry Smith      propagate the value to all processes
2563bbc1464cSBarry Smith   */
2564f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2566bbc1464cSBarry Smith }
2567bbc1464cSBarry Smith 
2568bbc1464cSBarry Smith /*@
2569f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2570c79ef259SPeter Brune 
2571c3339decSBarry Smith   Collective
2572c79ef259SPeter Brune 
2573c79ef259SPeter Brune   Input Parameters:
2574f6dfbefdSBarry Smith + snes - the `SNES` context
2575c79ef259SPeter Brune . x    - input vector
2576c79ef259SPeter Brune - b    - rhs vector
2577c79ef259SPeter Brune 
2578c79ef259SPeter Brune   Output Parameter:
2579c79ef259SPeter Brune . x - new solution vector
2580c79ef259SPeter Brune 
2581dc4c0fb0SBarry Smith   Level: developer
2582dc4c0fb0SBarry Smith 
2583f6dfbefdSBarry Smith   Note:
2584f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2585c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2586c79ef259SPeter Brune   themselves.
2587c79ef259SPeter Brune 
25888434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2589c79ef259SPeter Brune @*/
2590d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2591d71ae5a4SJacob Faibussowitsch {
25926cab3a1bSJed Brown   DM     dm;
2593942e3340SBarry Smith   DMSNES sdm;
2594646217ecSPeter Brune 
2595646217ecSPeter Brune   PetscFunctionBegin;
2596646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2597064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2598064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2599064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2600064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2601e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
26029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
26039566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
26049566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
26050fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
26069566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2607792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
26089566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
26099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
26103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2611646217ecSPeter Brune }
2612646217ecSPeter Brune 
2613494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2614494a190aSStefano Zampini {
2615494a190aSStefano Zampini   Vec          X;
2616494a190aSStefano Zampini   PetscScalar *g;
2617494a190aSStefano Zampini   PetscReal    f, f2;
2618494a190aSStefano Zampini   PetscInt     low, high, N, i;
2619494a190aSStefano Zampini   PetscBool    flg;
2620494a190aSStefano Zampini   PetscReal    h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2621494a190aSStefano Zampini 
2622494a190aSStefano Zampini   PetscFunctionBegin;
2623494a190aSStefano Zampini   PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2624494a190aSStefano Zampini   PetscCall(VecDuplicate(Xin, &X));
2625494a190aSStefano Zampini   PetscCall(VecCopy(Xin, X));
2626494a190aSStefano Zampini   PetscCall(VecGetSize(X, &N));
2627494a190aSStefano Zampini   PetscCall(VecGetOwnershipRange(X, &low, &high));
2628494a190aSStefano Zampini   PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2629494a190aSStefano Zampini   PetscCall(VecGetArray(G, &g));
2630494a190aSStefano Zampini   for (i = 0; i < N; i++) {
2631494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2632494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2633494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2634494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f));
2635494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2636494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2637494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2638494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f2));
2639494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2640494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2641494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2642494a190aSStefano Zampini     if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2643494a190aSStefano Zampini   }
2644494a190aSStefano Zampini   PetscCall(VecRestoreArray(G, &g));
2645494a190aSStefano Zampini   PetscCall(VecDestroy(&X));
2646494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2647494a190aSStefano Zampini }
2648494a190aSStefano Zampini 
26491dfd7622SMatthew Knepley /*@
26501dfd7622SMatthew Knepley   SNESTestFunction - Computes the difference between the computed and finite-difference functions
26511dfd7622SMatthew Knepley 
26521dfd7622SMatthew Knepley   Collective
26531dfd7622SMatthew Knepley 
2654d5bfe6baSJose E. Roman   Input Parameter:
26551dfd7622SMatthew Knepley . snes - the `SNES` context
26561dfd7622SMatthew Knepley 
26571dfd7622SMatthew Knepley   Options Database Keys:
26581dfd7622SMatthew Knepley + -snes_test_function      - compare the user provided function with one compute via finite differences to check for errors.
26591dfd7622SMatthew Knepley - -snes_test_function_view - display the user provided function, the finite difference function and the difference
26601dfd7622SMatthew Knepley 
26611dfd7622SMatthew Knepley   Level: developer
26621dfd7622SMatthew Knepley 
26631dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestJacobian()`, `SNESSetFunction()`, `SNESComputeFunction()`
26641dfd7622SMatthew Knepley @*/
2665494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2666494a190aSStefano Zampini {
2667494a190aSStefano Zampini   Vec               x, g1, g2, g3;
26681dfd7622SMatthew Knepley   PetscBool         complete_print = PETSC_FALSE;
2669494a190aSStefano Zampini   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2670494a190aSStefano Zampini   PetscScalar       dot;
2671494a190aSStefano Zampini   MPI_Comm          comm;
2672494a190aSStefano Zampini   PetscViewer       viewer, mviewer;
2673494a190aSStefano Zampini   PetscViewerFormat format;
2674494a190aSStefano Zampini   PetscInt          tabs;
2675494a190aSStefano Zampini   static PetscBool  directionsprinted = PETSC_FALSE;
26768434afd1SBarry Smith   SNESObjectiveFn  *objective;
2677494a190aSStefano Zampini 
2678494a190aSStefano Zampini   PetscFunctionBegin;
2679494a190aSStefano Zampini   PetscCall(SNESGetObjective(snes, &objective, NULL));
2680494a190aSStefano Zampini   if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2681494a190aSStefano Zampini 
2682494a190aSStefano Zampini   PetscObjectOptionsBegin((PetscObject)snes);
2683494a190aSStefano Zampini   PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2684494a190aSStefano Zampini   PetscOptionsEnd();
2685494a190aSStefano Zampini 
2686494a190aSStefano Zampini   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2687494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2688494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2689494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2690494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Function -------------\n"));
2691494a190aSStefano Zampini   if (!complete_print && !directionsprinted) {
2692494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2693494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference function entries greater than <threshold>.\n"));
2694494a190aSStefano Zampini   }
2695494a190aSStefano Zampini   if (!directionsprinted) {
2696494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2697494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Function is probably correct.\n"));
2698494a190aSStefano Zampini     directionsprinted = PETSC_TRUE;
2699494a190aSStefano Zampini   }
2700494a190aSStefano Zampini   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2701494a190aSStefano Zampini 
2702494a190aSStefano Zampini   PetscCall(SNESGetSolution(snes, &x));
2703494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g1));
2704494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g2));
2705494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g3));
2706494a190aSStefano Zampini   PetscCall(SNESComputeFunction(snes, x, g1));
2707494a190aSStefano Zampini   PetscCall(SNESComputeFunction_FD(snes, x, g2));
2708494a190aSStefano Zampini 
2709494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2710494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2711494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2712494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2713494a190aSStefano Zampini   PetscCall(VecDot(g1, g2, &dot));
2714494a190aSStefano Zampini   PetscCall(VecCopy(g1, g3));
2715494a190aSStefano Zampini   PetscCall(VecAXPY(g3, -1.0, g2));
2716494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2717494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2718494a190aSStefano 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))));
2719494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2720494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2721494a190aSStefano Zampini 
2722494a190aSStefano Zampini   if (complete_print) {
2723494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded function ----------\n"));
2724494a190aSStefano Zampini     PetscCall(VecView(g1, mviewer));
2725494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference function ----------\n"));
2726494a190aSStefano Zampini     PetscCall(VecView(g2, mviewer));
2727494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference function ----------\n"));
2728494a190aSStefano Zampini     PetscCall(VecView(g3, mviewer));
2729494a190aSStefano Zampini   }
2730494a190aSStefano Zampini   PetscCall(VecDestroy(&g1));
2731494a190aSStefano Zampini   PetscCall(VecDestroy(&g2));
2732494a190aSStefano Zampini   PetscCall(VecDestroy(&g3));
2733494a190aSStefano Zampini 
2734494a190aSStefano Zampini   if (complete_print) {
2735494a190aSStefano Zampini     PetscCall(PetscViewerPopFormat(mviewer));
2736494a190aSStefano Zampini     PetscCall(PetscViewerDestroy(&mviewer));
2737494a190aSStefano Zampini   }
2738494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2739494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2740494a190aSStefano Zampini }
2741494a190aSStefano Zampini 
2742cbf8f02cSMatthew G. Knepley /*@
2743cbf8f02cSMatthew G. Knepley   SNESTestJacobian - Computes the difference between the computed and finite-difference Jacobians
2744cbf8f02cSMatthew G. Knepley 
2745cbf8f02cSMatthew G. Knepley   Collective
2746cbf8f02cSMatthew G. Knepley 
2747d5bfe6baSJose E. Roman   Input Parameter:
2748cbf8f02cSMatthew G. Knepley . snes - the `SNES` context
2749cbf8f02cSMatthew G. Knepley 
2750cbf8f02cSMatthew G. Knepley   Output Parameters:
27511dfd7622SMatthew Knepley + Jnorm    - the Frobenius norm of the computed Jacobian, or `NULL`
27521dfd7622SMatthew Knepley - diffNorm - the Frobenius norm of the difference of the computed and finite-difference Jacobians, or `NULL`
2753cbf8f02cSMatthew G. Knepley 
2754cbf8f02cSMatthew G. Knepley   Options Database Keys:
2755cbf8f02cSMatthew 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.
2756cbf8f02cSMatthew G. Knepley - -snes_test_jacobian_view                 - display the user provided Jacobian, the finite difference Jacobian and the difference
2757cbf8f02cSMatthew G. Knepley 
2758cbf8f02cSMatthew G. Knepley   Level: developer
2759cbf8f02cSMatthew G. Knepley 
27601dfd7622SMatthew Knepley   Note:
27611dfd7622SMatthew Knepley   Directions and norms are printed to stdout if `diffNorm` is `NULL`.
27621dfd7622SMatthew Knepley 
27631dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestFunction()`, `SNESSetJacobian()`, `SNESComputeJacobian()`
2764cbf8f02cSMatthew G. Knepley @*/
2765cbf8f02cSMatthew G. Knepley PetscErrorCode SNESTestJacobian(SNES snes, PetscReal *Jnorm, PetscReal *diffNorm)
2766d71ae5a4SJacob Faibussowitsch {
276712837594SBarry Smith   Mat               A, B, C, D, jacobian;
27684df93895SStefano Zampini   Vec               x = snes->vec_sol, f;
2769e885f1abSBarry Smith   PetscReal         nrm, gnorm;
277081e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
27710e276705SLisandro Dalcin   MatType           mattype;
2772e885f1abSBarry Smith   PetscInt          m, n, M, N;
2773e885f1abSBarry Smith   void             *functx;
27741dfd7622SMatthew Knepley   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, flg, istranspose;
27751dfd7622SMatthew Knepley   PetscBool         silent = diffNorm != PETSC_NULLPTR ? PETSC_TRUE : PETSC_FALSE;
27763325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2777e885f1abSBarry Smith   MPI_Comm          comm;
2778e885f1abSBarry Smith   PetscInt          tabs;
277912837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
27803325ff46SBarry Smith   PetscViewerFormat format;
2781e885f1abSBarry Smith 
2782e885f1abSBarry Smith   PetscFunctionBegin;
2783d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
27849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
27859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
27864ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
27879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
27889566063dSJacob 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));
2789d0609cedSBarry Smith   PetscOptionsEnd();
2790e885f1abSBarry Smith 
27919566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
27929566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
27939566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
27949566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
27951dfd7622SMatthew Knepley   if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
27961dfd7622SMatthew Knepley   if (!complete_print && !silent && !directionsprinted) {
27979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
27989566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
279912837594SBarry Smith   }
28001dfd7622SMatthew Knepley   if (!directionsprinted && !silent) {
28019566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
28029566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
280312837594SBarry Smith     directionsprinted = PETSC_TRUE;
2804e885f1abSBarry Smith   }
28051baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2806e885f1abSBarry Smith 
28079566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
280812837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
280912837594SBarry Smith   else jacobian = snes->jacobian_pre;
281012837594SBarry Smith 
28114df93895SStefano Zampini   if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
28124df93895SStefano Zampini   else PetscCall(PetscObjectReference((PetscObject)x));
28139566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &f));
28144df93895SStefano Zampini 
2815a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
28169566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
28179566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
28189566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
281912837594SBarry Smith   while (jacobian) {
28202cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
28212cd624f9SStefano Zampini 
28222cd624f9SStefano Zampini     if (istranspose) {
28239566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
28242cd624f9SStefano Zampini       Jsave    = jacobian;
28252cd624f9SStefano Zampini       jacobian = JT;
28262cd624f9SStefano Zampini     }
28279566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
282812837594SBarry Smith     if (flg) {
282912837594SBarry Smith       A = jacobian;
28309566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
283112837594SBarry Smith     } else {
28329566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
283312837594SBarry Smith     }
2834e885f1abSBarry Smith 
28359566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
28369566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
28379566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
28389566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
28399566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
28409566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
28419566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
28429566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
28439566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2844e885f1abSBarry Smith 
28459566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
28469566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
284712837594SBarry Smith 
28489566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
28499566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28509566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
28519566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
28529566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
285312837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
28541dfd7622SMatthew Knepley     if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
2855e885f1abSBarry Smith     if (complete_print) {
28569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
28579566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
28589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
28599566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2860e885f1abSBarry Smith     }
2861e885f1abSBarry Smith 
2862df10fb39SFande Kong     if (threshold_print || complete_print) {
2863e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2864e885f1abSBarry Smith       PetscScalar       *cvals;
2865e885f1abSBarry Smith       const PetscInt    *bcols;
2866e885f1abSBarry Smith       const PetscScalar *bvals;
2867e885f1abSBarry Smith 
28689566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
28699566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
28709566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
28719566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
28729566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
28739566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
28740e276705SLisandro Dalcin 
28759566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28769566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2877e885f1abSBarry Smith 
2878e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
28799566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
28809566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2881e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
288223a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2883e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2884e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2885e885f1abSBarry Smith             cncols += 1;
2886e885f1abSBarry Smith           }
2887e885f1abSBarry Smith         }
288848a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
28899566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
28909566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2891e885f1abSBarry Smith       }
28929566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
28939566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
28949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
28959566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
28969566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2897e885f1abSBarry Smith     }
28989566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
28999566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
29009566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
29012cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
290212837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
290312837594SBarry Smith       jacobian = snes->jacobian_pre;
29041dfd7622SMatthew Knepley       if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
29059371c9d4SSatish Balay     } else jacobian = NULL;
290612837594SBarry Smith   }
29079566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
29081baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2909648c30bcSBarry Smith   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
29109566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2911cbf8f02cSMatthew G. Knepley 
2912cbf8f02cSMatthew G. Knepley   if (Jnorm) *Jnorm = gnorm;
2913cbf8f02cSMatthew G. Knepley   if (diffNorm) *diffNorm = nrm;
29143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2915e885f1abSBarry Smith }
2916e885f1abSBarry Smith 
291762fef451SLois Curfman McInnes /*@
2918f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
291962fef451SLois Curfman McInnes 
2920c3339decSBarry Smith   Collective
2921c7afd0dbSLois Curfman McInnes 
292262fef451SLois Curfman McInnes   Input Parameters:
2923f6dfbefdSBarry Smith + snes - the `SNES` context
2924e4094ef1SJacob Faibussowitsch - X    - input vector
292562fef451SLois Curfman McInnes 
292662fef451SLois Curfman McInnes   Output Parameters:
2927c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2928420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2929fee21e36SBarry Smith 
2930e35cf81dSBarry Smith   Options Database Keys:
293167b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
293267b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2933455a5933SJed 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.
2934455a5933SJed 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
2935693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2936693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2937693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
29387addb90fSBarry Smith . -snes_compare_operator                   - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner
293994d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2940a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2941c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2942dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2943dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2944a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2945a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2946c01495d3SJed Brown 
2947dc4c0fb0SBarry Smith   Level: developer
2948dc4c0fb0SBarry Smith 
2949f6dfbefdSBarry Smith   Note:
295062fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
295162fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
295262fef451SLois Curfman McInnes 
2953420bcc1bSBarry Smith   Developer Note:
2954dc4c0fb0SBarry 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
2955420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2956e885f1abSBarry Smith 
29571cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
295862fef451SLois Curfman McInnes @*/
2959d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2960d71ae5a4SJacob Faibussowitsch {
2961ace3abfcSBarry Smith   PetscBool flag;
29626cab3a1bSJed Brown   DM        dm;
2963942e3340SBarry Smith   DMSNES    sdm;
2964e0e3a89bSBarry Smith   KSP       ksp;
29653a40ed3dSBarry Smith 
29663a40ed3dSBarry Smith   PetscFunctionBegin;
29670700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
29680700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2969c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2970e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
29719566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
29729566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
29733232da50SPeter Brune 
297401c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2975fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2976fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2977f5af7f23SKarl Rupp 
29789566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2979fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
29809566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
29819566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2982ebd3b9afSBarry Smith     if (flag) {
29839566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29849566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2985ebd3b9afSBarry Smith     }
29863ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
298737ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
298863a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
29899566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2990ebd3b9afSBarry Smith     if (flag) {
29919566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29929566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2993ebd3b9afSBarry Smith     }
29943ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2995e35cf81dSBarry Smith   }
2996efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
29979566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29989566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
29993ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3000d728fb7dSPeter Brune   }
3001e35cf81dSBarry Smith 
30029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
30039566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
3004800f99ffSJeremy L Thompson   {
3005800f99ffSJeremy L Thompson     void           *ctx;
30068434afd1SBarry Smith     SNESJacobianFn *J;
3007800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
3008800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
3009800f99ffSJeremy L Thompson   }
30109566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
30119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
301228d58a37SPierre Jolivet 
30137addb90fSBarry Smith   /* attach latest linearization point to the matrix used to construct the preconditioner */
30149566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
3015a8054027SBarry Smith 
3016e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
30179566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
30183b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
30199566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
30209566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
30213b4f5425SBarry Smith     snes->lagpreconditioner = -1;
30223b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
30239566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
30249566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
302537ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
302663a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
30279566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
3028d1e9a80fSBarry Smith   } else {
30299566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
30309566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
3031a8054027SBarry Smith   }
3032a8054027SBarry Smith 
30334df93895SStefano Zampini   /* monkey business to allow testing Jacobians in multilevel solvers.
30344df93895SStefano Zampini      This is needed because the SNESTestXXX interface does not accept vectors and matrices */
30354df93895SStefano Zampini   {
30364df93895SStefano Zampini     Vec xsave            = snes->vec_sol;
30374df93895SStefano Zampini     Mat jacobiansave     = snes->jacobian;
30384df93895SStefano Zampini     Mat jacobian_presave = snes->jacobian_pre;
30394df93895SStefano Zampini 
30404df93895SStefano Zampini     snes->vec_sol      = X;
30414df93895SStefano Zampini     snes->jacobian     = A;
30424df93895SStefano Zampini     snes->jacobian_pre = B;
30431dfd7622SMatthew Knepley     if (snes->testFunc) PetscCall(SNESTestFunction(snes));
30441dfd7622SMatthew Knepley     if (snes->testJac) PetscCall(SNESTestJacobian(snes, NULL, NULL));
3045494a190aSStefano Zampini 
30464df93895SStefano Zampini     snes->vec_sol      = xsave;
30474df93895SStefano Zampini     snes->jacobian     = jacobiansave;
30484df93895SStefano Zampini     snes->jacobian_pre = jacobian_presave;
30494df93895SStefano Zampini   }
30504df93895SStefano Zampini 
3051693365a8SJed Brown   {
3052693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
3053648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
3054648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
3055648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
3056648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
3057693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
30580298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
3059693365a8SJed Brown       PetscViewer vdraw, vstdout;
30606b3a5b13SJed Brown       PetscBool   flg;
3061693365a8SJed Brown       if (flag_operator) {
30629566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
3063693365a8SJed Brown         Bexp = Bexp_mine;
3064693365a8SJed Brown       } else {
30657addb90fSBarry Smith         /* See if the matrix used to construct the preconditioner can be viewed and added directly */
30669566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
306794ab13aaSBarry Smith         if (flg) Bexp = B;
3068693365a8SJed Brown         else {
3069693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
30709566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
3071693365a8SJed Brown           Bexp = Bexp_mine;
3072693365a8SJed Brown         }
3073693365a8SJed Brown       }
30749566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
30759566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
30769566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
3077693365a8SJed Brown       if (flag_draw || flag_contour) {
30789566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30799566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30800298fd71SBarry Smith       } else vdraw = NULL;
30819566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
30829566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
30839566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
30849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
30859566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
30869566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
30879566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
30889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
30899566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
3090693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
30919566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30929566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
30939566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
3094693365a8SJed Brown       }
30959566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30969566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
30979566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
30989566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
3099693365a8SJed Brown     }
3100693365a8SJed Brown   }
31014c30e9fbSJed Brown   {
31026719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
31036719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
3104648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
3105648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
3106648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
3107648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
3108648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
310927b0f280SBarry Smith     if (flag_threshold) {
31109566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
31119566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
311227b0f280SBarry Smith     }
31136719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
31144c30e9fbSJed Brown       Mat             Bfd;
31154c30e9fbSJed Brown       PetscViewer     vdraw, vstdout;
3116335efc43SPeter Brune       MatColoring     coloring;
31174c30e9fbSJed Brown       ISColoring      iscoloring;
31184c30e9fbSJed Brown       MatFDColoring   matfdcoloring;
31198434afd1SBarry Smith       SNESFunctionFn *func;
31204c30e9fbSJed Brown       void           *funcctx;
31216719d8e4SJed Brown       PetscReal       norm1, norm2, normmax;
31224c30e9fbSJed Brown 
31239566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
31249566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
31259566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
31269566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
31279566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
31289566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
31299566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
31309566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
31319566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
31329566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
31334c30e9fbSJed Brown 
31344c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
31359566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
31362ba42892SBarry Smith       PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)func, funcctx));
31379566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
31389566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
31399566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
31409566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
31419566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
31424c30e9fbSJed Brown 
31439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
31444c30e9fbSJed Brown       if (flag_draw || flag_contour) {
31459566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
31469566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31470298fd71SBarry Smith       } else vdraw = NULL;
31489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
31499566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
31509566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
31519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
31529566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31539566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
31549566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
31559566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
31569566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
31579566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
31589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
31599566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31604c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
31619566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31629566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
31639566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
31644c30e9fbSJed Brown       }
31659566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
31666719d8e4SJed Brown 
31676719d8e4SJed Brown       if (flag_threshold) {
31686719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
31699566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
31709566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
31716719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
31726719d8e4SJed Brown           const PetscScalar *ba, *ca;
31736719d8e4SJed Brown           const PetscInt    *bj, *cj;
31746719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
31756719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
31769566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
31779566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
31785f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
31796719d8e4SJed Brown           for (j = 0; j < bn; j++) {
31806719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
31816719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
31826719d8e4SJed Brown               maxentrycol = bj[j];
31836719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
31846719d8e4SJed Brown             }
31856719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
31866719d8e4SJed Brown               maxdiffcol = bj[j];
31876719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
31886719d8e4SJed Brown             }
31896719d8e4SJed Brown             if (rdiff > maxrdiff) {
31906719d8e4SJed Brown               maxrdiffcol = bj[j];
31916719d8e4SJed Brown               maxrdiff    = rdiff;
31926719d8e4SJed Brown             }
31936719d8e4SJed Brown           }
31946719d8e4SJed Brown           if (maxrdiff > 1) {
319563a3b9bcSJacob 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));
31966719d8e4SJed Brown             for (j = 0; j < bn; j++) {
31976719d8e4SJed Brown               PetscReal rdiff;
31986719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
319948a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
32006719d8e4SJed Brown             }
320163a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
32026719d8e4SJed Brown           }
32039566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
32049566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
32056719d8e4SJed Brown         }
32066719d8e4SJed Brown       }
32079566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
32089566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
32094c30e9fbSJed Brown     }
32104c30e9fbSJed Brown   }
32113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32129b94acceSBarry Smith }
32139b94acceSBarry Smith 
32149b94acceSBarry Smith /*@C
32159b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3216044dda88SLois Curfman McInnes   location to store the matrix.
32179b94acceSBarry Smith 
3218c3339decSBarry Smith   Logically Collective
3219c7afd0dbSLois Curfman McInnes 
32209b94acceSBarry Smith   Input Parameters:
3221f6dfbefdSBarry Smith + snes - the `SNES` context
3222e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3223dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
32248434afd1SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3225c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3226dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3227dc4c0fb0SBarry Smith 
3228dc4c0fb0SBarry Smith   Level: beginner
32299b94acceSBarry Smith 
32309b94acceSBarry Smith   Notes:
3231dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
323216913363SBarry Smith   each matrix.
323316913363SBarry Smith 
3234dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3235dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3236895c21f2SBarry Smith 
3237dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3238f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3239a8a26c1eSJed Brown 
3240c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3241f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3242c3cc8fd1SJed Brown 
32431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
32448434afd1SBarry Smith           `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
32459b94acceSBarry Smith @*/
32468434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
3247d71ae5a4SJacob Faibussowitsch {
32486cab3a1bSJed Brown   DM dm;
32493a7fca6bSBarry Smith 
32503a40ed3dSBarry Smith   PetscFunctionBegin;
32510700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3252e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3253e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3254e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3255e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
32569566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32579566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3258e5d3d808SBarry Smith   if (Amat) {
32599566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
32609566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3261f5af7f23SKarl Rupp 
3262e5d3d808SBarry Smith     snes->jacobian = Amat;
32633a7fca6bSBarry Smith   }
3264e5d3d808SBarry Smith   if (Pmat) {
32659566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
32669566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3267f5af7f23SKarl Rupp 
3268e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
32693a7fca6bSBarry Smith   }
32703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32719b94acceSBarry Smith }
327262fef451SLois Curfman McInnes 
3273c2aafc4cSSatish Balay /*@C
3274b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3275b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3276b4fd4287SBarry Smith 
3277420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3278c7afd0dbSLois Curfman McInnes 
3279b4fd4287SBarry Smith   Input Parameter:
3280b4fd4287SBarry Smith . snes - the nonlinear solver context
3281b4fd4287SBarry Smith 
3282b4fd4287SBarry Smith   Output Parameters:
3283dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3284dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
32858434afd1SBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3286dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3287fee21e36SBarry Smith 
328836851e7fSLois Curfman McInnes   Level: advanced
328936851e7fSLois Curfman McInnes 
32908434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3291b4fd4287SBarry Smith @*/
32928434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
3293d71ae5a4SJacob Faibussowitsch {
32946cab3a1bSJed Brown   DM dm;
32956cab3a1bSJed Brown 
32963a40ed3dSBarry Smith   PetscFunctionBegin;
32970700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3298e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3299e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
33009566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3301800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
33023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3303b4fd4287SBarry Smith }
3304b4fd4287SBarry Smith 
3305d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3306d71ae5a4SJacob Faibussowitsch {
330758b371f3SBarry Smith   DM     dm;
330858b371f3SBarry Smith   DMSNES sdm;
330958b371f3SBarry Smith 
331058b371f3SBarry Smith   PetscFunctionBegin;
33119566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
33129566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
331358b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
331458b371f3SBarry Smith     DM        dm;
331558b371f3SBarry Smith     PetscBool isdense, ismf;
331658b371f3SBarry Smith 
33179566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
33189566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
33199566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
332058b371f3SBarry Smith     if (isdense) {
33219566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
332258b371f3SBarry Smith     } else if (!ismf) {
33239566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
332458b371f3SBarry Smith     }
332558b371f3SBarry Smith   }
33263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
332758b371f3SBarry Smith }
332858b371f3SBarry Smith 
33299b94acceSBarry Smith /*@
33309b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
33310b4b7b1cSBarry Smith   of a nonlinear solver `SNESSolve()`.
33329b94acceSBarry Smith 
3333c3339decSBarry Smith   Collective
3334fee21e36SBarry Smith 
33352fe279fdSBarry Smith   Input Parameter:
3336f6dfbefdSBarry Smith . snes - the `SNES` context
3337c7afd0dbSLois Curfman McInnes 
3338dc4c0fb0SBarry Smith   Level: advanced
3339dc4c0fb0SBarry Smith 
3340f6dfbefdSBarry Smith   Note:
33410b4b7b1cSBarry Smith   For basic use of the `SNES` solvers the user does not need to explicitly call
3342f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3343f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3344f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3345f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3346272ac6f2SLois Curfman McInnes 
33470b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()`
33489b94acceSBarry Smith @*/
3349d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3350d71ae5a4SJacob Faibussowitsch {
33516cab3a1bSJed Brown   DM             dm;
3352942e3340SBarry Smith   DMSNES         sdm;
3353c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
33546e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
33559b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
33569b5c1c08SStefano Zampini   Vec            f, fpc;
33579b5c1c08SStefano Zampini   void          *funcctx;
33589b5c1c08SStefano Zampini   void          *jacctx, *appctx;
33599b5c1c08SStefano Zampini   Mat            j, jpre;
33606b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
33616b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
33628434afd1SBarry Smith   SNESFunctionFn *func;
33638434afd1SBarry Smith   SNESJacobianFn *jac;
33643a40ed3dSBarry Smith 
33653a40ed3dSBarry Smith   PetscFunctionBegin;
33660700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33673ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3368fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
33699b94acceSBarry Smith 
337048a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
337185385478SLisandro Dalcin 
33729566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
337358c9b817SLisandro Dalcin 
33749566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
33759566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
33769566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
337758b371f3SBarry Smith 
337848a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3379efd51863SBarry Smith 
338048a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3381b710008aSBarry Smith 
3382d8d34be6SBarry Smith   if (snes->linesearch) {
33839566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
33849566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3385d8d34be6SBarry Smith   }
33869e764e56SPeter Brune 
33879b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3388b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3389172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3390172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3391172a4300SPeter Brune   }
3392d8f46077SPeter Brune 
3393efd4aadfSBarry Smith   if (snes->npc) {
33946e2a1849SPeter Brune     /* copy the DM over */
33959566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
33969566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
33976e2a1849SPeter Brune 
33989566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
33999566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
34009566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
34019566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
34029566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
34039566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
34049566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
34059b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
34069566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
34076e2a1849SPeter Brune 
34086e2a1849SPeter Brune     /* copy the function pointers over */
34099566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
34106e2a1849SPeter Brune 
34116e2a1849SPeter Brune     /* default to 1 iteration */
34129566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3413efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
34149566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3415a9936a0cSPeter Brune     } else {
34169566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3417a9936a0cSPeter Brune     }
34189566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
34196e2a1849SPeter Brune 
34206e2a1849SPeter Brune     /* copy the line search context over */
3421d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
34229566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
34239566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
34249566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
34259566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
34269566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
34279566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
34289566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
34296e2a1849SPeter Brune     }
3430d8d34be6SBarry Smith   }
34311baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
3432835f2295SStefano Zampini   if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx));
34336e2a1849SPeter Brune 
343437ec4e1aSPeter Brune   snes->jac_iter = 0;
343537ec4e1aSPeter Brune   snes->pre_iter = 0;
343637ec4e1aSPeter Brune 
3437dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
343858c9b817SLisandro Dalcin 
34399566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
344058b371f3SBarry Smith 
3441b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
34426c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3443d8d34be6SBarry Smith       if (snes->linesearch) {
34449566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
34459566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
34466c67d002SPeter Brune       }
34476c67d002SPeter Brune     }
3448d8d34be6SBarry Smith   }
3449fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
34507aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
34513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34529b94acceSBarry Smith }
34539b94acceSBarry Smith 
345437596af1SLisandro Dalcin /*@
34550b4b7b1cSBarry 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
345637596af1SLisandro Dalcin 
3457c3339decSBarry Smith   Collective
345837596af1SLisandro Dalcin 
345937596af1SLisandro Dalcin   Input Parameter:
34600b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
346137596af1SLisandro Dalcin 
3462d25893d9SBarry Smith   Level: intermediate
3463d25893d9SBarry Smith 
346495452b02SPatrick Sanan   Notes:
34650b4b7b1cSBarry Smith   Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain.
34660b4b7b1cSBarry Smith 
3467f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
346837596af1SLisandro Dalcin 
3469f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3470f6dfbefdSBarry Smith 
34711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
347237596af1SLisandro Dalcin @*/
3473d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3474d71ae5a4SJacob Faibussowitsch {
347537596af1SLisandro Dalcin   PetscFunctionBegin;
347637596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
347749abdd8aSBarry Smith   if (snes->ops->ctxdestroy && snes->ctx) {
3478835f2295SStefano Zampini     PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx));
347949abdd8aSBarry Smith     snes->ctx = NULL;
3480d25893d9SBarry Smith   }
34811baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
34828a23116dSBarry Smith 
3483dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
34841baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
34859e764e56SPeter Brune 
34861baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
34879e764e56SPeter Brune 
34889566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
34899566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
34909566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
34919566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
34929566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
34939566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
34949566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
34959566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
34969566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3497f5af7f23SKarl Rupp 
349840fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
349940fdac6aSLawrence Mitchell 
350037596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
350137596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
35023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
350337596af1SLisandro Dalcin }
350437596af1SLisandro Dalcin 
350552baeb72SSatish Balay /*@
350636d43d94SBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also
350736d43d94SBarry Smith   removes the default viewer.
3508c4421ceaSFande Kong 
3509c3339decSBarry Smith   Collective
3510c4421ceaSFande Kong 
3511c4421ceaSFande Kong   Input Parameter:
35120b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
3513c4421ceaSFande Kong 
3514c4421ceaSFande Kong   Level: intermediate
3515c4421ceaSFande Kong 
3516420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3517c4421ceaSFande Kong @*/
3518d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3519d71ae5a4SJacob Faibussowitsch {
3520c4421ceaSFande Kong   PetscInt i;
3521c4421ceaSFande Kong 
3522c4421ceaSFande Kong   PetscFunctionBegin;
3523c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3524c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
352548a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3526c4421ceaSFande Kong   }
3527c4421ceaSFande Kong   snes->numberreasonviews = 0;
3528648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
35293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3530c4421ceaSFande Kong }
3531c4421ceaSFande Kong 
35320764c050SBarry Smith /*@
35339b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3534f6dfbefdSBarry Smith   with `SNESCreate()`.
35359b94acceSBarry Smith 
3536c3339decSBarry Smith   Collective
3537c7afd0dbSLois Curfman McInnes 
35389b94acceSBarry Smith   Input Parameter:
3539f6dfbefdSBarry Smith . snes - the `SNES` context
35409b94acceSBarry Smith 
354136851e7fSLois Curfman McInnes   Level: beginner
354236851e7fSLois Curfman McInnes 
35431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
35449b94acceSBarry Smith @*/
3545d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3546d71ae5a4SJacob Faibussowitsch {
354792e852f7SPablo Brubeck   DM dm;
354892e852f7SPablo Brubeck 
35493a40ed3dSBarry Smith   PetscFunctionBegin;
35503ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3551f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3552f4f49eeaSPierre Jolivet   if (--((PetscObject)*snes)->refct > 0) {
35539371c9d4SSatish Balay     *snes = NULL;
35543ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
35559371c9d4SSatish Balay   }
3556d4bb536fSBarry Smith 
3557f4f49eeaSPierre Jolivet   PetscCall(SNESReset(*snes));
35589566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
35596b8b9a38SLisandro Dalcin 
3560e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
35619566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3562f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*snes, destroy);
35636d4c513bSLisandro Dalcin 
356492e852f7SPablo Brubeck   dm = (*snes)->dm;
356592e852f7SPablo Brubeck   while (dm) {
356692e852f7SPablo Brubeck     PetscCall(DMCoarsenHookRemove(dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
356792e852f7SPablo Brubeck     PetscCall(DMGetCoarseDM(dm, &dm));
356892e852f7SPablo Brubeck   }
356992e852f7SPablo Brubeck 
35709566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
35719566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
35729566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
35736b8b9a38SLisandro Dalcin 
35749566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
3575*12651944SBarry Smith   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)(&(*snes)->cnvP));
357648a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3577f4f49eeaSPierre Jolivet   PetscCall(SNESMonitorCancel(*snes));
3578f4f49eeaSPierre Jolivet   PetscCall(SNESConvergedReasonViewCancel(*snes));
35799566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
35803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35819b94acceSBarry Smith }
35829b94acceSBarry Smith 
35839b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
35849b94acceSBarry Smith 
3585a8054027SBarry Smith /*@
35860b4b7b1cSBarry Smith   SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`.
3587a8054027SBarry Smith 
3588c3339decSBarry Smith   Logically Collective
3589a8054027SBarry Smith 
3590a8054027SBarry Smith   Input Parameters:
3591f6dfbefdSBarry Smith + snes - the `SNES` context
3592d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
35933b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3594a8054027SBarry Smith 
3595a8054027SBarry Smith   Options Database Keys:
3596420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
35973d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3598420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
35993d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3600a8054027SBarry Smith 
3601dc4c0fb0SBarry Smith   Level: intermediate
3602dc4c0fb0SBarry Smith 
3603420bcc1bSBarry Smith   Notes:
3604a8054027SBarry Smith   The default is 1
3605420bcc1bSBarry Smith 
3606f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3607d8e291bfSBarry Smith 
3608f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3609a8054027SBarry Smith 
36103201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3611f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3612a8054027SBarry Smith @*/
3613d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3614d71ae5a4SJacob Faibussowitsch {
3615a8054027SBarry Smith   PetscFunctionBegin;
36160700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
36175f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
36185f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3619c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3620a8054027SBarry Smith   snes->lagpreconditioner = lag;
36213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3622a8054027SBarry Smith }
3623a8054027SBarry Smith 
3624efd51863SBarry Smith /*@
3625f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3626efd51863SBarry Smith 
3627c3339decSBarry Smith   Logically Collective
3628efd51863SBarry Smith 
3629efd51863SBarry Smith   Input Parameters:
3630f6dfbefdSBarry Smith + snes  - the `SNES` context
3631efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3632efd51863SBarry Smith 
3633f6dfbefdSBarry Smith   Options Database Key:
363467b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3635efd51863SBarry Smith 
3636efd51863SBarry Smith   Level: intermediate
3637efd51863SBarry Smith 
36380b4b7b1cSBarry Smith   Notes:
36390b4b7b1cSBarry Smith   Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement.
36400b4b7b1cSBarry Smith 
3641f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3642c0df2a02SJed Brown 
36433201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
364454c05997SPierre Jolivet           `SNESSetDM()`, `SNESSolve()`
3645efd51863SBarry Smith @*/
3646d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3647d71ae5a4SJacob Faibussowitsch {
3648efd51863SBarry Smith   PetscFunctionBegin;
3649efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3650efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3651efd51863SBarry Smith   snes->gridsequence = steps;
36523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3653efd51863SBarry Smith }
3654efd51863SBarry Smith 
3655fa19ca70SBarry Smith /*@
3656f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3657fa19ca70SBarry Smith 
3658c3339decSBarry Smith   Logically Collective
3659fa19ca70SBarry Smith 
3660fa19ca70SBarry Smith   Input Parameter:
3661f6dfbefdSBarry Smith . snes - the `SNES` context
3662fa19ca70SBarry Smith 
3663fa19ca70SBarry Smith   Output Parameter:
3664fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3665fa19ca70SBarry Smith 
3666fa19ca70SBarry Smith   Level: intermediate
3667fa19ca70SBarry Smith 
36683201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3669fa19ca70SBarry Smith @*/
3670d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3671d71ae5a4SJacob Faibussowitsch {
3672fa19ca70SBarry Smith   PetscFunctionBegin;
3673fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3674fa19ca70SBarry Smith   *steps = snes->gridsequence;
36753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3676fa19ca70SBarry Smith }
3677fa19ca70SBarry Smith 
3678a8054027SBarry Smith /*@
3679f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3680a8054027SBarry Smith 
36813f9fe445SBarry Smith   Not Collective
3682a8054027SBarry Smith 
3683a8054027SBarry Smith   Input Parameter:
3684f6dfbefdSBarry Smith . snes - the `SNES` context
3685a8054027SBarry Smith 
3686a8054027SBarry Smith   Output Parameter:
3687a8054027SBarry 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
36883b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3689a8054027SBarry Smith 
3690dc4c0fb0SBarry Smith   Level: intermediate
3691dc4c0fb0SBarry Smith 
3692a8054027SBarry Smith   Notes:
3693a8054027SBarry Smith   The default is 1
3694f6dfbefdSBarry Smith 
3695a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3696a8054027SBarry Smith 
36973201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3698a8054027SBarry Smith @*/
3699d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3700d71ae5a4SJacob Faibussowitsch {
3701a8054027SBarry Smith   PetscFunctionBegin;
37020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3703a8054027SBarry Smith   *lag = snes->lagpreconditioner;
37043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3705a8054027SBarry Smith }
3706a8054027SBarry Smith 
3707e35cf81dSBarry Smith /*@
3708f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3709e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3710e35cf81dSBarry Smith 
3711c3339decSBarry Smith   Logically Collective
3712e35cf81dSBarry Smith 
3713e35cf81dSBarry Smith   Input Parameters:
3714f6dfbefdSBarry Smith + snes - the `SNES` context
3715e35cf81dSBarry 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
3716fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3717e35cf81dSBarry Smith 
3718e35cf81dSBarry Smith   Options Database Keys:
371979a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37203d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
372179a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37223d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3723e35cf81dSBarry Smith 
3724dc4c0fb0SBarry Smith   Level: intermediate
3725dc4c0fb0SBarry Smith 
3726e35cf81dSBarry Smith   Notes:
3727e35cf81dSBarry Smith   The default is 1
3728f6dfbefdSBarry Smith 
3729e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3730f6dfbefdSBarry Smith 
3731fe3ffe1eSBarry 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
3732fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3733e35cf81dSBarry Smith 
37343201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3735e35cf81dSBarry Smith @*/
3736d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3737d71ae5a4SJacob Faibussowitsch {
3738e35cf81dSBarry Smith   PetscFunctionBegin;
37390700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
37405f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
37415f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3742c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3743e35cf81dSBarry Smith   snes->lagjacobian = lag;
37443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3745e35cf81dSBarry Smith }
3746e35cf81dSBarry Smith 
3747e35cf81dSBarry Smith /*@
3748f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3749e35cf81dSBarry Smith 
37503f9fe445SBarry Smith   Not Collective
3751e35cf81dSBarry Smith 
3752e35cf81dSBarry Smith   Input Parameter:
3753f6dfbefdSBarry Smith . snes - the `SNES` context
3754e35cf81dSBarry Smith 
3755e35cf81dSBarry Smith   Output Parameter:
3756e35cf81dSBarry 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
3757e35cf81dSBarry Smith          the Jacobian is built etc.
3758e35cf81dSBarry Smith 
3759dc4c0fb0SBarry Smith   Level: intermediate
3760dc4c0fb0SBarry Smith 
3761e35cf81dSBarry Smith   Notes:
3762e35cf81dSBarry Smith   The default is 1
3763f6dfbefdSBarry Smith 
3764f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3765e35cf81dSBarry Smith 
37663201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3767e35cf81dSBarry Smith 
3768e35cf81dSBarry Smith @*/
3769d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3770d71ae5a4SJacob Faibussowitsch {
3771e35cf81dSBarry Smith   PetscFunctionBegin;
37720700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3773e35cf81dSBarry Smith   *lag = snes->lagjacobian;
37743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3775e35cf81dSBarry Smith }
3776e35cf81dSBarry Smith 
377737ec4e1aSPeter Brune /*@
3778f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
377937ec4e1aSPeter Brune 
3780c3339decSBarry Smith   Logically collective
378137ec4e1aSPeter Brune 
3782d8d19677SJose E. Roman   Input Parameters:
3783f6dfbefdSBarry Smith + snes - the `SNES` context
37849d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
378537ec4e1aSPeter Brune 
378637ec4e1aSPeter Brune   Options Database Keys:
378779a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37883d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
378979a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37903d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
37913d5a8a6aSBarry Smith 
3792dc4c0fb0SBarry Smith   Level: advanced
3793dc4c0fb0SBarry Smith 
379495452b02SPatrick Sanan   Notes:
3795420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3796f6dfbefdSBarry Smith 
379795452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
379837ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
379937ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
380037ec4e1aSPeter Brune 
380142747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
380237ec4e1aSPeter Brune @*/
3803d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3804d71ae5a4SJacob Faibussowitsch {
380537ec4e1aSPeter Brune   PetscFunctionBegin;
380637ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
380737ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
380837ec4e1aSPeter Brune   snes->lagjac_persist = flg;
38093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
381037ec4e1aSPeter Brune }
381137ec4e1aSPeter Brune 
381237ec4e1aSPeter Brune /*@
3813d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
381437ec4e1aSPeter Brune 
3815c3339decSBarry Smith   Logically Collective
381637ec4e1aSPeter Brune 
3817d8d19677SJose E. Roman   Input Parameters:
3818f6dfbefdSBarry Smith + snes - the `SNES` context
38199d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
382037ec4e1aSPeter Brune 
382137ec4e1aSPeter Brune   Options Database Keys:
382279a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
38233d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
382479a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
38253d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
382637ec4e1aSPeter Brune 
3827dc4c0fb0SBarry Smith   Level: developer
3828dc4c0fb0SBarry Smith 
382995452b02SPatrick Sanan   Notes:
3830420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3831f6dfbefdSBarry Smith 
383295452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
383337ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
383437ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
383537ec4e1aSPeter Brune 
38361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
383737ec4e1aSPeter Brune @*/
3838d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3839d71ae5a4SJacob Faibussowitsch {
384037ec4e1aSPeter Brune   PetscFunctionBegin;
384137ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
384237ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
384337ec4e1aSPeter Brune   snes->lagpre_persist = flg;
38443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
384537ec4e1aSPeter Brune }
384637ec4e1aSPeter Brune 
38479b94acceSBarry Smith /*@
3848f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3849be5caee7SBarry Smith 
3850c3339decSBarry Smith   Logically Collective
3851be5caee7SBarry Smith 
3852be5caee7SBarry Smith   Input Parameters:
3853f6dfbefdSBarry Smith + snes  - the `SNES` context
3854f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3855be5caee7SBarry Smith 
3856f6dfbefdSBarry Smith   Options Database Key:
3857be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3858be5caee7SBarry Smith 
3859dc4c0fb0SBarry Smith   Level: intermediate
3860dc4c0fb0SBarry Smith 
3861f6dfbefdSBarry Smith   Note:
3862f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3863be5caee7SBarry Smith 
38643201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()`
3865be5caee7SBarry Smith @*/
3866d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3867d71ae5a4SJacob Faibussowitsch {
3868be5caee7SBarry Smith   PetscFunctionBegin;
3869be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3870be5caee7SBarry Smith   snes->forceiteration = force;
38713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3872be5caee7SBarry Smith }
3873be5caee7SBarry Smith 
387485216dc7SFande Kong /*@
3875f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
387685216dc7SFande Kong 
3877c3339decSBarry Smith   Logically Collective
387885216dc7SFande Kong 
38792fe279fdSBarry Smith   Input Parameter:
3880f6dfbefdSBarry Smith . snes - the `SNES` context
388185216dc7SFande Kong 
388285216dc7SFande Kong   Output Parameter:
3883dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
388485216dc7SFande Kong 
388506dd6b0eSSatish Balay   Level: intermediate
388606dd6b0eSSatish Balay 
38873201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()`
388885216dc7SFande Kong @*/
3889d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3890d71ae5a4SJacob Faibussowitsch {
389185216dc7SFande Kong   PetscFunctionBegin;
389285216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
389385216dc7SFande Kong   *force = snes->forceiteration;
38943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
389585216dc7SFande Kong }
3896be5caee7SBarry Smith 
3897be5caee7SBarry Smith /*@
38980b4b7b1cSBarry Smith   SNESSetTolerances - Sets various parameters used in `SNES` convergence tests.
38999b94acceSBarry Smith 
3900c3339decSBarry Smith   Logically Collective
3901c7afd0dbSLois Curfman McInnes 
39029b94acceSBarry Smith   Input Parameters:
3903f6dfbefdSBarry Smith + snes   - the `SNES` context
39040b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $
39050b4b7b1cSBarry Smith . rtol   - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $
39065358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
39070b4b7b1cSBarry Smith . maxit  - the maximum number of iterations allowed in the solver, default 50.
39080b4b7b1cSBarry Smith - maxf   - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000
3909fee21e36SBarry Smith 
391033174efeSLois Curfman McInnes   Options Database Keys:
391177e5a1f9SBarry Smith + -snes_atol <abstol>    - Sets `abstol`
391277e5a1f9SBarry Smith . -snes_rtol <rtol>      - Sets `rtol`
391377e5a1f9SBarry Smith . -snes_stol <stol>      - Sets `stol`
391477e5a1f9SBarry Smith . -snes_max_it <maxit>   - Sets `maxit`
391577e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum)
39169b94acceSBarry Smith 
391736851e7fSLois Curfman McInnes   Level: intermediate
391836851e7fSLois Curfman McInnes 
391977e5a1f9SBarry Smith   Note:
392077e5a1f9SBarry Smith   All parameters must be non-negative
392177e5a1f9SBarry Smith 
392277e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`.
392377e5a1f9SBarry Smith   The default value is the value in the object when its type is set.
392477e5a1f9SBarry Smith 
392577e5a1f9SBarry Smith   Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations.
392677e5a1f9SBarry Smith 
392777e5a1f9SBarry Smith   Fortran Note:
392877e5a1f9SBarry Smith   Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL`
392977e5a1f9SBarry Smith 
39303201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
39319b94acceSBarry Smith @*/
3932d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3933d71ae5a4SJacob Faibussowitsch {
39343a40ed3dSBarry Smith   PetscFunctionBegin;
39350700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3936c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3937c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3938c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3939c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3940c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3941c5eb9154SBarry Smith 
394277e5a1f9SBarry Smith   if (abstol == (PetscReal)PETSC_DETERMINE) {
394377e5a1f9SBarry Smith     snes->abstol = snes->default_abstol;
394477e5a1f9SBarry Smith   } else if (abstol != (PetscReal)PETSC_CURRENT) {
39455f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3946ab54825eSJed Brown     snes->abstol = abstol;
3947ab54825eSJed Brown   }
394877e5a1f9SBarry Smith 
394977e5a1f9SBarry Smith   if (rtol == (PetscReal)PETSC_DETERMINE) {
395077e5a1f9SBarry Smith     snes->rtol = snes->default_rtol;
395177e5a1f9SBarry Smith   } else if (rtol != (PetscReal)PETSC_CURRENT) {
39525f80ce2aSJacob 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);
3953ab54825eSJed Brown     snes->rtol = rtol;
3954ab54825eSJed Brown   }
395577e5a1f9SBarry Smith 
395677e5a1f9SBarry Smith   if (stol == (PetscReal)PETSC_DETERMINE) {
395777e5a1f9SBarry Smith     snes->stol = snes->default_stol;
395877e5a1f9SBarry Smith   } else if (stol != (PetscReal)PETSC_CURRENT) {
39595f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3960c60f73f4SPeter Brune     snes->stol = stol;
3961ab54825eSJed Brown   }
396277e5a1f9SBarry Smith 
3963835f2295SStefano Zampini   if (maxit == PETSC_DETERMINE) {
396477e5a1f9SBarry Smith     snes->max_its = snes->default_max_its;
3965835f2295SStefano Zampini   } else if (maxit == PETSC_UNLIMITED) {
396677e5a1f9SBarry Smith     snes->max_its = PETSC_INT_MAX;
396777e5a1f9SBarry Smith   } else if (maxit != PETSC_CURRENT) {
396863a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3969ab54825eSJed Brown     snes->max_its = maxit;
3970ab54825eSJed Brown   }
397177e5a1f9SBarry Smith 
3972835f2295SStefano Zampini   if (maxf == PETSC_DETERMINE) {
397377e5a1f9SBarry Smith     snes->max_funcs = snes->default_max_funcs;
3974835f2295SStefano Zampini   } else if (maxf == PETSC_UNLIMITED || maxf == -1) {
397577e5a1f9SBarry Smith     snes->max_funcs = PETSC_UNLIMITED;
397677e5a1f9SBarry Smith   } else if (maxf != PETSC_CURRENT) {
397777e5a1f9SBarry Smith     PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf);
3978ab54825eSJed Brown     snes->max_funcs = maxf;
3979ab54825eSJed Brown   }
39803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39819b94acceSBarry Smith }
39829b94acceSBarry Smith 
3983e4d06f11SPatrick Farrell /*@
3984f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3985e4d06f11SPatrick Farrell 
3986c3339decSBarry Smith   Logically Collective
3987e4d06f11SPatrick Farrell 
3988e4d06f11SPatrick Farrell   Input Parameters:
3989f6dfbefdSBarry Smith + snes   - the `SNES` context
39900b4b7b1cSBarry 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
39910b4b7b1cSBarry Smith            is stopped due to divergence.
3992e4d06f11SPatrick Farrell 
3993f6dfbefdSBarry Smith   Options Database Key:
3994dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3995e4d06f11SPatrick Farrell 
3996e4d06f11SPatrick Farrell   Level: intermediate
3997e4d06f11SPatrick Farrell 
399877e5a1f9SBarry Smith   Notes:
399977e5a1f9SBarry Smith   Use `PETSC_DETERMINE` to use the default value from when the object's type was set.
4000e5cd489fSStefano Zampini 
400177e5a1f9SBarry Smith   Fortran Note:
400277e5a1f9SBarry Smith   Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL`
400377e5a1f9SBarry Smith 
400477e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()`
4005e4d06f11SPatrick Farrell @*/
4006d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
4007d71ae5a4SJacob Faibussowitsch {
4008e4d06f11SPatrick Farrell   PetscFunctionBegin;
4009e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4010e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
401177e5a1f9SBarry Smith 
401277e5a1f9SBarry Smith   if (divtol == (PetscReal)PETSC_DETERMINE) {
401377e5a1f9SBarry Smith     snes->divtol = snes->default_divtol;
401477e5a1f9SBarry Smith   } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) {
401577e5a1f9SBarry Smith     snes->divtol = PETSC_UNLIMITED;
401677e5a1f9SBarry Smith   } else if (divtol != (PetscReal)PETSC_CURRENT) {
401777e5a1f9SBarry Smith     PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol);
401877e5a1f9SBarry Smith     snes->divtol = divtol;
401977e5a1f9SBarry Smith   }
40203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4021e4d06f11SPatrick Farrell }
4022e4d06f11SPatrick Farrell 
40239b94acceSBarry Smith /*@
40240b4b7b1cSBarry Smith   SNESGetTolerances - Gets various parameters used in `SNES` convergence tests.
402533174efeSLois Curfman McInnes 
4026c7afd0dbSLois Curfman McInnes   Not Collective
4027c7afd0dbSLois Curfman McInnes 
402877e5a1f9SBarry Smith   Input Parameter:
402977e5a1f9SBarry Smith . snes - the `SNES` context
403077e5a1f9SBarry Smith 
403177e5a1f9SBarry Smith   Output Parameters:
40320b4b7b1cSBarry Smith + atol  - the absolute convergence tolerance
40330b4b7b1cSBarry Smith . rtol  - the relative convergence tolerance
403477e5a1f9SBarry Smith . stol  - convergence tolerance in terms of the norm of the change in the solution between steps
40350b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed
40360b4b7b1cSBarry Smith - maxf  - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound
4037fee21e36SBarry Smith 
403836851e7fSLois Curfman McInnes   Level: intermediate
403936851e7fSLois Curfman McInnes 
40400b4b7b1cSBarry Smith   Notes:
40410b4b7b1cSBarry Smith   See `SNESSetTolerances()` for details on the parameters.
40420b4b7b1cSBarry Smith 
4043dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
4044dc4c0fb0SBarry Smith 
40451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
404633174efeSLois Curfman McInnes @*/
4047d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
4048d71ae5a4SJacob Faibussowitsch {
40493a40ed3dSBarry Smith   PetscFunctionBegin;
40500700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
405185385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
405233174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
4053c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
405433174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
405533174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
40563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
405733174efeSLois Curfman McInnes }
405833174efeSLois Curfman McInnes 
4059e4d06f11SPatrick Farrell /*@
4060e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
4061e4d06f11SPatrick Farrell 
4062e4d06f11SPatrick Farrell   Not Collective
4063e4d06f11SPatrick Farrell 
4064e4d06f11SPatrick Farrell   Input Parameters:
4065f6dfbefdSBarry Smith + snes   - the `SNES` context
4066e4d06f11SPatrick Farrell - divtol - divergence tolerance
4067e4d06f11SPatrick Farrell 
4068e4d06f11SPatrick Farrell   Level: intermediate
4069e4d06f11SPatrick Farrell 
40701cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
4071e4d06f11SPatrick Farrell @*/
4072d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
4073d71ae5a4SJacob Faibussowitsch {
4074e4d06f11SPatrick Farrell   PetscFunctionBegin;
4075e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4076e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
40773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4078e4d06f11SPatrick Farrell }
4079e4d06f11SPatrick Farrell 
40806ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
40816ba87a44SLisandro Dalcin 
4082d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
4083d71ae5a4SJacob Faibussowitsch {
4084b271bb04SBarry Smith   PetscDrawLG      lg;
4085b271bb04SBarry Smith   PetscReal        x, y, per;
4086b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
4087b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
4088b271bb04SBarry Smith   PetscDraw        draw;
4089b271bb04SBarry Smith 
4090459f5d12SBarry Smith   PetscFunctionBegin;
40914d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
40929566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
40939566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40949566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40959566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
4096b271bb04SBarry Smith   x = (PetscReal)n;
409777b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
409894c9c6d3SKarl Rupp   else y = -15.0;
40999566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
41006934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41019566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41029566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4103b271bb04SBarry Smith   }
4104b271bb04SBarry Smith 
41059566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
41069566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
41079566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4108aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
41099566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
4110b271bb04SBarry Smith   x = (PetscReal)n;
4111b271bb04SBarry Smith   y = 100.0 * per;
41129566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
41136934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41149566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41159566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4116b271bb04SBarry Smith   }
4117b271bb04SBarry Smith 
41189566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
41199371c9d4SSatish Balay   if (!n) {
41209371c9d4SSatish Balay     prev = rnorm;
41219371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
41229371c9d4SSatish Balay   }
41239566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
41249566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
4125b271bb04SBarry Smith   x = (PetscReal)n;
4126b271bb04SBarry Smith   y = (prev - rnorm) / prev;
41279566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
41286934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41299566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41309566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4131b271bb04SBarry Smith   }
4132b271bb04SBarry Smith 
41339566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
41349566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
41359566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
41369566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
4137b271bb04SBarry Smith   x = (PetscReal)n;
4138b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
4139b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
41409566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4141b271bb04SBarry Smith   }
41426934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41439566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41449566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4145b271bb04SBarry Smith   }
4146b271bb04SBarry Smith   prev = rnorm;
41473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4148b271bb04SBarry Smith }
4149b271bb04SBarry Smith 
4150228d79bcSJed Brown /*@
41512d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
41522d157150SStefano Zampini 
41532d157150SStefano Zampini   Collective
41542d157150SStefano Zampini 
41552d157150SStefano Zampini   Input Parameters:
41562d157150SStefano Zampini + snes  - the `SNES` context
41572d157150SStefano Zampini . it    - current iteration
41582d157150SStefano Zampini . xnorm - 2-norm of current iterate
41592d157150SStefano Zampini . snorm - 2-norm of current step
41602d157150SStefano Zampini - fnorm - 2-norm of function
41612d157150SStefano Zampini 
41622d157150SStefano Zampini   Level: developer
41632d157150SStefano Zampini 
41642d157150SStefano Zampini   Note:
4165420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
41662d157150SStefano Zampini   It does not typically need to be called by the user.
41672d157150SStefano Zampini 
4168c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
41692d157150SStefano Zampini @*/
41702d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
41712d157150SStefano Zampini {
41722d157150SStefano Zampini   PetscFunctionBegin;
41732d157150SStefano Zampini   if (!snes->reason) {
41742d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
41752d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
41762d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
41772d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
41782d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
41792d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
41802d157150SStefano Zampini     }
41812d157150SStefano Zampini   }
41822d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
41832d157150SStefano Zampini }
41842d157150SStefano Zampini 
41852d157150SStefano Zampini /*@
41860b4b7b1cSBarry Smith   SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database
4187228d79bcSJed Brown 
4188c3339decSBarry Smith   Collective
4189228d79bcSJed Brown 
4190228d79bcSJed Brown   Input Parameters:
4191f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
41920b4b7b1cSBarry Smith . iter  - current iteration number
41930b4b7b1cSBarry Smith - rnorm - current relative norm of the residual
4194228d79bcSJed Brown 
4195dc4c0fb0SBarry Smith   Level: developer
4196dc4c0fb0SBarry Smith 
4197f6dfbefdSBarry Smith   Note:
4198420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
4199228d79bcSJed Brown   It does not typically need to be called by the user.
4200228d79bcSJed Brown 
42011cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4202228d79bcSJed Brown @*/
4203d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4204d71ae5a4SJacob Faibussowitsch {
42057a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
42067a03ce2fSLisandro Dalcin 
42077a03ce2fSLisandro Dalcin   PetscFunctionBegin;
42089566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
420948a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
42109566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
42113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42127a03ce2fSLisandro Dalcin }
42137a03ce2fSLisandro Dalcin 
42149b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
42159b94acceSBarry Smith 
4216bf388a1fSBarry Smith /*MC
4217f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4218bf388a1fSBarry Smith 
4219bf388a1fSBarry Smith      Synopsis:
4220aaa7dc30SBarry Smith      #include <petscsnes.h>
422137fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4222bf388a1fSBarry Smith 
4223c3339decSBarry Smith      Collective
42241843f636SBarry Smith 
42251843f636SBarry Smith     Input Parameters:
4226f6dfbefdSBarry Smith +    snes - the `SNES` context
4227bf388a1fSBarry Smith .    its - iteration number
4228bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
4229bf388a1fSBarry Smith -    mctx - [optional] monitoring context
4230bf388a1fSBarry Smith 
4231878cb397SSatish Balay    Level: advanced
4232878cb397SSatish Balay 
423356296ac4SStefano Zampini .seealso: [](ch_snes), `SNESMonitorSet()`
4234bf388a1fSBarry Smith M*/
4235bf388a1fSBarry Smith 
42369b94acceSBarry Smith /*@C
4237a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
42380b4b7b1cSBarry Smith   iteration of the `SNES` nonlinear solver to display the iteration's
42399b94acceSBarry Smith   progress.
42409b94acceSBarry Smith 
4241c3339decSBarry Smith   Logically Collective
4242fee21e36SBarry Smith 
4243c7afd0dbSLois Curfman McInnes   Input Parameters:
4244f6dfbefdSBarry Smith + snes           - the `SNES` context
424520f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4246420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
424749abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
42489b94acceSBarry Smith 
42499665c990SLois Curfman McInnes   Options Database Keys:
4250f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4251798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4252dc4c0fb0SBarry 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
4253c7afd0dbSLois Curfman McInnes                                 the options database.
42549665c990SLois Curfman McInnes 
4255dc4c0fb0SBarry Smith   Level: intermediate
4256dc4c0fb0SBarry Smith 
4257f6dfbefdSBarry Smith   Note:
42586bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4259f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
42606bc08f3fSLois Curfman McInnes   order in which they were set.
4261639f9d9dSBarry Smith 
4262420bcc1bSBarry Smith   Fortran Note:
4263f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4264025f1a04SBarry Smith 
426549abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn`
42669b94acceSBarry Smith @*/
426749abdd8aSBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy)
4268d71ae5a4SJacob Faibussowitsch {
42693a40ed3dSBarry Smith   PetscFunctionBegin;
42700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4271453a69bbSBarry Smith   for (PetscInt i = 0; i < snes->numbermonitors; i++) {
4272453a69bbSBarry Smith     PetscBool identical;
4273453a69bbSBarry Smith 
4274453a69bbSBarry Smith     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, mctx, monitordestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
42753ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4276649052a6SBarry Smith   }
42775f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
42786e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4279b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4280835f2295SStefano Zampini   snes->monitorcontext[snes->numbermonitors++] = mctx;
42813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42829b94acceSBarry Smith }
42839b94acceSBarry Smith 
4284a278d85bSSatish Balay /*@
4285f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
42865cd90555SBarry Smith 
4287c3339decSBarry Smith   Logically Collective
4288c7afd0dbSLois Curfman McInnes 
42892fe279fdSBarry Smith   Input Parameter:
4290f6dfbefdSBarry Smith . snes - the `SNES` context
42915cd90555SBarry Smith 
42921a480d89SAdministrator   Options Database Key:
4293a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4294dc4c0fb0SBarry Smith                          into a code by calls to `SNESMonitorSet()`, but does not cancel those
4295c7afd0dbSLois Curfman McInnes                          set via the options database
42965cd90555SBarry Smith 
4297dc4c0fb0SBarry Smith   Level: intermediate
4298dc4c0fb0SBarry Smith 
4299f6dfbefdSBarry Smith   Note:
4300f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
43015cd90555SBarry Smith 
430256296ac4SStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESMonitorDefault()`, `SNESMonitorSet()`
43035cd90555SBarry Smith @*/
4304d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4305d71ae5a4SJacob Faibussowitsch {
4306d952e501SBarry Smith   PetscInt i;
4307d952e501SBarry Smith 
43085cd90555SBarry Smith   PetscFunctionBegin;
43090700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4310d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
431148a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4312d952e501SBarry Smith   }
43135cd90555SBarry Smith   snes->numbermonitors = 0;
43143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43155cd90555SBarry Smith }
43165cd90555SBarry Smith 
4317bf388a1fSBarry Smith /*MC
4318bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4319bf388a1fSBarry Smith 
4320bf388a1fSBarry Smith      Synopsis:
4321aaa7dc30SBarry Smith      #include <petscsnes.h>
432237fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4323bf388a1fSBarry Smith 
4324c3339decSBarry Smith      Collective
43251843f636SBarry Smith 
43261843f636SBarry Smith     Input Parameters:
4327f6dfbefdSBarry Smith +    snes - the `SNES` context
4328bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4329bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4330bf388a1fSBarry Smith .    gnorm - 2-norm of current step
43311843f636SBarry Smith .    f - 2-norm of function
43321843f636SBarry Smith -    cctx - [optional] convergence context
43331843f636SBarry Smith 
43341843f636SBarry Smith     Output Parameter:
43351843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4336bf388a1fSBarry Smith 
4337878cb397SSatish Balay    Level: intermediate
4338bf388a1fSBarry Smith 
4339c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
4340bf388a1fSBarry Smith M*/
4341bf388a1fSBarry Smith 
43429b94acceSBarry Smith /*@C
43439b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
43449b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
43459b94acceSBarry Smith 
4346c3339decSBarry Smith   Logically Collective
4347fee21e36SBarry Smith 
4348c7afd0dbSLois Curfman McInnes   Input Parameters:
4349f6dfbefdSBarry Smith + snes                        - the `SNES` context
4350e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4351dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4352dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
43539b94acceSBarry Smith 
435436851e7fSLois Curfman McInnes   Level: advanced
435536851e7fSLois Curfman McInnes 
43561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
43579b94acceSBarry Smith @*/
4358*12651944SBarry Smith PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscCtxDestroyFn *destroy)
4359d71ae5a4SJacob Faibussowitsch {
43603a40ed3dSBarry Smith   PetscFunctionBegin;
43610700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4362e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
4363*12651944SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(&snes->cnvP));
4364bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
43657f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
436685385478SLisandro Dalcin   snes->cnvP                  = cctx;
43673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43689b94acceSBarry Smith }
43699b94acceSBarry Smith 
437052baeb72SSatish Balay /*@
43710b4b7b1cSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation
4372184914b5SBarry Smith 
4373184914b5SBarry Smith   Not Collective
4374184914b5SBarry Smith 
4375184914b5SBarry Smith   Input Parameter:
4376f6dfbefdSBarry Smith . snes - the `SNES` context
4377184914b5SBarry Smith 
4378184914b5SBarry Smith   Output Parameter:
4379f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4380184914b5SBarry Smith 
4381f6dfbefdSBarry Smith   Options Database Key:
43826a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
43836a4d7782SBarry Smith 
4384184914b5SBarry Smith   Level: intermediate
4385184914b5SBarry Smith 
4386f6dfbefdSBarry Smith   Note:
4387f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4388184914b5SBarry Smith 
43891cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4390184914b5SBarry Smith @*/
4391d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4392d71ae5a4SJacob Faibussowitsch {
4393184914b5SBarry Smith   PetscFunctionBegin;
43940700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43954f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4396184914b5SBarry Smith   *reason = snes->reason;
43973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4398184914b5SBarry Smith }
4399184914b5SBarry Smith 
4400c4421ceaSFande Kong /*@C
4401f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4402c4421ceaSFande Kong 
4403c4421ceaSFande Kong   Not Collective
4404c4421ceaSFande Kong 
4405c4421ceaSFande Kong   Input Parameter:
4406f6dfbefdSBarry Smith . snes - the `SNES` context
4407c4421ceaSFande Kong 
4408c4421ceaSFande Kong   Output Parameter:
4409dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4410c4421ceaSFande Kong 
441199c90e12SSatish Balay   Level: beginner
4412c4421ceaSFande Kong 
44131cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4414c4421ceaSFande Kong @*/
4415d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4416d71ae5a4SJacob Faibussowitsch {
4417c4421ceaSFande Kong   PetscFunctionBegin;
4418c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44194f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4420c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
44213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4422c4421ceaSFande Kong }
4423c4421ceaSFande Kong 
442433866048SMatthew G. Knepley /*@
4425f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
442633866048SMatthew G. Knepley 
442733866048SMatthew G. Knepley   Not Collective
442833866048SMatthew G. Knepley 
442933866048SMatthew G. Knepley   Input Parameters:
4430f6dfbefdSBarry Smith + snes   - the `SNES` context
4431f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
443233866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
443333866048SMatthew G. Knepley 
4434f6dfbefdSBarry Smith   Level: developer
4435f6dfbefdSBarry Smith 
4436420bcc1bSBarry Smith   Developer Note:
4437f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
443833866048SMatthew G. Knepley 
44391cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
444033866048SMatthew G. Knepley @*/
4441d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4442d71ae5a4SJacob Faibussowitsch {
444333866048SMatthew G. Knepley   PetscFunctionBegin;
444433866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44455f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
444633866048SMatthew G. Knepley   snes->reason = reason;
44473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
444833866048SMatthew G. Knepley }
444933866048SMatthew G. Knepley 
4450c9005455SLois Curfman McInnes /*@
4451420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4452c9005455SLois Curfman McInnes 
4453c3339decSBarry Smith   Logically Collective
4454fee21e36SBarry Smith 
4455c7afd0dbSLois Curfman McInnes   Input Parameters:
4456f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
44578c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4458cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4459420bcc1bSBarry Smith . na    - size of `a` and `its`
4460f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4461758f92a0SBarry Smith           else it continues storing new values for new nonlinear solves after the old ones
4462c7afd0dbSLois Curfman McInnes 
4463dc4c0fb0SBarry Smith   Level: intermediate
4464dc4c0fb0SBarry Smith 
4465308dcc3eSBarry Smith   Notes:
4466ce78bad3SBarry 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
446777e5a1f9SBarry Smith   default array of length 1,000 is allocated.
4468308dcc3eSBarry Smith 
4469c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4470c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4471c9005455SLois Curfman McInnes   during the section of code that is being timed.
4472c9005455SLois Curfman McInnes 
4473420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4474420bcc1bSBarry Smith 
44751cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4476c9005455SLois Curfman McInnes @*/
4477d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4478d71ae5a4SJacob Faibussowitsch {
44793a40ed3dSBarry Smith   PetscFunctionBegin;
44800700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44814f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
44824f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
44837a1ec6d4SBarry Smith   if (!a) {
448477e5a1f9SBarry Smith     if (na == PETSC_DECIDE) na = 1000;
44859566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4486071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4487308dcc3eSBarry Smith   }
4488c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4489758f92a0SBarry Smith   snes->conv_hist_its   = its;
4490115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4491a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4492758f92a0SBarry Smith   snes->conv_hist_reset = reset;
44933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4494758f92a0SBarry Smith }
4495758f92a0SBarry Smith 
4496d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4497c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4498c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
449999e0435eSBarry Smith 
4500d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4501d71ae5a4SJacob Faibussowitsch {
4502308dcc3eSBarry Smith   mxArray   *mat;
4503308dcc3eSBarry Smith   PetscInt   i;
4504308dcc3eSBarry Smith   PetscReal *ar;
4505308dcc3eSBarry Smith 
4506308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4507308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4508f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
450911cc89d2SBarry Smith   return mat;
4510308dcc3eSBarry Smith }
4511308dcc3eSBarry Smith #endif
4512308dcc3eSBarry Smith 
45130c4c9dddSBarry Smith /*@C
4514420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4515758f92a0SBarry Smith 
45163f9fe445SBarry Smith   Not Collective
4517758f92a0SBarry Smith 
4518758f92a0SBarry Smith   Input Parameter:
4519f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4520758f92a0SBarry Smith 
4521758f92a0SBarry Smith   Output Parameters:
4522f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4523758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4524758f92a0SBarry Smith          negative if not converged) for each solve.
452520f4b53cSBarry Smith - na  - size of `a` and `its`
4526758f92a0SBarry Smith 
4527dc4c0fb0SBarry Smith   Level: intermediate
4528dc4c0fb0SBarry Smith 
452920f4b53cSBarry Smith   Note:
453020f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
453120f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
453220f4b53cSBarry Smith   during the section of code that is being timed.
453320f4b53cSBarry Smith 
4534ce78bad3SBarry Smith   Fortran Notes:
4535ce78bad3SBarry Smith   Return the arrays with ``SNESRestoreConvergenceHistory()`
4536ce78bad3SBarry Smith 
4537ce78bad3SBarry Smith   Use the arguments
4538dc4c0fb0SBarry Smith .vb
4539ce78bad3SBarry Smith   PetscReal, pointer :: a(:)
4540ce78bad3SBarry Smith   PetscInt, pointer :: its(:)
4541dc4c0fb0SBarry Smith .ve
4542758f92a0SBarry Smith 
45431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4544758f92a0SBarry Smith @*/
4545d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4546d71ae5a4SJacob Faibussowitsch {
4547758f92a0SBarry Smith   PetscFunctionBegin;
45480700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4549758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4550758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4551115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
45523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4553c9005455SLois Curfman McInnes }
4554c9005455SLois Curfman McInnes 
4555ac226902SBarry Smith /*@C
455676b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4557eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
455853e5d35bSStefano Zampini   it is called just before the Jacobian is "evaluated" and after the function
455953e5d35bSStefano Zampini   evaluation.
456076b2cf59SMatthew Knepley 
4561c3339decSBarry Smith   Logically Collective
456276b2cf59SMatthew Knepley 
456376b2cf59SMatthew Knepley   Input Parameters:
4564a2b725a8SWilliam Gropp + snes - The nonlinear solver context
456553e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn`
456676b2cf59SMatthew Knepley 
4567fe97e370SBarry Smith   Level: advanced
4568fe97e370SBarry Smith 
4569420bcc1bSBarry Smith   Notes:
4570f6dfbefdSBarry 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
4571f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
457253e5d35bSStefano Zampini   This is not used by most users, and it is intended to provide a general hook that is run
457353e5d35bSStefano Zampini   right before the direction step is computed.
4574ce78bad3SBarry Smith 
457553e5d35bSStefano Zampini   Users are free to modify the current residual vector,
457653e5d35bSStefano Zampini   the current linearization point, or any other vector associated to the specific solver used.
457753e5d35bSStefano Zampini   If such modifications take place, it is the user responsibility to update all the relevant
4578ce78bad3SBarry Smith   vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like
4579ce78bad3SBarry Smith .vb
4580ce78bad3SBarry Smith   PetscErrorCode update(SNES snes, PetscInt iteration)
4581ce78bad3SBarry Smith   {
4582ce78bad3SBarry Smith     PetscFunctionBeginUser;
4583ce78bad3SBarry Smith     if (iteration > 0) {
4584ce78bad3SBarry Smith       // update the model parameters here
4585ce78bad3SBarry Smith       Vec x,f;
4586ce78bad3SBarry Smith       PetscCall(SNESGetSolution(snes,&x));
4587ce78bad3SBarry Smith       PetcCall(SNESGetFunction(snes,&f,NULL,NULL));
4588ce78bad3SBarry Smith       PetscCall(SNESComputeFunction(snes,x,f));
4589ce78bad3SBarry Smith     }
4590ce78bad3SBarry Smith     PetscFunctionReturn(PETSC_SUCCESS);
4591ce78bad3SBarry Smith   }
4592ce78bad3SBarry Smith .ve
459376b2cf59SMatthew Knepley 
4594aaa8cc7dSPierre 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.
45956b7fb656SBarry Smith 
4596e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
459753e5d35bSStefano Zampini          `SNESMonitorSet()`
459876b2cf59SMatthew Knepley @*/
459953e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4600d71ae5a4SJacob Faibussowitsch {
460176b2cf59SMatthew Knepley   PetscFunctionBegin;
46020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4603e7788613SBarry Smith   snes->ops->update = func;
46043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
460576b2cf59SMatthew Knepley }
460676b2cf59SMatthew Knepley 
4607ffeef943SBarry Smith /*@
4608f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
46092a359c20SBarry Smith 
4610c3339decSBarry Smith   Collective
46112a359c20SBarry Smith 
4612e4094ef1SJacob Faibussowitsch   Input Parameters:
4613f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
46142a359c20SBarry Smith - viewer - the viewer to display the reason
46152a359c20SBarry Smith 
46162a359c20SBarry Smith   Options Database Keys:
4617ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4618ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4619eafd5ff0SAlex Lindsay 
4620420bcc1bSBarry Smith   Level: beginner
4621420bcc1bSBarry Smith 
4622f6dfbefdSBarry Smith   Note:
4623f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4624f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
46252a359c20SBarry Smith 
46261cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4627f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4628f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4629db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
46302a359c20SBarry Smith @*/
4631d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4632d71ae5a4SJacob Faibussowitsch {
463375cca76cSMatthew G. Knepley   PetscViewerFormat format;
46342a359c20SBarry Smith   PetscBool         isAscii;
46352a359c20SBarry Smith 
46362a359c20SBarry Smith   PetscFunctionBegin;
463719a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
46389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
46392a359c20SBarry Smith   if (isAscii) {
46409566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
464165bf60d2SBarry Smith     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
464275cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
464375cca76cSMatthew G. Knepley       DM       dm;
464475cca76cSMatthew G. Knepley       Vec      u;
464575cca76cSMatthew G. Knepley       PetscDS  prob;
464675cca76cSMatthew G. Knepley       PetscInt Nf, f;
464795cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
464895cbbfd3SMatthew G. Knepley       void    **exactCtx;
464975cca76cSMatthew G. Knepley       PetscReal error;
465075cca76cSMatthew G. Knepley 
46519566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
46529566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
46539566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
46549566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
46559566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
46569566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
46579566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
46589566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
46599566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
466063a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
466175cca76cSMatthew G. Knepley     }
4662eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
46632a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
466463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
46652a359c20SBarry Smith       } else {
466663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46672a359c20SBarry Smith       }
4668eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
46692a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
467063a3b9bcSJacob 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));
46712a359c20SBarry Smith       } else {
467263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46732a359c20SBarry Smith       }
46742a359c20SBarry Smith     }
467565bf60d2SBarry Smith     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
46762a359c20SBarry Smith   }
46773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46782a359c20SBarry Smith }
46792a359c20SBarry Smith 
4680c4421ceaSFande Kong /*@C
4681c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4682aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4683c4421ceaSFande Kong 
4684c3339decSBarry Smith   Logically Collective
4685c4421ceaSFande Kong 
4686c4421ceaSFande Kong   Input Parameters:
4687f6dfbefdSBarry Smith + snes              - the `SNES` context
4688420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4689420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
469049abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
4691420bcc1bSBarry Smith 
4692420bcc1bSBarry Smith   Calling sequence of `f`:
4693420bcc1bSBarry Smith + snes - the `SNES` context
469449abdd8aSBarry Smith - vctx - [optional] context for private data for the function
4695c4421ceaSFande Kong 
4696c4421ceaSFande Kong   Options Database Keys:
4697f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4698420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4699420bcc1bSBarry Smith                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4700c4421ceaSFande Kong 
4701dc4c0fb0SBarry Smith   Level: intermediate
4702dc4c0fb0SBarry Smith 
4703f6dfbefdSBarry Smith   Note:
4704c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4705f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4706c4421ceaSFande Kong   order in which they were set.
4707c4421ceaSFande Kong 
470849abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`,
470949abdd8aSBarry Smith           `PetscCtxDestroyFn`
4710c4421ceaSFande Kong @*/
471149abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy)
4712d71ae5a4SJacob Faibussowitsch {
4713c4421ceaSFande Kong   PetscFunctionBegin;
4714c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4715453a69bbSBarry Smith   for (PetscInt i = 0; i < snes->numberreasonviews; i++) {
4716453a69bbSBarry Smith     PetscBool identical;
4717453a69bbSBarry Smith 
4718453a69bbSBarry Smith     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
47193ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4720c4421ceaSFande Kong   }
47215f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4722c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4723c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4724835f2295SStefano Zampini   snes->reasonviewcontext[snes->numberreasonviews++] = vctx;
47253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4726c4421ceaSFande Kong }
4727c4421ceaSFande Kong 
472891f3e32bSBarry Smith /*@
4729420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
47300b4b7b1cSBarry Smith   All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist.
47312a359c20SBarry Smith 
4732c3339decSBarry Smith   Collective
47332a359c20SBarry Smith 
47342fe279fdSBarry Smith   Input Parameter:
4735f6dfbefdSBarry Smith . snes - the `SNES` object
47362a359c20SBarry Smith 
4737f6dfbefdSBarry Smith   Level: advanced
47382a359c20SBarry Smith 
47391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4740f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
47412a359c20SBarry Smith @*/
4742d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4743d71ae5a4SJacob Faibussowitsch {
47442a359c20SBarry Smith   static PetscBool incall = PETSC_FALSE;
47452a359c20SBarry Smith 
47462a359c20SBarry Smith   PetscFunctionBegin;
47473ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
47482a359c20SBarry Smith   incall = PETSC_TRUE;
4749c4421ceaSFande Kong 
4750c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
475136d43d94SBarry Smith   for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4752c4421ceaSFande Kong 
4753c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
475436d43d94SBarry Smith   if (snes->convergedreasonviewer) {
475536d43d94SBarry Smith     PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
475636d43d94SBarry Smith     PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
475736d43d94SBarry Smith     PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
47582a359c20SBarry Smith   }
47592a359c20SBarry Smith   incall = PETSC_FALSE;
47603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47612a359c20SBarry Smith }
47622a359c20SBarry Smith 
4763487a658cSBarry Smith /*@
47640b4b7b1cSBarry Smith   SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object
47659b94acceSBarry Smith 
4766c3339decSBarry Smith   Collective
4767c7afd0dbSLois Curfman McInnes 
4768b2002411SLois Curfman McInnes   Input Parameters:
4769f6dfbefdSBarry Smith + snes - the `SNES` context
47700b4b7b1cSBarry Smith . b    - the constant part of the equation $F(x) = b$, or `NULL` to use zero.
477185385478SLisandro Dalcin - x    - the solution vector.
47729b94acceSBarry Smith 
4773dc4c0fb0SBarry Smith   Level: beginner
4774dc4c0fb0SBarry Smith 
4775f6dfbefdSBarry Smith   Note:
4776420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4777a9b45538SStefano Zampini   for the nonlinear solve prior to calling `SNESSolve()` .
47788ddd3da0SLois Curfman McInnes 
47791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4780db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4781a9b45538SStefano Zampini           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
47829b94acceSBarry Smith @*/
4783d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4784d71ae5a4SJacob Faibussowitsch {
4785ace3abfcSBarry Smith   PetscBool flg;
4786efd51863SBarry Smith   PetscInt  grid;
47870298fd71SBarry Smith   Vec       xcreated = NULL;
4788caa4e7f2SJed Brown   DM        dm;
4789052efed2SBarry Smith 
47903a40ed3dSBarry Smith   PetscFunctionBegin;
47910700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4792a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4793a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
47940700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
479585385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
479685385478SLisandro Dalcin 
479734b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
479806fc46c8SMatthew G. Knepley   {
479906fc46c8SMatthew G. Knepley     PetscViewer       viewer;
480006fc46c8SMatthew G. Knepley     PetscViewerFormat format;
48017c88af5aSMatthew G. Knepley     PetscInt          num;
480206fc46c8SMatthew G. Knepley     PetscBool         flg;
480306fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
480406fc46c8SMatthew G. Knepley 
480506fc46c8SMatthew G. Knepley     if (!incall) {
480634b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
4807648c30bcSBarry Smith       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
480806fc46c8SMatthew G. Knepley       if (flg) {
480906fc46c8SMatthew G. Knepley         PetscConvEst conv;
481046079b62SMatthew G. Knepley         DM           dm;
481146079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
481246079b62SMatthew G. Knepley         PetscInt     Nf;
481306fc46c8SMatthew G. Knepley 
481406fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
48159566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
48169566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
48179566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
48189566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
48199566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
48209566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
48219566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
48229566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
48239566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
48249566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
48259566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4826648c30bcSBarry Smith         PetscCall(PetscViewerDestroy(&viewer));
48279566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
48289566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
482906fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
483006fc46c8SMatthew G. Knepley       }
483134b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4832b2588ea6SMatthew G. Knepley       num = 1;
48339566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
483434b4d3a8SMatthew G. Knepley       if (flg) {
483534b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
483634b4d3a8SMatthew G. Knepley 
483734b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
48389566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
48399566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48409566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48419566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48429566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
48439566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
48449566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
484534b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
484634b4d3a8SMatthew G. Knepley       }
48477c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
48487c88af5aSMatthew G. Knepley       num = 0;
48499566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
48507c88af5aSMatthew G. Knepley       if (num) {
48517c88af5aSMatthew G. Knepley         DMAdaptor   adaptor;
4852e03fd340SMatthew G. Knepley         const char *prefix;
48537c88af5aSMatthew G. Knepley 
48547c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
48559566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4856e03fd340SMatthew G. Knepley         PetscCall(SNESGetOptionsPrefix(snes, &prefix));
4857e03fd340SMatthew G. Knepley         PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix));
48589566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48599566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48609566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48619566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
4862e5148a0bSMatthew G. Knepley         PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
48639566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
48649566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
48657c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
48667c88af5aSMatthew G. Knepley       }
486706fc46c8SMatthew G. Knepley     }
486806fc46c8SMatthew G. Knepley   }
4869ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4870caa4e7f2SJed Brown   if (!x) {
48719566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
48729566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4873a69afd8bSBarry Smith     x = xcreated;
4874a69afd8bSBarry Smith   }
48759566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4876f05ece33SBarry Smith 
48779566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4878efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
487985385478SLisandro Dalcin     /* set solution vector */
48809566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
48819566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
488285385478SLisandro Dalcin     snes->vec_sol = x;
48839566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4884caa4e7f2SJed Brown 
4885caa4e7f2SJed Brown     /* set affine vector if provided */
48869566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
48879566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
488885385478SLisandro Dalcin     snes->vec_rhs = b;
488985385478SLisandro Dalcin 
48905f80ce2aSJacob 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");
48915f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4892dd8e379bSPierre Jolivet     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4893aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
48949566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
48959566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
48963f149594SLisandro Dalcin 
48977eee914bSBarry Smith     if (!grid) {
48989927e4dfSBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4899dd568438SSatish Balay     }
4900d25893d9SBarry Smith 
4901abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
490212b1dd1aSStefano Zampini     PetscCall(SNESResetCounters(snes));
49032d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
49049566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4905dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
49069566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
49072d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4908422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
49093f149594SLisandro Dalcin 
491037ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
491137ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
491237ec4e1aSPeter Brune 
4913648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
49149566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4915c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
49169566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
49175968eb51SBarry Smith 
49181b3000acSStefano Zampini     if (snes->errorifnotconverged) {
49191b3000acSStefano Zampini       if (snes->reason < 0) PetscCall(SNESMonitorCancel(snes));
49201b3000acSStefano Zampini       PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
49211b3000acSStefano Zampini     }
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